mirror of https://github.com/nymea/nymea.git
439 lines
21 KiB
Python
Executable File
439 lines
21 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# -*- coding: UTF-8 -*-
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
# #
|
|
# Copyright (C) 2015-2017 Simon Stuerz <simon.stuerz@guh.io> #
|
|
# Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> #
|
|
# #
|
|
# This file is part of guh. #
|
|
# #
|
|
# guh is free software: you can redistribute it and/or modify #
|
|
# it under the terms of the GNU General Public License as published by #
|
|
# the Free Software Foundation, version 2 of the License. #
|
|
# #
|
|
# guh is distributed in the hope that it will be useful, #
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
|
# GNU General Public License for more details. #
|
|
# #
|
|
# You should have received a copy of the GNU General Public License #
|
|
# along with guh. If not, see <http://www.gnu.org/licenses/>. #
|
|
# #
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
|
|
|
import argparse
|
|
import traceback
|
|
import json
|
|
import os
|
|
import subprocess
|
|
|
|
__version__='1.0.1'
|
|
|
|
##################################################################################################################
|
|
# Methods
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def printInfo(info):
|
|
if args.filetype is 'i':
|
|
print(info)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def printWarning(warning):
|
|
print('Warning: ' + warning)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def printError(error):
|
|
print('Error: ' + error)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def writeToFile(line):
|
|
outputFile.write('%s\n' % line)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractPlugin(pluginMap):
|
|
variableName = 'pluginId'
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define PluginId pluginId = %s' % (pluginMap['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('PluginId pluginId = PluginId(\"%s\");' % (pluginMap['id']))
|
|
addTranslationString(pluginMap['name'], 'The name of the plugin %s (%s)' % (pluginMap['name'], pluginMap['id']))
|
|
createExternDefinition('PluginId', variableName)
|
|
|
|
if 'paramTypes' in pluginMap:
|
|
extractParamTypes(pluginMap['paramTypes'], pluginMap['name'])
|
|
|
|
if 'vendors' in pluginMap:
|
|
extractVendors(pluginMap['vendors'])
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractParamTypes(paramTypes, contextName):
|
|
for paramType in paramTypes:
|
|
try:
|
|
variableName = '%sParamTypeId' % (contextName + paramType['name'][0].capitalize() + paramType['name'][1:])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define ParamTypeId %s = %s' % (variableName, paramType['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('ParamTypeId %s = ParamTypeId(\"%s\");' % (variableName, paramType['id']))
|
|
addTranslationString(paramType['displayName'], 'The name of the paramType (%s) of %s' % (paramType['id'], contextName))
|
|
createExternDefinition('ParamTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for ParamTypeId %s -> skipping' % (variableName, paramType['id']))
|
|
except:
|
|
pass
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractVendors(vendors):
|
|
for vendor in vendors:
|
|
try:
|
|
variableName = '%sVendorId' % (vendor['name'])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define VendorId %s = %s' % (variableName, vendor['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('VendorId %s = VendorId(\"%s\");' % (variableName, vendor['id']))
|
|
addTranslationString(vendor['displayName'], 'The name of the vendor (%s)' % vendor['id'])
|
|
createExternDefinition('VendorId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for VendorId %s -> skipping' % (variableName, param['id']))
|
|
except:
|
|
pass
|
|
|
|
if 'deviceClasses' in vendor:
|
|
extractDeviceClasses(vendor['deviceClasses'])
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractDeviceClasses(deviceClasses):
|
|
for deviceClass in deviceClasses:
|
|
try:
|
|
variableName = '%sDeviceClassId' % (deviceClass['name'])
|
|
|
|
if 'pairingInfo' in deviceClass:
|
|
addTranslationString(deviceClass['pairingInfo'], 'The pairing info of deviceClass %s' % deviceClass['name'])
|
|
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define DeviceClassId %s = %s' % (variableName, deviceClass['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('DeviceClassId %s = DeviceClassId(\"%s\");' % (variableName, deviceClass['id']))
|
|
addTranslationString(deviceClass['displayName'], 'The name of the DeviceClass (%s)' %(deviceClass['id']))
|
|
createExternDefinition('DeviceClassId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for DeviceClassId %s -> skipping' % (variableName, deviceClass['deviceClassId']))
|
|
|
|
except:
|
|
pass
|
|
|
|
if 'paramTypes' in deviceClass:
|
|
extractParamTypes(deviceClass['paramTypes'], deviceClass['name'])
|
|
|
|
if 'discoveryParamTypes' in deviceClass:
|
|
extractParamTypes(deviceClass['discoveryParamTypes'], deviceClass['name'])
|
|
|
|
if 'stateTypes' in deviceClass:
|
|
extractStateTypes(deviceClass['stateTypes'], deviceClass['name'])
|
|
|
|
if 'actionTypes' in deviceClass:
|
|
extractActionTypes(deviceClass['actionTypes'], deviceClass['name'])
|
|
|
|
if 'eventTypes' in deviceClass:
|
|
extractEventTypes(deviceClass['eventTypes'], deviceClass['name'])
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractStateTypes(stateTypes, deviceClassName):
|
|
for stateType in stateTypes:
|
|
try:
|
|
# Define StateType
|
|
variableName = '%s%sStateTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
|
#addTranslationString(stateType['name'], 'The name of the stateType (%s) of DeviceClass %s' % (stateType['id'], deviceClassName))
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define StateTypeId %s = %s' % (variableName, stateType['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('StateTypeId %s = StateTypeId(\"%s\");' % (variableName, stateType['id']))
|
|
createExternDefinition('StateTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for StateTypeId %s -> skipping' % (variableName, stateType['id']))
|
|
|
|
# Create EventTypeId for this state
|
|
variableName = '%s%sEventTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
|
if not variableName in variableNames:
|
|
addTranslationString(stateType['displayNameEvent'], 'The name of the autocreated EventType (%s)' % stateType['id'])
|
|
variableNames.append(variableName)
|
|
printInfo('Define EventTypeId %s = %s' % (variableName, stateType['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('EventTypeId %s = EventTypeId(\"%s\");' % (variableName, stateType['id']))
|
|
createExternDefinition('EventTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for autocreated EventTypeId %s -> skipping' % (variableName, stateType['id']))
|
|
|
|
#ParamType for EventType/ActionType
|
|
variableName = '%s%sStateParamTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define ParamTypeId %s for StateType %s = %s' % (variableName, variableName, stateType['id']))
|
|
if args.filetype is 'i':
|
|
writeToFile('ParamTypeId %s = ParamTypeId(\"%s\");' % (variableName, stateType['id']))
|
|
createExternDefinition('ParamTypeId', variableName)
|
|
addTranslationString(stateType['name'], 'The name of the ParamType of StateType (%s) of DeviceClass %s' % (stateType['id'], deviceClassName))
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for ParamTypeId %s -> skipping' % (variableName, stateType['id']))
|
|
|
|
# Create ActionTypeId if the state is writable
|
|
if 'writable' in stateType and stateType['writable']:
|
|
variableName = '%s%sActionTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
printInfo('Define ActionTypeId for writable StateType %s = %s' % (variableName, stateType['id']))
|
|
addTranslationString(stateType['displayNameAction'], 'The name of the autocreated ActionType (%s)' % stateType['id'])
|
|
if args.filetype is 'i':
|
|
writeToFile('ActionTypeId %s = ActionTypeId(\"%s\");' % (variableName, stateType['id']))
|
|
createExternDefinition('ActionTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for autocreated ActionTypeId %s -> skipping' % (variableName, stateType['id']))
|
|
|
|
except:
|
|
pass
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractActionTypes(actionTypes, deviceClassName):
|
|
for actionType in actionTypes:
|
|
try:
|
|
# Define ActionTypeId
|
|
variableName = '%s%sActionTypeId' % (deviceClassName, actionType['name'][0].capitalize() + actionType['name'][1:])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
addTranslationString(actionType['displayName'], 'The name of the ActionType %s of deviceClass %s' % (actionType['id'], deviceClassName))
|
|
if args.filetype is 'i':
|
|
writeToFile('ActionTypeId %s = ActionTypeId(\"%s\");' % (variableName, actionType['id']))
|
|
createExternDefinition('ActionTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for ActionTypeId %s -> skipping' % (variableName, actionType['id']))
|
|
|
|
except:
|
|
pass
|
|
|
|
# Define paramTypes of this ActionType
|
|
if 'paramTypes' in actionType:
|
|
extractParamTypes(actionType['paramTypes'], deviceClassName)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def extractEventTypes(eventTypes, deviceClassName):
|
|
for eventType in eventTypes:
|
|
try:
|
|
# Define EventTypeId
|
|
variableName = '%s%sEventTypeId' % (deviceClassName, eventType['name'][0].capitalize() + eventType['name'][1:])
|
|
if not variableName in variableNames:
|
|
variableNames.append(variableName)
|
|
addTranslationString(eventType['displayName'], 'The name of the EventType %s of deviceClass %s' % (eventType['id'], deviceClassName))
|
|
if args.filetype is 'i':
|
|
writeToFile('EventTypeId %s = EventTypeId(\"%s\");' % (variableName, eventType['id']))
|
|
createExternDefinition('EventTypeId', variableName)
|
|
else:
|
|
printWarning('Duplicated variable name \"%s\" for EventTypeId %s -> skipping' % (variableName, eventType['id']))
|
|
except:
|
|
pass
|
|
|
|
# Define paramTypes of this EventType
|
|
if 'paramTypes' in eventType:
|
|
extractParamTypes(eventType['paramTypes'], deviceClassName)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def createExternDefinition(type, name):
|
|
definition = {}
|
|
definition['type'] = type
|
|
definition['variable'] = name
|
|
externDefinitions.append(definition)
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def addTranslationString(string, comment):
|
|
translationStrings.append([string, comment])
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def writeTranslationStrings():
|
|
if len(translationStrings) is not 0:
|
|
writeToFile('// Translation strings')
|
|
writeToFile('const QString translations[] {')
|
|
|
|
for index, value in enumerate(translationStrings):
|
|
writeToFile(' //: %s' % value[1])
|
|
if index != len(translationStrings) - 1:
|
|
writeToFile(' QT_TRANSLATE_NOOP(\"%s\", \"%s\"), \n' % (pluginMap['name'], value[0]))
|
|
else:
|
|
writeToFile(' QT_TRANSLATE_NOOP(\"%s\", \"%s\")' % (pluginMap['name'], value[0]))
|
|
|
|
writeToFile('};')
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def createTranslationFiles():
|
|
for translation in args.translations:
|
|
translationFile = (sourceDir + '/' + translation)
|
|
path, fileName = os.path.split(translationFile)
|
|
translationOutput = (path + '/' + pluginMap['id'] + '-' + os.path.splitext(fileName)[0] + '.qm')
|
|
printInfo(' --> Translation update %s' % translationFile)
|
|
printInfo(subprocess.check_output(['mkdir', '-p', path]))
|
|
printInfo(subprocess.check_output(['lupdate', '-recursive', '-no-obsolete', sourceDir, (args.builddir + '/' + args.output), '-ts', translationFile]))
|
|
printInfo(' --> Translation release %s' % translationOutput)
|
|
printInfo(subprocess.check_output(['lrelease', translationFile, '-qm', translationOutput]))
|
|
printInfo(' --> Copy translation files to build dir %s' % args.builddir + '/translations/')
|
|
subprocess.check_output(['rsync', '-a', translationOutput, args.builddir + '/translations/'])
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def writePluginInfoFile():
|
|
print(' --> Generate plugininfo.h for plugin \"%s\" = %s' % (pluginMap['name'], pluginMap['id']))
|
|
|
|
writeToFile('/* This file is generated by the guh build system. Any changes to this file will')
|
|
writeToFile(' * be lost.')
|
|
writeToFile(' *')
|
|
writeToFile(' * If you want to change this file, edit the plugin\'s json file.')
|
|
writeToFile(' */')
|
|
writeToFile('')
|
|
writeToFile('#ifndef PLUGININFO_H')
|
|
writeToFile('#define PLUGININFO_H')
|
|
writeToFile('')
|
|
writeToFile('#include <QLoggingCategory>')
|
|
writeToFile('#include <QObject>')
|
|
writeToFile('')
|
|
writeToFile('#include \"typeutils.h\"')
|
|
writeToFile('')
|
|
writeToFile('// Id definitions')
|
|
extractPlugin(pluginMap)
|
|
writeToFile('')
|
|
writeToFile('// Logging category')
|
|
|
|
if 'name' in pluginMap:
|
|
debugCategoryName = pluginMap['name'][0].capitalize() + pluginMap['name'][1:]
|
|
writeToFile('Q_DECLARE_LOGGING_CATEGORY(dc%s)' % debugCategoryName)
|
|
writeToFile('Q_LOGGING_CATEGORY(dc%s, \"%s\")' % (debugCategoryName, debugCategoryName))
|
|
printInfo('Define logging category: \'dc%s\'' % debugCategoryName)
|
|
|
|
writeToFile('')
|
|
|
|
# Write translation strings
|
|
writeTranslationStrings()
|
|
|
|
writeToFile('')
|
|
writeToFile('#endif // PLUGININFO_H')
|
|
outputFile.close()
|
|
print(' --> Generated successfully \"%s\"' % (args.output))
|
|
|
|
|
|
#-----------------------------------------------------------------------------------------------------------------
|
|
def writeExternPluginInfoFile():
|
|
print(' --> Generate extern-plugininfo.h for plugin \"%s\" = %s' % (pluginMap['name'], pluginMap['id']))
|
|
extractPlugin(pluginMap)
|
|
writeToFile('/* This file is generated by the guh build system. Any changes to this file will')
|
|
writeToFile(' * be lost.')
|
|
writeToFile(' *')
|
|
writeToFile(' * If you want to change this file, edit the plugin\'s json file.')
|
|
writeToFile(' */')
|
|
writeToFile('')
|
|
writeToFile('#ifndef EXTERNPLUGININFO_H')
|
|
writeToFile('#define EXTERNPLUGININFO_H')
|
|
writeToFile('#include \"typeutils.h\"')
|
|
writeToFile('#include <QLoggingCategory>')
|
|
writeToFile('')
|
|
writeToFile('// Id definitions')
|
|
|
|
for externDefinition in externDefinitions:
|
|
writeToFile('extern %s %s;' % (externDefinition['type'], externDefinition['variable']))
|
|
|
|
writeToFile('')
|
|
writeToFile('// Logging category definition')
|
|
|
|
if 'name' in pluginMap:
|
|
debugCategoryName = pluginMap['name'][0].capitalize() + pluginMap['name'][1:]
|
|
writeToFile('Q_DECLARE_LOGGING_CATEGORY(dc%s)' % debugCategoryName)
|
|
|
|
writeToFile('')
|
|
writeToFile('#endif // EXTERNPLUGININFO_H')
|
|
outputFile.close()
|
|
print(' --> Generated successfully \'%s\'' % (args.output))
|
|
|
|
|
|
##################################################################################################################
|
|
# Main
|
|
##################################################################################################################
|
|
|
|
if __name__ == '__main__':
|
|
# Argument parser
|
|
parser = argparse.ArgumentParser(description='The guh-generateplugininfo is a precompiler for building plugins. This precompiler will create a plugininfo.h containing the uuid definitions from the plugin json file and creates the translations for the plugin.')
|
|
parser.add_argument('-j', '--jsonfile', help='The JSON input file name with the plugin description', metavar='jsonfile', required=True)
|
|
parser.add_argument('-b', '--builddir', help='The path to the build directory of the plugin where the plugininfo.h file can be found.', metavar='buildpath', required=True)
|
|
parser.add_argument('-f', '--filetype', help='The file type to generate: e = extern infofile, i = infofile', action='store', choices=['e', 'i'], default='i')
|
|
parser.add_argument('-o', '--output', help='The plugininfo.h outputFile with the uuid declarations', metavar='output')
|
|
parser.add_argument('-t', '--translations', help='The translation files for the plugin.', nargs='*', type=str, metavar='*.ts')
|
|
parser.add_argument('-v', '--version', action='version', version=__version__)
|
|
args = parser.parse_args()
|
|
|
|
# Get the source directors
|
|
sourceDir = os.path.dirname(os.path.abspath(args.jsonfile))
|
|
|
|
# Print build information for debugging
|
|
printInfo('Json file: %s' % args.jsonfile)
|
|
printInfo('Output: %s/%s' % (args.builddir, args.output))
|
|
printInfo('Build directory: %s' % args.builddir)
|
|
printInfo('Source directory: %s' % sourceDir)
|
|
printInfo('Translations: %s' % args.translations)
|
|
printInfo('FileType: %s' % args.filetype)
|
|
|
|
# Tuple ('string to translate', 'comment for translater')
|
|
translationStrings = []
|
|
|
|
variableNames = []
|
|
externDefinitions = []
|
|
|
|
# Open files
|
|
try:
|
|
inputFile = open(args.jsonfile, 'r')
|
|
except:
|
|
printError('Could not open file \"%s\"' % (args.jsonfile))
|
|
exit -1
|
|
|
|
try:
|
|
outputFile = open(args.builddir + '/' + args.output, 'w')
|
|
except:
|
|
printError('Could not open file \"%s\"' % (args.jsonfile))
|
|
exit -1
|
|
|
|
# Read json file
|
|
try:
|
|
pluginMap = json.loads(inputFile.read())
|
|
inputFile.close()
|
|
except ValueError as error:
|
|
printError(' --> Could not load json input file \"%s\"' % (args.input))
|
|
printError(' %s' % (error))
|
|
inputFile.close()
|
|
exit -1
|
|
|
|
# Write files
|
|
if args.filetype is 'i':
|
|
writePluginInfoFile()
|
|
else:
|
|
writeExternPluginInfoFile()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|