Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions code/iec61131-integration/.module-id
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
00c8d7a5-e1fd-4a2c-bbdf-9d0d4ac80394
39 changes: 39 additions & 0 deletions code/iec61131-integration/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import org.fbme.gradle.moduleDependency

plugins {
kotlin
mps
}

dependencies {
compileOnly(mpsDistribution())
compileOnly(project(":code:library"))
compileOnly(project(":code:language"))
compileOnly(project(":code:platform"))
implementation(project(":code:iec61131"))

mpsImplementation(project(":code:library", "mps"))
mpsImplementation(project(":code:language", "mps"))
mpsImplementation(project(":code:platform", "mps"))
mpsImplementation(project(":code:richediting", "mps"))
}

mps {
buildScriptName.set("fbme_iec61131")
moduleName.set("org.fbme.integration.iec61131.lib")
moduleDependency(project(":code:library"))
moduleDependency(project(":code:platform"))
}

val mpsPrepare by tasks.getting(Copy::class) {
from("build/libs/iec61131-integration.jar")
into("solutions/org.fbme.integration.iec61131/lib")
}

val test by tasks.getting(Test::class) {
dependsOn(
":code:library:buildDistPlugin",
":code:platform:buildDistPlugin",
"buildDistPlugin"
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package org.fbme.integration.iec61131.importer

import com.intellij.ide.util.BrowseFilesListener
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
import com.intellij.openapi.fileChooser.FileChooserFactory
import com.intellij.openapi.util.EmptyRunnable
import com.intellij.ui.FieldPanel
import com.intellij.ui.InsertPathAction
import com.intellij.util.ui.JBUI
import org.fbme.ide.platform.projectWizard.Iec61499SolutionSettings
import javax.swing.JLabel
import javax.swing.JTextField

class Iec61131ImportLocationConfig(defaultName: String) :
Iec61499SolutionSettings(defaultName) {
private val importLocation: JTextField

init {
this.add(JLabel("IEC61131 file:"), 4, 0.0)
importLocation = JTextField()
importLocation.name = "Path"
val descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor()
InsertPathAction.addTo(importLocation, descriptor)
val listener = BrowseFilesListener(importLocation, "Choose IEC61131 project xml file", "", descriptor)
val fieldPanel = FieldPanel(importLocation, null, null, listener, EmptyRunnable.getInstance())
FileChooserFactory.getInstance().installFileCompletion(fieldPanel.textField, descriptor, false, null)
this.add(fieldPanel, 5, 0.0, JBUI.insetsBottom(5))
}

fun getImportLocation(): String {
return importLocation.text.trim { it <= ' ' }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.fbme.integration.iec61131.importer

import com.intellij.openapi.util.IconLoader

object Iec61131IntegrationIcons {

@JvmField
val importProject = IconLoader.getIcon("/icons/iec61131_import.svg", Iec61131IntegrationIcons::class.java)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package org.fbme.integration.iec61131.importer

import jetbrains.mps.project.AbstractModule
import jetbrains.mps.smodel.ModelImports
import org.fbme.ide.iec61499.repository.PlatformElement
import org.fbme.ide.iec61499.repository.PlatformElementsOwner
import org.fbme.ide.iec61499.repository.PlatformRepository
import org.fbme.ide.platform.projectWizard.Iec61499ProjectTemplate
import org.fbme.lib.iec61131.converter.ProjectConverter
import org.jetbrains.mps.openapi.model.SModel
import org.jetbrains.mps.openapi.persistence.PersistenceFacade


class Iec61131ImportProjectTemplate : Iec61499ProjectTemplate(
Iec61131ImportLocationConfig("NewModel"),
"IEC61131 Project",
"Convert IEC61131 project to IEC61499 FBME project",
Iec61131IntegrationIcons.importProject,
null
) {

override fun initModel(repository: PlatformRepository, model: SModel): PlatformElement {
val settings = settings as Iec61131ImportLocationConfig
val iec61131ProjectLocation = settings.getImportLocation()
addModelImports(model)

readModel(iec61131ProjectLocation, model)
val first = model.rootNodes.first()

return repository.getAdapter(first, PlatformElement::class.java)
}

private fun addModelImports(model: SModel) {
val iec61499ModuleId = "b8a7e14f-52ea-4ee2-b17e-26c27da8084c(IEC-61499)"
(model.module as AbstractModule).addDependency(
PersistenceFacade.getInstance().createModuleReference(iec61499ModuleId), false
)

val stdLibModuleId = "r:fa98296a-e4fa-4f84-b917-968f5f770c4b(iec61499.4diac.stdlib)"
ModelImports(model).addModelImport(PersistenceFacade.getInstance().createModelReference(stdLibModuleId))
}


private fun readModel(path: String, model: SModel) {
val owner = PlatformElementsOwner();

ProjectConverter(owner.iec61499Factory, owner.stFactory).getProjectNodes(path)
.map { (it as PlatformElement).node }
.forEach { model.addRootNode(it) }
}
}
22 changes: 22 additions & 0 deletions code/iec61131-integration/src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<idea-plugin>
<id>fbme.integration.iec61131</id>
<name>FBME - IEC61131</name>
<description>FBME projects creation from IEC61131 projects</description>
<version>0.1</version>
<vendor url="https://github.com/JetBrains/fbme">FBME</vendor>

<depends>fbme.platform</depends>
<depends>jetbrains.mps.core</depends>
<depends>jetbrains.mps.execution.languages</depends>
<depends>fbme.richediting</depends>
<depends>fbme.scenes</depends>

<extensions defaultExtensionNs="com.intellij">
<mps.LanguageLibrary dir="/languages" />
</extensions>

<extensions defaultExtensionNs="fbme.platform">
<iec61499projectTemplate implementation="org.fbme.integration.iec61131.importer.Iec61131ImportProjectTemplate" />
</extensions>
</idea-plugin>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE FBType SYSTEM "http://www.holobloc.com/xml/LibraryElement.dtd">
<FBType Name="ParserTestFbt1">
<InterfaceList />
<BasicFB />
</FBType>
10 changes: 10 additions & 0 deletions code/iec61131/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
plugins {
kotlin
kotlin("plugin.serialization").version("1.6.21")
}

dependencies {
implementation("io.github.pdvrieze.xmlutil:serialization-jvm:0.83.0")
implementation("io.github.pdvrieze.xmlutil:core-jvm:0.83.0")
compileOnly(project(":code:library"))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package org.fbme.lib.iec61131.converter

import org.fbme.lib.iec61131.model.BlockInfo
import org.fbme.lib.iec61131.model.DataParameterInfo
import org.fbme.lib.iec61131.model.Iec61131Xml
import org.fbme.lib.iec61131.model.oldStandardBocks
import org.fbme.lib.iec61499.IEC61499Factory
import org.fbme.lib.st.STFactory
import org.fbme.lib.st.types.DataType
import org.fbme.lib.st.types.ElementaryType
import org.fbme.lib.st.types.GenericType

open class ConverterBase(arguments: ConverterArguments) {
val factory: IEC61499Factory
val stFactory: STFactory
val blocksInterfaceInfo: BlocksInterfaceInfo

init {
factory = arguments.factory
stFactory = arguments.stFactory
blocksInterfaceInfo = arguments.blocksInterfaceInfo
}
}

class ConverterArguments(
val factory: IEC61499Factory,
val stFactory: STFactory,
val blocksInterfaceInfo: BlocksInterfaceInfo
)

class BlocksInterfaceInfo(pous: Iec61131Xml.Pous) {

private val typeNameToBlock: Map<String, BlockInfo> =
(oldStandardBocks + getAdditionalBlockTypes(pous)).associateBy { it.typeName }
fun getBlockParameters(blockTypeName: String): List<DataParameterInfo> {
return typeNameToBlock[blockTypeName]!!.parameterNameToType.values.toList()
}

private fun getAdditionalBlockTypes(pous: Iec61131Xml.Pous): List<BlockInfo> {
return pous.pouList.map { toBlockType(it) }
}

private val nameToType: Map<String, DataType> = GenericType.values().associateBy { it.name } +
ElementaryType.values().associateBy { it.name }

private fun toBlockType(pou: Iec61131Xml.Pou): BlockInfo {
val parameters = pou.pouInterface?.outputVars?.toParameters() ?: emptyList()
return BlockInfo(pou.name, parameters)
}

private fun List<Iec61131Xml.VariableList>.toParameters(): List<DataParameterInfo> {
return this.map { variableList ->
variableList.variableList.map { variable ->
val typeStr = variable.type.typeName
DataParameterInfo(variable.name, nameToType[typeStr]!!)
}
}.flatten()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package org.fbme.lib.iec61131.converter

import org.fbme.lib.iec61131.model.Iec61131Xml
import org.fbme.lib.iec61499.declarations.EventAssociation
import org.fbme.lib.iec61499.declarations.FBTypeDeclaration
import org.fbme.lib.iec61499.declarations.ParameterDeclaration
import org.fbme.lib.iec61499.parser.STConverter

class FbInterfaceConverter(
private val xmlPou: Iec61131Xml.Pou,
converterArguments: ConverterArguments
) : ConverterBase(converterArguments) {

fun fillInterface(fbtd: FBTypeDeclaration) {
fbtd.name = xmlPou.name

val inputEvent = factory.createEventDeclaration(null)
inputEvent.name = "REQ"

val outputEvent = factory.createEventDeclaration(null)
outputEvent.name = "CNF"

val pouInterface = xmlPou.pouInterface
if (pouInterface != null) {
fbtd.inputParameters.addAll(mapVarListToParameters(pouInterface.inputVars))
fbtd.inputParameters.addAll(mapVarListToParameters(pouInterface.inOutVars))

fbtd.outputParameters.addAll(mapVarListToParameters(pouInterface.outputVars))
fbtd.outputParameters.addAll(mapVarListToParameters(pouInterface.inOutVars))

fbtd.inputParameters.forEach { inputEvent.associations.add(createAssociation(it.name)) }
fbtd.outputParameters.forEach { outputEvent.associations.add(createAssociation(it.name)) }
}
fbtd.inputEvents.add(inputEvent)
fbtd.outputEvents.add(outputEvent)
}

private fun createAssociation(varName: String): EventAssociation {
val association = factory.createEventAssociation()
association.parameterReference.setTargetName(varName)
return association
}

private fun mapVarListToParameters(varListList: List<Iec61131Xml.VariableList>): List<ParameterDeclaration> {
return varListList
.map { it.variableList.map(::mapVariableToParameter) }
.flatten()
}

private fun mapVariableToParameter(xmlVariable: Iec61131Xml.VariableList.Variable): ParameterDeclaration {
val parameterDeclaration = factory.createParameterDeclaration(null)
parameterDeclaration.name = xmlVariable.name
parameterDeclaration.type = STConverter.parseType(stFactory, xmlVariable.type.typeName)
return parameterDeclaration
}
}
Loading