diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py index 2818138543a58a346ae023da2333713a1bb8da63..bece292aadb03beccb5138c9a2c72fa86fd15b2b 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/fesaTemplates.py @@ -490,6 +490,9 @@ cGetStringArrayReg = string.Template(""" cGetScalarReg = string.Template(""" pDevice->${fesaFieldName}.set( pPLCDevice->getRegister("${regName}")->getVal<${regType}>(), pContext);""") + +cGetCustomScalarReg = string.Template(""" + pDevice->${fesaFieldName}.set(static_cast<${enumName}::${enumName}>(pPLCDevice->getRegister("${regName}")->getVal<${regType}>()), pContext);""") cGetArrayReg = string.Template(""" { @@ -498,6 +501,19 @@ cGetArrayReg = string.Template(""" pDevice->${fesaFieldName}.set(pRegister->getRefArray<${regType}>(dim1), dim1, pContext); } """) +cGetCustomArrayReg = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1; + ${regType}* data = pRegister->getRefArray<${regType}>(dim1); + std::vector<${enumName}::${enumName}> ${regName}; + for(uint32_t i = 0; i < dim1; ++i) + { + ${regName}.push_back(static_cast<${enumName}::${enumName}>(*(data + i))); + } + pDevice->${fesaFieldName}.set(${regName}.data(), dim1, pContext); + } + """) cGetArray2DReg = string.Template(""" { auto& pRegister = pPLCDevice->getRegister("${regName}"); @@ -506,6 +522,20 @@ cGetArray2DReg = string.Template(""" pDevice->${fesaFieldName}.set(pRegister->getRefArray2D<${regType}>(dim1, dim2), dim1, dim2, pContext); } """) +cGetCustomArray2DReg = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1; + uint32_t dim2; + ${regType}* data = pRegister->getRefArray2D<${regType}>(dim1, dim2); + std::vector<${enumName}::${enumName}> ${regName}; + for(uint32_t i = 0; i < dim1 * dim2; ++i) + { + ${regName}.push_back(static_cast<${enumName}::${enumName}>(*(data + i))); + } + pDevice->${fesaFieldName}.set(${regName}.data(), dim1, dim2, pContext); + } +""") cGetUnsignedArray2DReg = string.Template(""" { auto& pRegister = pPLCDevice->getRegister("${regName}"); @@ -577,6 +607,17 @@ cSetArrayReg = string.Template(""" } """) +cSetCustomArrayReg = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1 = pRegister->getDimension1(); + uint32_t fesaDim1; + const ${enumName}::${enumName}* ${regName} = pDevice->${fesaFieldName}.get(fesaDim1${context}); + std::vector<${regType}> data(${regName}, ${regName} + dim1); + pRegister->setValArray<${regType}>(data.data(), dim1); + } + """) + cSetUnsignedArrayReg = string.Template(""" { auto& pRegister = pPLCDevice->getRegister("${regName}"); @@ -597,6 +638,18 @@ cSetArray2DReg = string.Template(""" pRegister->setValArray2D<${regType}>(pDevice->${fesaFieldName}.get(fesaDim1, fesaDim2${context}), dim1, dim2); } """) + +cSetCustomArray2DReg = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1 = pRegister->getDimension1(); + uint32_t dim2 = pRegister->getDimension2(); + uint32_t fesaDim1,fesaDim2; + const ${enumName}::${enumName}* ${regName} = pDevice->${fesaFieldName}.get(fesaDim1, fesaDim2${context}); + std::vector<${regType}> data(${regName}, ${regName} + dim1 * dim2); + pRegister->setValArray2D<${regType}>(data.data(), dim1, dim2); + } +""") cSetUnsignedArray2DReg = string.Template(""" { @@ -652,6 +705,19 @@ cSetUnsignedArrayRegData = string.Template(""" } """) +cSetCustomArrayRegData = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1 = pRegister->getDimension1(); + uint32_t fesaDim1; + const ${enumName}::${enumName}* ${regName}; + (data.is${fesaFieldName_upper}Available()) ? ${regName} = data.${fesaFieldName}.get(fesaDim1) : + ${regName} = pDevice->${fesaFieldName}.get(fesaDim1${context}); + std::vector<${regType}> data(${regName}, ${regName} + dim1); + pRegister->setValArray<${regType}>(data.data(), dim1); + } + """) + cSetArray2DRegData = string.Template(""" { auto& pRegister = pPLCDevice->getRegister("${regName}"); @@ -677,6 +743,20 @@ cSetUnsignedArray2DRegData = string.Template(""" } """) +cSetCustomArray2DRegData = string.Template(""" + { + auto& pRegister = pPLCDevice->getRegister("${regName}"); + uint32_t dim1 = pRegister->getDimension1(); + uint32_t dim2 = pRegister->getDimension2(); + uint32_t fesaDim1,fesaDim2; + const ${enumName}::${enumName}* ${regName}; + (data.is${fesaFieldName_upper}Available()) ? ${regName} = data.${fesaFieldName}.get(fesaDim1, fesaDim2) : + ${regName} = pDevice->${fesaFieldName}.get(fesaDim1, fesaDim2${context}); + std::vector<${regType}> data(${regName}, ${regName} + dim1 * dim2); + pRegister->setValArray2D<${regType}>(data.data(), dim1, dim2); + } +""") + makeDesign = """# Include SILECS makefile include Makefile.silecs @@ -797,6 +877,15 @@ def genCGetStringArrayReg(register): def genCGetScalarReg(register): return cGetScalarReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName()) +def genCGetCustomScalarReg(register): + return cGetCustomScalarReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), enumName=register.custom_type_name) + +def genCGetCustomArrayReg(register): + return cGetCustomArrayReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), enumName=register.custom_type_name) + +def genCGetCustomArray2DReg(register): + return cGetCustomArray2DReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), enumName=register.custom_type_name) + def genCGetArrayReg(register): if register.isUnsigned(): return cGetUnsignedArrayReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), fesaType=register.getFesaType()) @@ -853,6 +942,18 @@ def genCSetArray2DReg(register): return cSetUnsignedArray2DReg.substitute(regName=register.name, regType=register.getCType(), fesaType=register.getFesaType(), fesaFieldName=register.getFesaFieldName(), context=context) else: return cSetArray2DReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), context=context) + +def genCSetCustomArrayReg(register): + context = ", pContext" + if register.isConfiguration(): + context = "" + return cSetCustomArrayReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), context=context, enumName=register.custom_type_name) + +def genCSetCustomArray2DReg(register): + context = ", pContext" + if register.isConfiguration(): + context = "" + return cSetCustomArray2DReg.substitute(regName=register.name, regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), context=context, enumName=register.custom_type_name) def genCSetStringRegData(register): context = "pContext" @@ -884,6 +985,12 @@ def genCSetArrayRegData(register): else: return cSetArrayRegData.substitute(regName=register.name, fesaFieldName_upper=register.getFesaFieldNameCapitalized(), regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), context=context) +def genCSetCustomArrayRegData(register): + context = ", pContext" + if register.isConfiguration(): + context = "" + return cSetCustomArrayRegData.substitute(regName=register.name, fesaFieldName_upper=register.getFesaFieldNameCapitalized(), regType=register.getCType(), fesaType=register.getFesaType(), fesaFieldName=register.getFesaFieldName(), context=context, enumName=register.custom_type_name) + def genCSetArray2DRegData(register): context = ", pContext" if register.isConfiguration(): @@ -893,6 +1000,12 @@ def genCSetArray2DRegData(register): else: return cSetArray2DRegData.substitute(regName=register.name, fesaFieldName_upper=register.getFesaFieldNameCapitalized(), regType=register.getCType(), fesaFieldName=register.getFesaFieldName(), context=context) +def genCSetCustomArray2DRegData(register): + context = ", pContext" + if register.isConfiguration(): + context = "" + return cSetCustomArray2DRegData.substitute(regName=register.name, fesaFieldName_upper=register.getFesaFieldNameCapitalized(), regType=register.getCType(), fesaType=register.getFesaType(), fesaFieldName=register.getFesaFieldName(), context=context, enumName=register.custom_type_name) + def genMakeDesign(): return makeDesign diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py index 91f14a1ae6871e9795358267f8facf78eda42a34..0265392799274265c731f7001afd3bba33391c5d 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateFesaDesign.py @@ -87,8 +87,29 @@ class FESADesignGenerator3_0_0(object): fillAttributes(scalarNode, {'type': register.getFesaType()}) return scalarNode - def getOrCreateType(self,fieldNode,register): - if register.valueType == "scalar": + def getOrCreateCustomScalarType(self, fieldNode, register): + scalarNode = getOrCreateChildElement(fieldNode,'custom-type-scalar') + fillAttributes(scalarNode, {'data-type-name-ref': register.custom_type_name}) + return scalarNode + + def getOrCreateCustomArrayType(self,fieldNode,register): + arrayNode = getOrCreateChildElement(fieldNode,'custom-type-array') + fillAttributes(arrayNode, {'data-type-name-ref': register.custom_type_name}) + dimNode = getOrCreateChildElement(arrayNode,'dim') + dimNode.setContent(str(register.dim1)) + return arrayNode + + def getOrCreateCustom2DArrayType(self,fieldNode,register): + array2DNode = getOrCreateChildElement(fieldNode,'custom-type-array2D') + fillAttributes(array2DNode, {'data-type-name-ref': register.custom_type_name}) + dim1Node = getOrCreateChildElement(array2DNode,'dim1') + dim2Node = getOrCreateChildElement(array2DNode,'dim2') + dim1Node.setContent(str(register.dim1)) + dim2Node.setContent(str(register.dim2)) + return array2DNode + + def getOrCreateType(self,fieldNode, register): + if register.valueType == "scalar": return self.getOrCreateScalarType(fieldNode,register) elif register.valueType == "array": return self.getOrCreateArrayType(fieldNode,register) @@ -100,6 +121,12 @@ class FESADesignGenerator3_0_0(object): return self.getOrCreateStringArrayType(fieldNode,register) elif register.valueType == "stringArray2D": iecommon.logError('ERROR: In register '+register.name+' - 2D array of strings not supported in FESA.', True, {'errorlog': True}) + elif register.valueType == "custom-type-scalar": + return self.getOrCreateCustomScalarType(fieldNode, register) + elif register.valueType == "custom-type-array": + return self.getOrCreateCustomArrayType(fieldNode, register) + elif register.valueType == "custom-type-array2D": + return self.getOrCreateCustom2DArrayType(fieldNode, register) else: iecommon.logError('ERROR: Unknown data-type:' + register.valueType, True, {'errorlog': True}) return None diff --git a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py index 17913a76a5a18377268af730279b3de92ecee771..1652d43a48e4955ebea7f15226c81ce566294600 100644 --- a/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py +++ b/silecs-codegen/src/xml/fesa/fesa_3_0_0/generateSourceCode.py @@ -122,6 +122,13 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource += fesaTemplates.genCGetArrayReg(register) elif register.valueType == 'array2D': finalSource += fesaTemplates.genCGetArray2DReg(register) + elif register.valueType == 'custom-type-scalar': + finalSource += fesaTemplates.genCGetCustomScalarReg(register) + elif register.valueType == 'custom-type-array': + finalSource += fesaTemplates.genCGetCustomArrayReg(register) + elif register.valueType == 'custom-type-array2D': + finalSource += fesaTemplates.genCGetCustomArray2DReg(register) + finalSource += '\n }\n' if block.isWritable(): @@ -139,6 +146,12 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource += fesaTemplates.genCSetArrayReg(register) elif register.valueType == 'array2D': finalSource += fesaTemplates.genCSetArray2DReg(register) + elif register.valueType == 'custom-type-scalar': + finalSource += fesaTemplates.genCSetScalarReg(register) + elif register.valueType == 'custom-type-array': + finalSource += fesaTemplates.genCSetCustomArrayReg(register) + elif register.valueType == 'custom-type-array2D': + finalSource += fesaTemplates.genCSetCustomArray2DReg(register) finalSource += fesaTemplates.cSend finalSource += ' }\n' finalSource += fesaTemplates.genCDatatypeSet(block.name,block.getFesaName(), className) @@ -156,6 +169,12 @@ def genCppSource(className, silecsRoot, fesaRoot, sourcePath,logTopics): finalSource += fesaTemplates.genCSetArrayRegData(register) elif register.valueType == 'scalar': finalSource += fesaTemplates.genCSetScalarRegData(register) + elif register.valueType == 'custom-type-scalar': + finalSource += fesaTemplates.genCSetScalarRegData(register) + elif register.valueType == 'custom-type-array': + finalSource += fesaTemplates.genCSetCustomArrayRegData(register) + elif register.valueType == 'custom-type-array2D': + finalSource += fesaTemplates.genCSetCustomArray2DRegData(register) finalSource += fesaTemplates.cSend finalSource += '\n }\n' # closing bracket for block diff --git a/silecs-codegen/src/xml/fesa/fesa_7_3_0/generateFesaDesign.py b/silecs-codegen/src/xml/fesa/fesa_7_3_0/generateFesaDesign.py index 73dcf4238fc006ff71e1e304fab19185e0b61a23..0640a479d6aeee77c29505a50a543f7693cc2338 100644 --- a/silecs-codegen/src/xml/fesa/fesa_7_3_0/generateFesaDesign.py +++ b/silecs-codegen/src/xml/fesa/fesa_7_3_0/generateFesaDesign.py @@ -96,3 +96,42 @@ class FESADesignGenerator7_3_0(fesa.fesa_3_1_0.generateFesaDesign.FESADesignGene else: globalConfigurationNode = globalDataNode.xpathEval("configuration")[0] self.getOrCreatePLCClassVersionField(globalConfigurationNode,designClass.version) + + # Fill custom-types with enums. + enums = designClass.getEnums() + customTypesNode = doc.xpathEval('/equipment-model/custom-types')[0] + for enum in enums: + enumElement = getOrCreateNamedChildElement(customTypesNode, "enum", enum.name) + existing_items = enumElement.xpathEval("item") + to_add = [] + to_edit = [] + + # Loop through all new enums and check which should be added and which edited. + for item in enum.items: + if item.symbol in [item.prop("symbol") for item in existing_items]: + to_edit.append(item) + else: + to_add.append(item) + + # Loop though all existing enums and remove any which are not in new enums. + to_add_edit = to_add + to_edit + for existing in existing_items: + if existing.prop("symbol") not in [item.symbol for item in to_add_edit]: + existing.unlinkNode() + existing.freeNode() + + # Edit existing items. + for item in to_edit: + for existing in existing_items: + if existing.prop("symbol") != item.symbol: + continue + existing.setProp("access", item.access) + existing.setProp("value", item.value) + + # Add missing items. + for item in to_add: + itemElement = libxml2.newNode("item") + enumElement.addChild(itemElement) + itemElement.setProp("access", item.access) + itemElement.setProp("value", item.value) + itemElement.setProp("symbol", item.symbol) diff --git a/silecs-codegen/src/xml/genduwrapper.py b/silecs-codegen/src/xml/genduwrapper.py index 2034155aa8807c1b91bb3fa9724678dbf2d147a2..7e466b2707dbb667bd52abb86ed0250270dd8fe2 100644 --- a/silecs-codegen/src/xml/genduwrapper.py +++ b/silecs-codegen/src/xml/genduwrapper.py @@ -43,13 +43,13 @@ def genClassHeader(workspacePath, deploy, design, funcGetSilecsDesignFilePath, f classDeclarations += genduwrappertemplate.getBlockClass(block,registerInitializerList,registerGetterSetter,registersDimentionsDeclaration,registersDeclaration) blockGetters = "" - sendRecvBlocks = genduwrappertemplate.getDeviceSendRecvBlocks(designClass.getBlockNodes()) + sendRecvBlocks = genduwrappertemplate.getDeviceSendRecvBlocks(designClass.getBlockNodes(), designClass.customTypesXmlNode) for block in designClass.getDesignBlocks(): blockGetters += genduwrappertemplate.getDeviceBlockGetterSetter(block) classDeclarations += genduwrappertemplate.getDeviceClass(blockGetters,sendRecvBlocks) - sendRecvBlocks = genduwrappertemplate.getControllerSendRecvBlocks(designClass.getBlockNodes()) + sendRecvBlocks = genduwrappertemplate.getControllerSendRecvBlocks(designClass.getBlockNodes(), designClass.customTypesXmlNode) classDeclarations = genduwrappertemplate.getDesignClass(design.name, design.version) designWrapper = genduwrappertemplate.designFileTemplate.substitute({'designNameCapitalized' : iecommon.capitalizeString(design.name),'designNameUpper' : design.name.upper(),'classDeclarations' : classDeclarations}) diff --git a/silecs-codegen/src/xml/genduwrappertemplate.py b/silecs-codegen/src/xml/genduwrappertemplate.py index 8ee582d0ad6feec6ed355f2b0fee8e4937e83e84..083df069b5f786b27ec4f902ce5becb074a54947 100644 --- a/silecs-codegen/src/xml/genduwrappertemplate.py +++ b/silecs-codegen/src/xml/genduwrappertemplate.py @@ -337,10 +337,10 @@ controllerSendTemplate = string.Template("""\ """) -def getControllerSendRecvBlocks(blockList): +def getControllerSendRecvBlocks(blockList, customTypesXmlNode): text = "" for blockNode in blockList: - block = DesignBlock(blockNode) + block = DesignBlock(blockNode, customTypesXmlNode) map = {'blockName' : block.name, 'blockNameCapitalized' : block.getNameCapitalized()} if block.isReadable(): @@ -500,10 +500,10 @@ deviceSendTemplate = string.Template("""\ """) -def getDeviceSendRecvBlocks(blockList): +def getDeviceSendRecvBlocks(blockList, customTypesXmlNode): text = "" for blockNode in blockList: - block = DesignBlock(blockNode) + block = DesignBlock(blockNode, customTypesXmlNode) map = {'blockName' : block.name, 'blockNameCapitalized' : block.getNameCapitalized()} if block.isReadable(): diff --git a/silecs-codegen/src/xml/genplcsrc.py b/silecs-codegen/src/xml/genplcsrc.py index d96b55aaba3c92f84231acb05d563a0296d21b20..c332c146f33095d6f24b7dbad3803cebf998791a 100644 --- a/silecs-codegen/src/xml/genplcsrc.py +++ b/silecs-codegen/src/xml/genplcsrc.py @@ -543,7 +543,7 @@ def generateBeckhoffSources(param, sourceFolderPath, logTopics): source += 'END_VAR' # Write the source into the EXP source file - generateControllerFiles(sourceFolderPath,param.controller.hostName,".exp",source,logTopics); + generateControllerFiles(sourceFolderPath,param.controller.hostName,".exp",source,logTopics) #------------------------------------------------------------------------- # NI code generation @@ -556,7 +556,7 @@ def generateControllerFiles(sourceFolderPath,hostName,fileExtention,source,logTo fileName = hostName + fileExtention fullFilePath = os.path.normpath(sourceFolderPath + "/" + fileName ) - iecommon.logInfo("Generate PLC sources: %s" %fullFilePath,logTopics); + iecommon.logInfo("Generate PLC sources: %s" %fullFilePath,logTopics) fdesc = open(fullFilePath, "w") fdesc.write(source) fdesc.close() diff --git a/silecs-codegen/src/xml/model/Class/Block.py b/silecs-codegen/src/xml/model/Class/Block.py index 92ae5c4adaff8492b011b8c0beb50f264e20b21f..3cb9ad30da9d0bd275b87e28bf2a21aee556c8f1 100644 --- a/silecs-codegen/src/xml/model/Class/Block.py +++ b/silecs-codegen/src/xml/model/Class/Block.py @@ -35,8 +35,9 @@ class Block(object): ___acquisitionIOBlockName = "Acquisition-IO-Block" ___commandIOBlockName = "Command-IO-Block" - def __init__(self, xmlNode): + def __init__(self, xmlNode, customTypesXmlNode): self.xmlNode = xmlNode + self.customTypesXmlNode = customTypesXmlNode self.ioType = "" self.name = xmlNode.prop("name") if xmlNode.hasProp("ioType"): @@ -109,8 +110,8 @@ class ParamBlock(Block): self.address = 0 self.memSize = 0 - def initWithParamBlockNode(self, xmlNode): - super(ParamBlock, self).__init__(xmlNode) + def initWithParamBlockNode(self, xmlNode, customTypesXmlNode): + super(ParamBlock, self).__init__(xmlNode, customTypesXmlNode) self.size = int(self.xmlNode.prop("size")) self.address = int(self.xmlNode.prop("address")) self.memSize = int(self.xmlNode.prop("mem-size")) @@ -121,7 +122,7 @@ class ParamBlock(Block): if designBlock.xmlNode.hasProp("ioType"): newNode.newProp("ioType", designBlock.xmlNode.prop("ioType")) print(newNode.get_name()) - super(ParamBlock, self).__init__(newNode) + super(ParamBlock, self).__init__(newNode, designBlock.customTypesXmlNode) newNode.newProp("size", str(self.size)) newNode.newProp("address", str(self.address)) newNode.newProp("mem-size", str(self.memSize)) @@ -142,7 +143,7 @@ class ParamBlock(Block): paramRegisters = [] for registerNode in self.getRegisterNodes(): paramRegister = ParamRegister() - paramRegister.initWithParamRegisterNode(registerNode) + paramRegister.initWithParamRegisterNode(registerNode, self.customTypesXmlNode) paramRegisters.append(paramRegister) return paramRegisters @@ -157,8 +158,8 @@ class ParamBlock(Block): class DesignBlock(Block): - def __init__(self, xmlNode): - super(DesignBlock, self).__init__(xmlNode) + def __init__(self, xmlNode, customTypesXmlNode): + super(DesignBlock, self).__init__(xmlNode, customTypesXmlNode) self.generateFesaProperty = False self.fesaPropertyName = "" self.fesaGetServerActionName = "" @@ -188,13 +189,13 @@ class DesignBlock(Block): def getDesignMEMRegisters(self): designRegisters = [] for registerNode in self.getMEMRegisterNodes(): - designRegisters.append(DesignRegister(registerNode)) + designRegisters.append(DesignRegister(registerNode, self.customTypesXmlNode)) return designRegisters def getDesignIORegisters(self): designIORegisters = [] for registerNode in self.getIORegisterNodes(): - designIORegisters.append(DesignRegister(registerNode)) + designIORegisters.append(DesignRegister(registerNode, self.customTypesXmlNode)) return designIORegisters def getDesignRegisters(self): diff --git a/silecs-codegen/src/xml/model/Class/Class.py b/silecs-codegen/src/xml/model/Class/Class.py index b1cbfe19fa0b43e25afc66e60c2a1b669b65ca81..ef91395aa4702ed65f67cd16ad386f70385f3817 100644 --- a/silecs-codegen/src/xml/model/Class/Class.py +++ b/silecs-codegen/src/xml/model/Class/Class.py @@ -18,11 +18,18 @@ from iecommon import * from model.Class.Block import * from Mapping import * import libxml2 +from model.Class.Types import Enum class Class(object): def __init__(self, xmlNode): self.xmlNode = xmlNode + customTypes = self.xmlNode.xpathEval("custom-types") + if customTypes is not None and len(customTypes) == 1: + self.customTypesXmlNode = customTypes[0] + else: + self.customTypesXmlNode = None + self.name = xmlNode.prop("name") self.version = xmlNode.prop("version") #xmlNode.shellPrintNode() @@ -39,6 +46,9 @@ class Class(object): def getMemoryBlockNodes(self): return self.xmlNode.xpathEval("*[name()='Acquisition-Block' or name()='Setting-Block' or name()='Command-Block' or name()='Configuration-Block']") + def getEnumNodes(self): + return self.xmlNode.xpathEval("custom-types/enum") + class ParamClass(Class): ___addressAttribute = { MEM_TYPE: "address", DI_TYPE: "DI-address", DO_TYPE: "DO-address", AI_TYPE: "AI-address", AO_TYPE: "AO-address" } ___usedDataAttribute = { MEM_TYPE: "used-mem", DI_TYPE: "used-DI", DO_TYPE: "used-DO", AI_TYPE: "used-AI", AO_TYPE: "used-AO" } @@ -58,6 +68,9 @@ class ParamClass(Class): newNode = libxml2.newNode(designClass.xmlNode.get_name()) newNode.newProp("name", designClass.name) newNode.newProp("version", designClass.version) + if designClass.customTypesXmlNode is not None: + customNode = designClass.customTypesXmlNode.copyNode(1) + newNode.addChild(customNode) super(ParamClass, self).__init__(newNode) for index, address in enumerate(self.address): newNode.newProp(self.___addressAttribute[index], str(self.address[index])) @@ -76,7 +89,7 @@ class ParamClass(Class): paramBlocks = [] for blockNode in self.getBlockNodes(): paramBlock = ParamBlock() - paramBlock.initWithParamBlockNode(blockNode) + paramBlock.initWithParamBlockNode(blockNode, self.customTypesXmlNode) paramBlocks.append(paramBlock) return paramBlocks @@ -84,7 +97,7 @@ class ParamClass(Class): paramMemBlocks = [] for blockNode in self.getMemoryBlockNodes(): paramBlock = ParamBlock() - paramBlock.initWithParamBlockNode(blockNode) + paramBlock.initWithParamBlockNode(blockNode, self.customTypesXmlNode) paramMemBlocks.append(paramBlock) return paramMemBlocks @@ -111,15 +124,21 @@ class DesignClass(Class): def getDesignBlocks(self): designBlocks = [] for blockNode in self.getBlockNodes(): - designBlocks.append(DesignBlock(blockNode)) + designBlocks.append(DesignBlock(blockNode, self.customTypesXmlNode)) return designBlocks def getDesignMemoryBlocks(self): designBlocks = [] for blockNode in self.getMemoryBlockNodes(): - designBlocks.append(DesignBlock(blockNode)) + designBlocks.append(DesignBlock(blockNode, self.customTypesXmlNode)) return designBlocks + def getEnums(self): + enums = [] + for node in self.getEnumNodes(): + enums.append(Enum(node)) + return enums + @staticmethod def getDesignClassFromRootNode(silecsRoot): classNodes = silecsRoot.xpathEval('/SILECS-Design/SILECS-Class') diff --git a/silecs-codegen/src/xml/model/Class/Register.py b/silecs-codegen/src/xml/model/Class/Register.py index c665f59735e26dc3469ce7e4a72d9d4e6a135893..1d215200b3649e6e9b0bb6698938dac8c03f19dc 100644 --- a/silecs-codegen/src/xml/model/Class/Register.py +++ b/silecs-codegen/src/xml/model/Class/Register.py @@ -25,9 +25,9 @@ class Register(object): ___acquisitionIORegisterType = "Acquisition-IO-Register" - def __init__(self, xmlNode): + def __init__(self, xmlNode, customTypesXmlNode): self.xmlNode = xmlNode - + self.customTypesXmlNode = customTypesXmlNode #xmlNode.shellPrintNode() self.name = xmlNode.prop("name") self.___type = xmlNode.get_name() @@ -37,8 +37,9 @@ class Register(object): self.dim2 = 1 self.stringLength = 1 # ... currently needs to be default because of some old convention self.format = "" + self.custom_type_name = "" - valueTypes = xmlNode.xpathEval("*[name()='scalar' or name()='array' or name()='array2D' or name()='string' or name()='stringArray' or name()='stringArray2D']") + valueTypes = xmlNode.xpathEval("*[name()='scalar' or name()='array' or name()='array2D' or name()='string' or name()='stringArray' or name()='stringArray2D' or name()='custom-type-scalar' or name()='custom-type-array' or name()='custom-type-array2D']") if not valueTypes: iecommon.logError('ERROR: The register '+ self.name +' has no valueTypes.', True, {'errorlog': True}) if len(valueTypes) < 1: @@ -59,7 +60,15 @@ class Register(object): if self.valueTypeNode.hasProp("string-length"): self.stringLength = int(self.valueTypeNode.prop("string-length")) - self.format = self.valueTypeNode.prop("format") + if self.isCustomType(): + self.custom_type_name = self.valueTypeNode.prop("custom-type-name-ref") + + if self.isEnumType(): + self.format = "int32" + else: + raise Exception("Custom types other than 'enum' are not yet supported.") + else: + self.format = self.valueTypeNode.prop("format") def getNameCapitalized(self): @@ -89,6 +98,29 @@ class Register(object): def isStringType(self): return self.valueType == 'string' or self.valueType == 'stringArray' or self.valueType == 'stringArray2D' + def isCustomScalar(self): + return self.valueType == 'custom-type-scalar' + + def isCustomArray(self): + return self.valueType == 'custom-type-array' + + def isCustomArray2D(self): + return self.valueType == 'custom-type-array2D' + + def isCustomType(self): + return self.isCustomScalar() or self.isCustomArray() or self.isCustomArray2D() + + def isEnumType(self): + if self.customTypesXmlNode is None: + return False + + enums = self.customTypesXmlNode.xpathEval("enum") + for e in enums: + if e.prop("name") == self.custom_type_name: + return True + + return False + def isArrayType(self): return self.isArray() or self.isArray2D() @@ -203,8 +235,8 @@ class ParamRegister(Register): self.memSize = 0 self.bitNumber = 0 - def initWithParamRegisterNode(self, xmlNode): - super(ParamRegister, self).__init__(xmlNode) + def initWithParamRegisterNode(self, xmlNode, customTypesXmlNode): + super(ParamRegister, self).__init__(xmlNode, customTypesXmlNode) self.size = int(self.xmlNode.prop("size")) self.address = int(self.xmlNode.prop("address")) self.memSize = int(self.xmlNode.prop("mem-size")) @@ -218,7 +250,7 @@ class ParamRegister(Register): newNodeTree = designRegister.xmlNode.copyNode(1) # 1 is for recursive copy if ( newNodeTree == None ): iecommon.logError('ERROR: Failed to copy register node: '+ designRegister.name +'.', True, {'errorlog': True}) - super(ParamRegister, self).__init__(designRegister.xmlNode) + super(ParamRegister, self).__init__(designRegister.xmlNode, designRegister.customTypesXmlNode) self.xmlNode = newNodeTree self.size = self.getDataSize() newNodeTree.newProp("size", str(self.size)) @@ -231,7 +263,11 @@ class ParamRegister(Register): newNodeTree.newProp("bit-number", str(bitNumber)) self.bitNumber = bitNumber - #self.xmlNode.shellPrintNode() + # Add an attribute to facilitate detecting the type of the custom-type. + if self.isEnumType(): + for elem in self.xmlNode: + if elem.hasProp("custom-type-name-ref"): + elem.newProp("type", "enum") def setSize(self,size): self.xmlNode.setProp("size", str(size)) @@ -248,8 +284,8 @@ class ParamRegister(Register): class DesignRegister(Register): - def __init__(self, xmlNode): - super(DesignRegister, self).__init__(xmlNode) + def __init__(self, xmlNode, customTypesXmlNode): + super(DesignRegister, self).__init__(xmlNode, customTypesXmlNode) self.fesaFieldName = self.name self.generateFesaValueItem=True if self.xmlNode.hasProp("fesaFieldName"): diff --git a/silecs-codegen/src/xml/model/Class/Types.py b/silecs-codegen/src/xml/model/Class/Types.py new file mode 100644 index 0000000000000000000000000000000000000000..2d3f32498c8a74255e7a1990dbbc365b2718fff5 --- /dev/null +++ b/silecs-codegen/src/xml/model/Class/Types.py @@ -0,0 +1,25 @@ +class EnumItem(object): + def __init__(self, xmlNode) -> None: + self.xmlNode = xmlNode + self.access = xmlNode.prop("access") + self.symbol = xmlNode.prop("symbol") + self.value = xmlNode.prop("value") + + def __str__(self) -> str: + return f"EnumItem: {self.access}, {self.symbol}, {self.value}" + +class Enum(object): + def __init__(self, xmlNode) -> None: + self.xmlNode = xmlNode + + self.name: str = xmlNode.prop("name") + self.items: EnumItem = [] + items = xmlNode.xpathEval("item") + for item in items: + self.items.append(EnumItem(item)) + + def __str__(self) -> str: + items = "" + for item in self.items: + items += "\t"+ str(item) + "\n" + return f"Enum {self.name}.\nItems:\n {items}" \ No newline at end of file diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp index 1cb6a07496c3a95c863efcffbb62648af9d889e8..3d99d9dd8a0ba19262dddb449023b8d2b4910c01 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp @@ -37,8 +37,30 @@ Register::Register(const ElementXML& registerNode) : for (auto childIter = childNodes.begin(); childIter != childNodes.end(); childIter++) { // We have to loop, since there is as well the description-element - type_ = whichFormatType(childIter->getAttribute("format")); - typeString_ = childIter->getAttribute("format"); + + if (childIter->hasAttribute("custom-type-name-ref")) + { + if (!childIter->hasAttribute("type")) + { + throw SilecsException(__FILE__, __LINE__, "Register '" + name_+ "' - Can't detect the type of the custom-type."); + } + + if (childIter->getAttribute("type") == "enum") + { + // Enum type. + type_ = Int32; + typeString_ = "int32"; + } + else + { + throw SilecsException(__FILE__, __LINE__, "Register '" + name_+ "' - Custom types other than 'enum' are not yet supported."); + } + } + else + { + type_ = whichFormatType(childIter->getAttribute("format")); + typeString_ = childIter->getAttribute("format"); + } StringUtilities::toLower(typeString_); if (childIter->hasAttribute("dim")) diff --git a/silecs-model/src/xml/DeploySchema.xsd b/silecs-model/src/xml/DeploySchema.xsd index 8577a26d20960a62d01dcf30ff82d3fbbbf67011..cdb7309cdf066992eca9f9d1e65658c417c53c0c 100644 --- a/silecs-model/src/xml/DeploySchema.xsd +++ b/silecs-model/src/xml/DeploySchema.xsd @@ -589,13 +589,6 @@ </xs:restriction> </xs:simpleType> - <!-- Base type which just forbid characters not supported by the DB --> - <xs:simpleType name="BaseType"> - <xs:restriction base="xs:string"> - <xs:pattern value="[^&<>"]*" /> - </xs:restriction> - </xs:simpleType> - <!-- Type for named item which are not transformed into Cpp object --> <xs:simpleType name="NonIdentifierType"> <xs:restriction base="BaseType"> diff --git a/silecs-model/src/xml/DesignSchema-custom-types.xsd b/silecs-model/src/xml/DesignSchema-custom-types.xsd new file mode 100644 index 0000000000000000000000000000000000000000..4fe83ec2a5e9abb0b1a6191cdb419184ef68889b --- /dev/null +++ b/silecs-model/src/xml/DesignSchema-custom-types.xsd @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2016 CERN and GSI This program 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, either version 3 of the License, or (at your option) any later version. This program 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 this program. If not, see http://www.gnu.org/licenses/. --> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> + <xs:include schemaLocation="DesignSchema-data-types.xsd" /> + <xs:include schemaLocation="shared.xsd" /> + + <xs:simpleType name="MeaningValueType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="ON" /> + <xs:enumeration value="OFF" /> + <xs:enumeration value="WARNING" /> + <xs:enumeration value="ERROR" /> + <xs:enumeration value="NONE" /> + </xs:restriction> + </xs:simpleType> + + <xs:element name="enum"> + <xs:complexType> + <xs:sequence> + <xs:element name="description" type="DescriptionType" minOccurs="0" maxOccurs="unbounded" /> + <xs:element name="item" maxOccurs="unbounded"> + <xs:complexType> + <xs:attribute name="symbol" type="EnumSymbolNameType" use="required" /> + <xs:attribute name="value" type="xs:int" use="required" /> + <xs:attribute name="meaning" type="MeaningValueType" default="NONE" /> + <xs:attribute name="access" type="EnumAccessType" use="required" /> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="name" type="TypeNameType" use="required" /> + </xs:complexType> + + <xs:unique name="item-symbol-is-unique-per-enum"> + + <xs:selector xpath="./item" /> + + <xs:field xpath="@symbol" /> + </xs:unique> + + <xs:unique name="item-value-is-unique-per-enum"> + + <xs:selector xpath="./item" /> + + <xs:field xpath="@value" /> + </xs:unique> + </xs:element> + + <!-- This type can be extended in the lab-package --> + <xs:complexType name="custom-type-collection"> + <xs:sequence> + <!-- Stacked sequences to have variable order for the sub-elements --> + <xs:sequence minOccurs="0" maxOccurs="unbounded"> + <xs:element ref="enum" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:sequence> + </xs:complexType> + +</xs:schema> \ No newline at end of file diff --git a/silecs-model/src/xml/DesignSchema-data-types.xsd b/silecs-model/src/xml/DesignSchema-data-types.xsd new file mode 100644 index 0000000000000000000000000000000000000000..67f8d3799a28126b2cd5b75fb2e556c6dcec5870 --- /dev/null +++ b/silecs-model/src/xml/DesignSchema-data-types.xsd @@ -0,0 +1,137 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- Copyright 2016 CERN and GSI This program 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, either version 3 of the License, or (at your option) any later version. This program 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 this program. If not, see http://www.gnu.org/licenses/. --> + +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> + + + <xs:simpleType name="IdentifierType"> + <xs:restriction base="xs:string"> + <xs:pattern value="[A-Za-z][A-Za-z0-9_]*" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="TypeNameType"> + <xs:restriction base="IdentifierType"> + <xs:maxLength value="60" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="EnumAccessType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="RW" /> + <xs:enumeration value="RO" /> + <xs:enumeration value="WO" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="EnumSymbolNameType"> + <xs:restriction base="xs:string"> + <xs:pattern value="[_A-Za-z][_A-Za-z0-9]*" /> + <xs:maxLength value="60" /> + </xs:restriction> + </xs:simpleType> + + <xs:complexType name="TypeRefType"> + <xs:attribute name="data-type-name-ref" type="xs:string" use="required" /> + </xs:complexType> + + <xs:simpleType name="FormatType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="uint8" /> + <xs:enumeration value="int8" /> + <xs:enumeration value="uint16" /> + <xs:enumeration value="int16" /> + <xs:enumeration value="uint32" /> + <xs:enumeration value="int32" /> + <xs:enumeration value="uint64" /> + <xs:enumeration value="int64" /> + <xs:enumeration value="float32" /> + <xs:enumeration value="float64" /> + <xs:enumeration value="date" /> + <xs:enumeration value="char" /> + <xs:enumeration value="byte" /> + <xs:enumeration value="word" /> + <xs:enumeration value="dword" /> + <xs:enumeration value="int" /> + <xs:enumeration value="dint" /> + <xs:enumeration value="real" /> + <xs:enumeration value="dt" /> + <xs:enumeration value="bool" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="IOFormatType"> + <xs:restriction base="xs:string"> + <xs:enumeration value="uint8" /> + <xs:enumeration value="uint16" /> + <xs:enumeration value="uint32" /> + <xs:enumeration value="byte" /> + <xs:enumeration value="word" /> + <xs:enumeration value="dword" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="DimensionType"> + <xs:restriction base="xs:unsignedInt"> + <xs:minInclusive value="1" /> + </xs:restriction> + </xs:simpleType> + <xs:simpleType name="LengthType"> + <xs:restriction base="xs:unsignedInt"> + <xs:minInclusive value="2" /> + <xs:maxInclusive value="254" /> + </xs:restriction> + </xs:simpleType> + + <xs:complexType name="ScalarValueType"> + <xs:attribute name="format" type="FormatType" use="required" /> + </xs:complexType> + + <xs:complexType name="IO-ScalarValueType"> + <xs:attribute name="format" type="IOFormatType" use="required" /> + </xs:complexType> + + <xs:complexType name="ArrayValueType"> + <xs:attribute name="format" type="FormatType" use="required" /> + <xs:attribute name="dim" type="DimensionType" use="required" /> + </xs:complexType> + + <xs:complexType name="Array2DValueType"> + <xs:attribute name="format" type="FormatType" use="required" /> + <xs:attribute name="dim1" type="DimensionType" use="required" /> + <xs:attribute name="dim2" type="DimensionType" use="required" /> + </xs:complexType> + + <xs:complexType name="StringValueType"> + <xs:attribute name="format" fixed="string" use="required" /> + <xs:attribute name="string-length" type="LengthType" use="required" /> + </xs:complexType> + + <xs:complexType name="StringArrayValueType"> + <xs:attribute name="format" fixed="string" use="required" /> + <xs:attribute name="string-length" type="LengthType" use="required" /> + <xs:attribute name="dim" type="DimensionType" use="required" /> + </xs:complexType> + + <xs:complexType name="StringArray2DValueType"> + <xs:attribute name="format" fixed="string" use="required" /> + <xs:attribute name="string-length" type="LengthType" use="required" /> + <xs:attribute name="dim1" type="DimensionType" use="required" /> + <xs:attribute name="dim2" type="DimensionType" use="required" /> + </xs:complexType> + + <xs:complexType name="CustomScalarValueType"> + <xs:attribute name="custom-type-name-ref" type="xs:string" use="required" /> + </xs:complexType> + + <xs:complexType name="CustomArrayValueType"> + <xs:attribute name="custom-type-name-ref" type="xs:string" use="required" /> + <xs:attribute name="dim" type="DimensionType" use="required" /> + </xs:complexType> + + <xs:complexType name="CustomArray2DValueType"> + <xs:attribute name="custom-type-name-ref" type="xs:string" use="required" /> + <xs:attribute name="dim1" type="DimensionType" use="required" /> + <xs:attribute name="dim2" type="DimensionType" use="required" /> + </xs:complexType> +</xs:schema> \ No newline at end of file diff --git a/silecs-model/src/xml/DesignSchema.xsd b/silecs-model/src/xml/DesignSchema.xsd index 52ff0caeabddc0c4cbdc8edf6aaf5bedc403e0ad..eeec6e0f7853371d9770a42c6761b6fe060cc437 100644 --- a/silecs-model/src/xml/DesignSchema.xsd +++ b/silecs-model/src/xml/DesignSchema.xsd @@ -3,7 +3,9 @@ <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified"> <xs:include schemaLocation="shared.xsd" /> - + <xs:include schemaLocation="DesignSchema-data-types.xsd" /> + <xs:include schemaLocation="DesignSchema-custom-types.xsd" /> + <xs:element name="SILECS-Design"> <xs:annotation> <xs:documentation>A SILECS configuration contains the class designs, the memory mapping and the hardware distribution for a given set of PLCs.</xs:documentation> @@ -89,6 +91,7 @@ <xs:element name="Command-IO-Block" type="Setting-IO-BlockType" /> </xs:choice> <xs:element name="Description" type="xs:string" minOccurs="0" /> + <xs:element name="custom-types" type="custom-type-collection" minOccurs="0" /> </xs:sequence> <xs:attribute name="name" type="SilecsClassNameType" use="required" /> <xs:attribute name="version" type="VersionType" use="required" /> @@ -104,6 +107,14 @@ </xs:simpleType> </xs:attribute> </xs:complexType> + <xs:key name="custom-key"> + <xs:selector xpath="./custom-types/*" /> + <xs:field xpath="@name" /> + </xs:key> + <xs:keyref name="custom-scalar-keyref" refer="custom-key"> + <xs:selector xpath=".//custom-type-scalar | .//custom-type-array | .//custom-type-array2D"/> + <xs:field xpath="@custom-type-name-ref"/> + </xs:keyref> <xs:unique name="Register-name-has-to-be-unique"> <xs:selector xpath="*/*" /> <xs:field xpath="@name" /> @@ -315,43 +326,6 @@ </xs:complexContent> </xs:complexType> - <xs:complexType name="ScalarValueType"> - <xs:attribute name="format" type="FormatType" use="required" /> - </xs:complexType> - - <xs:complexType name="IO-ScalarValueType"> - <xs:attribute name="format" type="IOFormatType" use="required" /> - </xs:complexType> - - <xs:complexType name="ArrayValueType"> - <xs:attribute name="format" type="FormatType" use="required" /> - <xs:attribute name="dim" type="DimensionType" use="required" /> - </xs:complexType> - - <xs:complexType name="Array2DValueType"> - <xs:attribute name="format" type="FormatType" use="required" /> - <xs:attribute name="dim1" type="DimensionType" use="required" /> - <xs:attribute name="dim2" type="DimensionType" use="required" /> - </xs:complexType> - - <xs:complexType name="StringValueType"> - <xs:attribute name="format" fixed="string" use="required" /> - <xs:attribute name="string-length" type="LengthType" use="required" /> - </xs:complexType> - - <xs:complexType name="StringArrayValueType"> - <xs:attribute name="format" fixed="string" use="required" /> - <xs:attribute name="string-length" type="LengthType" use="required" /> - <xs:attribute name="dim" type="DimensionType" use="required" /> - </xs:complexType> - - <xs:complexType name="StringArray2DValueType"> - <xs:attribute name="format" fixed="string" use="required" /> - <xs:attribute name="string-length" type="LengthType" use="required" /> - <xs:attribute name="dim1" type="DimensionType" use="required" /> - <xs:attribute name="dim2" type="DimensionType" use="required" /> - </xs:complexType> - <xs:complexType name="BaseRegisterType"> <xs:sequence> <xs:element name="Description" type="xs:string" minOccurs="0" /> @@ -388,6 +362,9 @@ <xs:element name="string" type="StringValueType" /> <xs:element name="stringArray" type="StringArrayValueType" /> <xs:element name="stringArray2D" type="StringArray2DValueType" /> + <xs:element name="custom-type-scalar" type="CustomScalarValueType" /> + <xs:element name="custom-type-array" type="CustomArrayValueType" /> + <xs:element name="custom-type-array2D" type="CustomArray2DValueType" /> </xs:choice> </xs:sequence> </xs:extension> @@ -399,6 +376,7 @@ <xs:extension base="BaseRegisterType"> <xs:sequence> <xs:element name="scalar" type="IO-ScalarValueType" /> + <xs:element name="custom-type-scalar" type="CustomScalarValueType" /> </xs:sequence> </xs:extension> </xs:complexContent> @@ -421,52 +399,5 @@ <xs:pattern value="[_A-Za-z]+[_A-Za-z0-9]*" /> </xs:restriction> </xs:simpleType> - <xs:simpleType name="FormatType"> - <xs:restriction base="xs:string"> - <xs:enumeration value="uint8" /> - <xs:enumeration value="int8" /> - <xs:enumeration value="uint16" /> - <xs:enumeration value="int16" /> - <xs:enumeration value="uint32" /> - <xs:enumeration value="int32" /> - <xs:enumeration value="uint64" /> - <xs:enumeration value="int64" /> - <xs:enumeration value="float32" /> - <xs:enumeration value="float64" /> - <xs:enumeration value="date" /> - <xs:enumeration value="char" /> - <xs:enumeration value="byte" /> - <xs:enumeration value="word" /> - <xs:enumeration value="dword" /> - <xs:enumeration value="int" /> - <xs:enumeration value="dint" /> - <xs:enumeration value="real" /> - <xs:enumeration value="dt" /> - <xs:enumeration value="bool" /> - </xs:restriction> - </xs:simpleType> - - <xs:simpleType name="IOFormatType"> - <xs:restriction base="xs:string"> - <xs:enumeration value="uint8" /> - <xs:enumeration value="uint16" /> - <xs:enumeration value="uint32" /> - <xs:enumeration value="byte" /> - <xs:enumeration value="word" /> - <xs:enumeration value="dword" /> - </xs:restriction> - </xs:simpleType> - - <xs:simpleType name="DimensionType"> - <xs:restriction base="xs:unsignedInt"> - <xs:minInclusive value="1" /> - </xs:restriction> - </xs:simpleType> - <xs:simpleType name="LengthType"> - <xs:restriction base="xs:unsignedInt"> - <xs:minInclusive value="2" /> - <xs:maxInclusive value="254" /> - </xs:restriction> - </xs:simpleType> </xs:schema> diff --git a/silecs-model/src/xml/shared.xsd b/silecs-model/src/xml/shared.xsd index ee68b9c1b9fa4ebc989920052d1770c6c4e1a7f0..22b9a1a3ac677daa93e31325b6c01fc67b5d18cc 100644 --- a/silecs-model/src/xml/shared.xsd +++ b/silecs-model/src/xml/shared.xsd @@ -30,4 +30,26 @@ along with this program. If not, see http://www.gnu.org/licenses/.--> </xs:restriction> </xs:simpleType> + <!-- Base type which just forbid characters not supported by the DB --> + <xs:simpleType name="BaseType"> + <xs:restriction base="xs:string"> + <xs:pattern value="[^&<>"]*" /> + </xs:restriction> + </xs:simpleType> + + <!-- We must allow empty content for defining empty strings in default values --> + <xs:simpleType name="ValueType"> + <xs:restriction base="BaseType"> + <xs:whiteSpace value="collapse" /> + <xs:maxLength value="4000" /> + </xs:restriction> + </xs:simpleType> + + <xs:simpleType name="DescriptionType"> + <xs:restriction base="BaseType"> + <xs:whiteSpace value="collapse" /> + <xs:maxLength value="4000" /> + </xs:restriction> + </xs:simpleType> + </xs:schema>