Setting property values with Python4capella

Hi,
I created a property value named “mass” with PVMT, now I am trying to set its value for the logical component “TMS for electrical drive train” but using the P4C tool, I know that with “PVMT.get_p_v_value(lc, pvName)” I can get that value but it seems that a function with which I can do for instance
PVMT.set_p_v_value(lc,pvName)=float(variable)
doesn’t exist.
Is there a way to do that?
Here you can see the model and the property

Considering mass, is there an easier way to do this but with the basic mass viewpoint? (So addressing the value to the mass description in the physical level?

You can create different types of property value:

pv = PropertyValue(None, “StringPropertyValue”)

Is the default value but you can use: “BooleanPropertyValue”, “EnumerationPropertyValue”, “FloatPropertyValue”, “IntegerPropertyValue”, or “StringPropertyValue”.

In your case:

pv = PropertyValue(None, “FloatPropertyValue”)
pv.set_value(3.14)

Then you can add the property value you will need to get its property value group and then use:

pvg.get_owned_property_values().add(pv)
pvg.get_applied_property_values().add(pv)

Thank you,
And how do I set the value of a Property value already created with the PVMT editor?
Let’s say that once I created the “mass” Property I apply it to an element through the + button in the element properties, but then I want to set or change its value through a python for capella script, is there a way to do that?

Yes you are right this API is a bit confusing… I think the API should return the PropertyValue itself instead of its value. This way we could modify it.

You can try or start with:

    @staticmethod
    def set_p_v_value(elem, PVName, value):
        for group in elem.get_java_object().getOwnedPropertyValueGroups():
            for pv in group.getOwnedPropertyValues():
                if PVName == pv.getName():
                    pv.setValue(value)
                    return

This has some limitations:

  • it will only work if the property value exists
  • it will not work for enum property value

I opened a new issue:

I already tried that but get_p_v() takes just 1 argument and not 2 so pvName connot be specified, furthermore get_p_v() gives a list as output and so no value could be addressed to that list

Also trying to create a new property value from P4C as you showed and applying it to a logical component in this way:

for lc in allLC:
     if lc.get_name() == 'TMS for Electrical drive train':
          
        pv = PropertyValue(None, 'FloatPropertyValue')
        pv.set_value(3.14)
        lc.get_owned_property_values().add(pv)
        lc.get_applied_property_values().add(pv)

I obtain this error in the console

java.lang.IllegalStateException: Cannot modify resource set without a write transaction

Yes you are right this API is a bit confusing… I think the API should return the PropertyValue itself instead of its value. This way we could modify it.

You can try or start with:

    @staticmethod
    def set_p_v_value(elem, PVName, value):
        for group in elem.get_java_object().getOwnedPropertyValueGroups():
            for pv in group.getOwnedPropertyValues():
                if PVName == pv.getName():
                    pv.setValue(value)
                    return

This has some limitations:

  • it will only work if the property value exists
  • it will not work for enum property value

I opened a new issue:

Yes that makes sense to me, I am now trying to implement that function but something is going wrong, using this script to modify just one Property Value for one Logical Element:

  # include needed for the Capella modeller API
  include('workspace://Python4Capella/simplified_api/capella.py')
  if False:
      from simplified_api.capella import *
      
  # include needed for the PVMT API
  include('workspace://Python4Capella/simplified_api/pvmt.py')
  if False:
      from simplified_api.pvmt import *
      
  # include needed for utilities
  include('workspace://Python4Capella/utilities/CapellaPlatform.py')
  if False:
      from utilities.CapellaPlatform import *
  
  # include needed for the requirement API
  include('workspace://Python4Capella/simplified_api/requirement.py')
  if False:
      from simplified_api.requirement import *
      
  aird_path = '/TMS_test_5/TMS_test_5.aird'
  
  model = CapellaModel()
  model.open(aird_path)
  
  se = model.get_system_engineering()
  
  allLC = se.get_all_contents_by_type(LogicalComponent)
  
  allPVs = []
      
  print('start')
   
  def set_p_v_value(elem, PVName, value):
      for group in elem.get_java_object().getOwnedPropertyValueGroups():
          for pv in group.getOwnedPropertyValues():
              if PVName == pv.getName():
                  pv.setValue(value)
                  return
     
  for lc in allLC:
      for pvName in PVMT.get_p_v_names(lc):
          if pvName not in allPVs:
              allPVs.append(pvName)
              
  for lc in allLC:
      if lc.get_name() == 'TMS for Electrical drive train':
          print(lc.get_name())
          for pvName in allPVs:
              if pvName=='Mass':
                  set_p_v_value(lc,str(pvName),int(500))
                                
  print('end')

I am obtaining this error:

org.eclipse.ease.ScriptExecutionException: Traceback (most recent call last):
  File "workspace://test_1/test_5.py", line 58, in <module>
    Python object in all modules.
  File "workspace://test_1/test_5.py", line 43, in set_p_v_value
    _pyease_integer_types = (int,)
  File "C:\Users\Utente\Desktop\capella test 2\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\java_gateway.py", line 1321, in __call__
    return_value = get_return_value(
  File "C:\Users\Utente\Desktop\capella test 2\capella\plugins\py4j-python_0.10.9.5-bnd-2odeag\src\py4j\protocol.py", line 330, in get_return_value
    raise Py4JError(
py4j.protocol.Py4JError: An error occurred while calling o9470.setValue. Trace:
py4j.Py4JException: Method setValue([class java.lang.Integer]) does not exist
	at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:318)
	at py4j.reflection.ReflectionEngine.getMethod(ReflectionEngine.java:326)
	at py4j.Gateway.invoke(Gateway.java:274)
	at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
	at py4j.commands.CallCommand.execute(CallCommand.java:79)
	at py4j.ClientServerConnection.sendCommand(ClientServerConnection.java:244)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:384)
	at py4j.CallbackClient.sendCommand(CallbackClient.java:356)
	at py4j.reflection.PythonProxyHandler.invoke(PythonProxyHandler.java:106)
	at jdk.proxy12/jdk.proxy12.$Proxy25.executeScript(Unknown Source)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.internalExecute(Py4jScriptEngine.java:240)
	at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.execute(Py4jScriptEngine.java:227)
	at org.eclipse.ease.AbstractScriptEngine.inject(AbstractScriptEngine.java:189)
	at org.eclipse.ease.AbstractScriptEngine.run(AbstractScriptEngine.java:242)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

I honestly don’t know what is going wrong or where to look to fix it

Replacing in your function pv.setValue(value) with pv.setValue(float(value)) I get the same error that I reported yesterday (03/01)

	java.lang.IllegalStateException: Cannot modify resource set without a write transaction
		at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.assertWriting(TransactionChangeRecorder.java:349)
		at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.appendNotification(TransactionChangeRecorder.java:303)
		at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.processObjectNotification(TransactionChangeRecorder.java:285)
		at org.eclipse.emf.transaction.impl.TransactionChangeRecorder.notifyChanged(TransactionChangeRecorder.java:241)
		at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:424)
		at org.polarsys.capella.core.data.capellacore.impl.FloatPropertyValueImpl.setValue(FloatPropertyValueImpl.java:108)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
		at java.base/java.lang.reflect.Method.invoke(Method.java:568)
		at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
		at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
		at py4j.Gateway.invoke(Gateway.java:282)
		at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
		at py4j.commands.CallCommand.execute(CallCommand.java:79)
		at py4j.ClientServerConnection.sendCommand(ClientServerConnection.java:244)
		at py4j.CallbackClient.sendCommand(CallbackClient.java:384)
		at py4j.CallbackClient.sendCommand(CallbackClient.java:356)
		at py4j.reflection.PythonProxyHandler.invoke(PythonProxyHandler.java:106)
		at jdk.proxy12/jdk.proxy12.$Proxy25.executeScript(Unknown Source)
		at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.internalExecute(Py4jScriptEngine.java:240)
		at org.eclipse.ease.lang.python.py4j.internal.Py4jScriptEngine.execute(Py4jScriptEngine.java:227)
		at org.eclipse.ease.AbstractScriptEngine.inject(AbstractScriptEngine.java:189)
		at org.eclipse.ease.AbstractScriptEngine.run(AbstractScriptEngine.java:242)
		at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

I was just searching for possible solutions and maybe this error is related

Yes you was not passing the right type.

To modify the Capella model you need to create a transaction:

#declare and open the Capella model
model = CapellaModel()
model.open(aird_path)

# start a transaction to modify the Capella model
model.start_transaction()
try:
    # code modifying the Capella model
except:
    # if something went wrong we rollback the transaction
    model.rollback_transaction()
    raise
else:
    # if everything is ok we commit the transaction
    model.commit_transaction()

You can find an example in this script for instance.