I’m pretty sure we bumped into the same thing in Ignition 8.1.7. I whittled it down to a simple test case.
If I have a dataset stored in a tag at [default]sandbox/testds
, this code will work:
src_path = '[default]sandbox/testds'
dst_path = '[default]sandbox'
dst_name = 'goodds'
src_config = system.tag.getConfiguration(src_path, False)[0]
dst_config = dict()
dst_config['valueSource'] = src_config['valueSource']
dst_config['dataType'] = src_config['dataType']
dst_config['name'] = dst_name
dst_config['value'] = src_config['value']
dst_config['tagType'] = src_config['tagType']
system.tag.configure(dst_path, [dst_config], 'a')
But this code will fail:
src_path = '[default]sandbox/testds'
dst_path = '[default]sandbox'
dst_name = 'badds'
src_config = system.tag.getConfiguration(src_path, False)[0]
for x in src_config:
if x not in ['valueSource', 'dataType', 'name', 'value', 'tagType']:
src_config.pop(x)
src_config['name'] = dst_name
system.tag.configure(dst_path, [src_config], 'a')
The error is the same as others have shown:
java.lang.UnsupportedOperationException: Attempted to serialize java.lang.Class: java.lang.Boolean. Forgot to register a type adapter?
at com.inductiveautomation.ignition.common.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:73)
at com.inductiveautomation.ignition.common.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:69)
at com.inductiveautomation.ignition.common.gson.TypeAdapter$1.write(TypeAdapter.java:191)
at com.inductiveautomation.ignition.common.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.inductiveautomation.ignition.common.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:97)
at com.inductiveautomation.ignition.common.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:61)
at com.inductiveautomation.ignition.common.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.inductiveautomation.ignition.common.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:127)
at com.inductiveautomation.ignition.common.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:245)
at com.inductiveautomation.ignition.common.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.inductiveautomation.ignition.common.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:69)
at com.inductiveautomation.ignition.common.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:208)
at com.inductiveautomation.ignition.common.gson.internal.bind.MapTypeAdapterFactory$Adapter.write(MapTypeAdapterFactory.java:145)
at com.inductiveautomation.ignition.common.gson.Gson.toJson(Gson.java:704)
at com.inductiveautomation.ignition.common.gson.Gson.toJson(Gson.java:683)
at com.inductiveautomation.ignition.common.gson.Gson.toJson(Gson.java:638)
at com.inductiveautomation.ignition.common.gson.Gson.toJson(Gson.java:618)
at com.inductiveautomation.ignition.common.config.PyTagDictionary.toTagConfiguration(PyTagDictionary.java:122)
at com.inductiveautomation.ignition.common.config.PyTagDictionary.toTagConfiguration(PyTagDictionary.java:163)
at com.inductiveautomation.ignition.common.script.builtin.AbstractTagUtilities.dictToTagEdits(AbstractTagUtilities.java:191)
at com.inductiveautomation.ignition.common.script.builtin.AbstractTagUtilities.lambda$configure$0(AbstractTagUtilities.java:154)
at java.base/java.util.stream.ReferencePipeline$7$1.accept(Unknown Source)
at java.base/java.util.Iterator.forEachRemaining(Unknown Source)
at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.copyInto(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(Unknown Source)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(Unknown Source)
at java.base/java.util.stream.AbstractPipeline.evaluate(Unknown Source)
at java.base/java.util.stream.ReferencePipeline.collect(Unknown Source)
at com.inductiveautomation.ignition.common.script.builtin.AbstractTagUtilities.configure(AbstractTagUtilities.java:154)
at jdk.internal.reflect.GeneratedMethodAccessor58.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.java:188)
at com.inductiveautomation.ignition.common.script.ScriptManager$ReflectedInstanceFunction.__call__(ScriptManager.java:539)
at org.python.core.PyObject.__call__(PyObject.java:515)
at org.python.core.PyObject.__call__(PyObject.java:519)
at org.python.pycode._pyx168.f$0(<input>:18)
at org.python.pycode._pyx168.call_function(<input>)
at org.python.core.PyTableCode.call(PyTableCode.java:171)
at org.python.core.PyCode.call(PyCode.java:18)
at org.python.core.Py.runCode(Py.java:1614)
at org.python.core.Py.exec(Py.java:1658)
at org.python.util.PythonInterpreter.exec(PythonInterpreter.java:276)
at org.python.util.InteractiveInterpreter.runcode(InteractiveInterpreter.java:131)
at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:605)
at com.inductiveautomation.ignition.designer.gui.tools.jythonconsole.JythonConsole$ConsoleWorker.doInBackground(JythonConsole.java:593)
at java.desktop/javax.swing.SwingWorker$1.call(Unknown Source)
at java.base/java.util.concurrent.FutureTask.run(Unknown Source)
at java.desktop/javax.swing.SwingWorker.run(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
I’m confused as to what is different between the bad sample versus the good sample.
EDIT: And this one will work:
src_path = '[default]sandbox/testds'
dst_path = '[default]sandbox'
dst_name = 'newds'
src_config = system.tag.getConfiguration(src_path, False)[0]
dst_config = dict(src_config)
for x in dst_config:
if x not in ['valueSource', 'dataType', 'name', 'value', 'tagType']:
dst_config.pop(x)
dst_config['name'] = dst_name
system.tag.configure(dst_path, [dst_config], 'a')