2022-08-02 23:32:11 +03:00
# PrepareProject.py - инструмент для подготовки проекта к компиляции.
# Необходимо вызвать при изменении персональных настроек или состава модулей.
#
# При отсутствии файла с персональными настройками, myProfile.json будет создан автоматически
# python PrepareProject.py
#
# Если myProfile.json уже существует, можно запустить PrepareProject.py с параметром -u или --update для обновления списка модулей.
# Данная функция будет полезна для разработчиков при добавлении модуля в папку src/modules
# python PrepareProject.py --update
# python PrepareProject.py -u
#
# Возможно использовать несколько вариантов персональных настроек и уточнять имя файла при запуске с использованием параметра -p или -profile
# python PrepareProject.py --profile <ИмяФайла>
# python PrepareProject.py -p <ИмяФайла>
#
2022-11-13 20:44:31 +05:00
# поддерживаемые контроллеры (профили):
# esp8266_4mb
# esp32_4mb
# esp8266_1mb
# esp8266_1mb_ota
2022-08-02 23:32:11 +03:00
import configparser
import os , json , sys , getopt
from pathlib import Path
2022-10-05 20:42:34 +03:00
2022-08-02 23:32:11 +03:00
config = configparser . ConfigParser ( ) # создаём объекта парсера INI
def printHelp ( ) :
print ( ''' Usage:
PrepareProject . py
- p - - profile < file . json_in_root_folder >
- u - - update
- h - - help ''' )
def updateModulesInProfile ( profJson ) :
profJson [ " modules " ] = { }
2022-10-05 20:42:34 +03:00
for root , d_names , f_names in os . walk ( " src/modules " ) :
2022-08-02 23:32:11 +03:00
for fname in f_names :
if fname == " modinfo.json " :
2022-10-05 20:42:34 +03:00
with open ( os . path . join ( root , fname ) , " r " , encoding = ' utf-8 ' ) as read_file :
2022-08-02 23:32:11 +03:00
modinfoJson = json . load ( read_file )
# проверяем есть ли уже узловой элемент и если нет, то создаем
if not modinfoJson [ ' menuSection ' ] in profJson [ " modules " ] :
2022-08-11 23:20:16 +03:00
listFromFirstElement = { modinfoJson [ ' menuSection ' ] : [ ] }
listFromFirstElement . update ( profJson [ " modules " ] )
profJson [ " modules " ] = listFromFirstElement
2022-08-02 23:32:11 +03:00
# добавляем информацию о модуле в узловой элемент
profJson [ " modules " ] [ modinfoJson [ ' menuSection ' ] ] . append ( {
2022-10-05 20:42:34 +03:00
' path ' : os . path . normpath ( root ) . replace ( " \\ " , " / " ) ,
2022-08-02 23:32:11 +03:00
' active ' : modinfoJson [ ' defActive ' ]
} )
update = False # признак необходимости обновить список модулей
profile = ' myProfile.json ' # имя профиля. Будет заменено из консоли, если указано при старте
argv = sys . argv [ 1 : ]
try :
opts , args = getopt . getopt ( argv , ' hp:u ' , [ ' help ' , ' profile= ' , ' update ' ] )
except getopt . GetoptError :
print ( ' Ошибка обработки параметров! ' )
printHelp ( )
sys . exit ( 2 )
for opt , arg in opts :
if opt in ( " -h " , " --help " ) :
printHelp ( )
sys . exit ( )
elif opt in ( " -p " , " --profile " ) :
profile = arg
elif opt in ( " -u " , " --update " ) :
update = True
if Path ( profile ) . is_file ( ) :
# подтягиваем уже существующий профиль
with open ( profile , " r " , encoding = ' utf-8 ' ) as read_file :
profJson = json . load ( read_file )
# если хотим обновить список модулей в существующем профиле
if update :
2022-08-11 23:20:16 +03:00
updateModulesInProfile ( profJson )
# sortedListNames = sorted(profJson["modules"])
# sortedModules = {}
# for sortedModulName in sortedList:
2022-08-22 15:21:44 +03:00
# print(profJson)
2022-08-11 23:20:16 +03:00
2022-08-02 23:32:11 +03:00
with open ( profile , " w " , encoding = ' utf-8 ' ) as write_file :
json . dump ( profJson , write_file , ensure_ascii = False , indent = 4 , sort_keys = False )
else :
# если файла нет - создаем по образу настроек из проекта
profJson = json . loads ( ' {} ' )
# копируем параметры IOTM из settings.json в новый профиль
with open ( " data_svelte/settings.json " , " r " , encoding = ' utf-8 ' ) as read_file :
profJson [ ' iotmSettings ' ] = json . load ( read_file )
# устанавливаем параметры сборки
profJson [ ' projectProp ' ] = {
' platformio ' : {
2022-10-11 21:57:10 +03:00
' default_envs ' : ' esp8266_4mb '
2022-08-02 23:32:11 +03:00
}
}
# загружаем список модулей для сборки
updateModulesInProfile ( profJson )
# сохраняем новый профиль
with open ( profile , " w " , encoding = ' utf-8 ' ) as write_file :
json . dump ( profJson , write_file , ensure_ascii = False , indent = 4 , sort_keys = False )
2022-10-11 21:57:10 +03:00
# определяем какое устройство используется в профиле
deviceName = profJson [ ' projectProp ' ] [ ' platformio ' ] [ ' default_envs ' ]
# назначаем папку с файлами прошивки в зависимости от устройства и запоминаем в профиле
dataDir = ' data_svelte '
if deviceName == ' esp8266_1mb_ota ' :
dataDir = ' data_svelte_lite '
profJson [ ' projectProp ' ] = {
' platformio ' : {
' data_dir ' : dataDir
}
}
2022-08-02 23:32:11 +03:00
# генерируем файлы проекта на основе подготовленного профиля
# заполняем конфигурационный файл прошивки параметрами из профиля
2022-10-11 21:57:10 +03:00
with open ( dataDir + " /settings.json " , " r " , encoding = ' utf-8 ' ) as read_file :
2022-08-02 23:32:11 +03:00
iotmJson = json . load ( read_file )
for key , value in profJson [ ' iotmSettings ' ] . items ( ) :
iotmJson [ key ] = value
2022-10-11 21:57:10 +03:00
with open ( dataDir + " /settings.json " , " w " , encoding = ' utf-8 ' ) as write_file :
2022-08-02 23:32:11 +03:00
json . dump ( iotmJson , write_file , ensure_ascii = False , indent = 4 , sort_keys = False )
2022-10-11 21:57:10 +03:00
2022-08-02 23:32:11 +03:00
# собираем меню прошивки из модулей
# параллельно формируем список имен активных модулей
2022-10-11 21:57:10 +03:00
# параллельно собираем необходимые активным модулям библиотеки для включения в компиляцию для текущего типа устройства (esp8266_4m, esp32_4mb, esp8266_1m, esp8266_1m_ota)
2022-08-02 23:32:11 +03:00
activeModulesName = [ ] # список имен активных модулей
allLibs = " " # подборка всех библиотек необходимых модулям для дальнейшей записи в конфигурацию platformio
itemsCount = 1 ;
includeDirs = " " # подборка путей ко всем модулям для дальнейшей записи в конфигурацию platformio
itemsJson = json . loads ( ' [ { " name " : " Выберите элемент " , " num " : 0}] ' )
for section , modules in profJson [ ' modules ' ] . items ( ) :
itemsJson . append ( { " header " : section } )
for module in modules :
if module [ ' active ' ] :
2022-10-05 20:42:34 +03:00
with open ( module [ ' path ' ] + " /modinfo.json " , " r " , encoding = ' utf-8 ' ) as read_file :
2022-08-02 23:32:11 +03:00
moduleJson = json . load ( read_file )
2022-10-06 13:27:47 +03:00
if deviceName in moduleJson [ ' usedLibs ' ] : # проверяем поддерживает ли модуль текущее устройство
2022-08-02 23:32:11 +03:00
activeModulesName . append ( moduleJson [ ' about ' ] [ ' moduleName ' ] ) # запоминаем имена для использования на след шагах
2022-10-05 20:42:34 +03:00
includeDirs = includeDirs + " \n +< " + module [ ' path ' ] . replace ( " src/ " , " " ) + " > " # запоминаем пути к модулям для компиляции
2022-10-06 13:27:47 +03:00
for libPath in moduleJson [ ' usedLibs ' ] [ deviceName ] : # запоминаем библиотеки необходимые модулю для текущей платы
2022-08-02 23:32:11 +03:00
allLibs = allLibs + " \n " + libPath
for configItemsJson in moduleJson [ ' configItem ' ] :
configItemsJson [ ' num ' ] = itemsCount
configItemsJson [ ' name ' ] = str ( itemsCount ) + " . " + configItemsJson [ ' name ' ]
itemsCount = itemsCount + 1
itemsJson . append ( configItemsJson )
2022-10-11 21:57:10 +03:00
with open ( dataDir + " /items.json " , " w " , encoding = ' utf-8 ' ) as write_file :
2022-08-02 23:32:11 +03:00
json . dump ( itemsJson , write_file , ensure_ascii = False , indent = 4 , sort_keys = False )
# учитываем вызовы модулей в API.cpp
allAPI_head = " "
allAPI_exec = " "
for activModuleName in activeModulesName :
allAPI_head = allAPI_head + " \n void* getAPI_ " + activModuleName + " (String subtype, String params); "
allAPI_exec = allAPI_exec + " \n if ((tmpAPI = getAPI_ " + activModuleName + " (subtype, params)) != nullptr) return tmpAPI; "
apicpp = ' #include " ESPConfiguration.h " \n '
apicpp = apicpp + allAPI_head
apicpp = apicpp + ' \n \n void* getAPI(String subtype, String params) { \n void* tmpAPI; '
apicpp = apicpp + allAPI_exec
apicpp = apicpp + ' \n return nullptr; \n } '
with open ( ' src/modules/API.cpp ' , ' w ' ) as f :
f . write ( apicpp )
# корректируем параметры platformio
# собираем пути всех отключенных модулей для исключения их из процесса компиляции
# excludeDirs = ""
# for root,d_names,f_names in os.walk("src\\modules"):
# for fname in f_names:
# if fname == "modinfo.json":
# with open(root + "\\" + fname, "r", encoding='utf-8') as read_file:
# modinfoJson = json.load(read_file)
# if not modinfoJson['about']['moduleName'] in activeModulesName:
# excludeDirs = excludeDirs + "\n-<" + root.replace("src\\", "") + ">"
# фиксируем изменения в platformio.ini
config . clear ( )
config . read ( " platformio.ini " )
config [ " env: " + deviceName + " _fromitems " ] [ " lib_deps " ] = allLibs
config [ " env: " + deviceName + " _fromitems " ] [ " build_src_filter " ] = includeDirs
config [ " platformio " ] [ " default_envs " ] = deviceName
config [ " platformio " ] [ " data_dir " ] = profJson [ ' projectProp ' ] [ ' platformio ' ] [ ' data_dir ' ]
with open ( " platformio.ini " , ' w ' ) as configFile :
config . write ( configFile )
2022-10-05 20:42:34 +03:00
2022-08-22 15:21:44 +03:00
2022-10-05 20:42:34 +03:00
# import ctypes # An included library with Python install.
# if update:
# ctypes.windll.user32.MessageBoxW(0, "Модули профиля " + profile + " обновлены, а сам профиль применен, можно запускать компиляцию и прошивку.", "Операция завершена.", 0)
# else:
# ctypes.windll.user32.MessageBoxW(0, "Профиль " + profile + " применен, можно запускать компиляцию и прошивку.", "Операция завершена.", 0)
2022-08-22 15:21:44 +03:00
if update :
2022-10-05 20:42:34 +03:00
print ( f " \x1b [1;31;42m Модули профиля " + profile + " обновлены, а сам профиль применен, можно запускать компиляцию и прошивку. \x1b [0m " )
2022-08-22 15:21:44 +03:00
else :
2022-10-05 20:42:34 +03:00
print ( f " \x1b [1;31;42m Профиль " , profile , " применен, можно запускать компиляцию и прошивку. \x1b [0m " )
2022-08-02 23:32:11 +03:00
2022-10-05 20:42:34 +03:00
# print(f"\x1b[1;32;41m Операция завершена. \x1b[0m")
2022-08-02 23:32:11 +03:00