# Creating thousands of simulated tags?

**URL:** <https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115>\
**Category:** Ignition\
**Created:** [March 11, 2024, 11:24am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115 "2024-03-11T11:24:38Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 11, 2024, 11:24am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/1 "2024-03-11T11:24:38Z")

</div>

Hi,

We would love to test our Apache IoTDB Tag Historian module under more usual loads for IoTDB and therefore would love to create something round 500000 tags that we can store in IoTDB. I know there are the simulated devices available, but creating so many tags would take for ever to setup.

Is there a way to create a large number of simulated tags for load testing? (Maybe even using an external process on a separate device)

Chris

---

<div class="post-metadata">

**Author:** ![Hayden\_Watson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/hayden_watson/32/48792_2.png) [@Hayden\_Watson](https://forum.inductiveautomation.com/u/Hayden_Watson)\
**Post date:** [March 11, 2024, 11:27am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/2 "2024-03-11T11:27:09Z")

</div>

If I remember right the programmable device simulator can be generated from a CSV, maybe can write a script to generate a massive CSV for you to then generate these?

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 11, 2024, 11:29am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/3 "2024-03-11T11:29:46Z")

</div>

Hi Hayden,

that sounds like a reasonable plan ... and running a CSV would probably reduce the load of generating hundreds of thousands of simulated devices.

Do you have any pointers to this programmable device simulator?

Chris

---

<div class="post-metadata">

**Author:** ![Hayden\_Watson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/hayden_watson/32/48792_2.png) [@Hayden\_Watson](https://forum.inductiveautomation.com/u/Hayden_Watson)\
**Post date:** [March 11, 2024, 11:35am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/4 "2024-03-11T11:35:06Z")

</div>

> **[Programmable Device Simulator | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/ignition-modules/opc-ua/opc-ua-drivers/programmable-device-simulator)**
>
> The Programmable Device Simulator allows you to add simulator devices that act as if they are connected to a real device. It allows users to read and write Tags without any network or PLC connection.

Probably best adding some tags on the interface, then exporting the CSV to get the format right. Write a script to generate a load more tags, then reimport it.

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 11, 2024, 12:12pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/5 "2024-03-11T12:12:23Z")

</div>

Hi Hayden,

thanks for that ... I was already watching the video ... helps a lot 😉

Chris

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 11, 2024, 12:25pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/6 "2024-03-11T12:25:37Z")

</div>

One thing however that I don't see, is that in this I can setup loads of tags for the OPC-UA simulator device, however in order to make this data go to the tag-historian, I usually need to go to the graphical editor, create an ignition tag, select the OPC-UA tag as source and then configure it to go to my historian.

I can't see this part being "automatable".

Do you have any idea how I could programm creating these simulated tags going to the historian?

---

<div class="post-metadata">

**Author:** ![Kevin.Herron](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kevin.herron/32/7259_2.png) [@Kevin.Herron](https://forum.inductiveautomation.com/u/Kevin.Herron)\
**Post date:** [March 11, 2024, 12:30pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/7 "2024-03-11T12:30:14Z")

</div>

Bulk/programmatic creation via [system.tag.configure | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-tag/system-tag-configure)

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [March 11, 2024, 12:32pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/8 "2024-03-11T12:32:22Z")

</div>

Most advanced Ignition users would write a jython script to instantiate many tags with `system.tag.configure()`. It would be most efficient if done with a UDT that has many member tags, preset to historize to your new historian, preferably expression tags that generate some pseudo-random or cyclic data.

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 11, 2024, 12:38pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/9 "2024-03-11T12:38:35Z")

</div>

Aaaaah ... that sounds a lot more interesting 😉

I'll look into it ... thanks for the pointers.

Chris

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 12, 2024, 8:54am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/10 "2024-03-12T08:54:19Z")

</div>

Hmpf ... why can't anything I'm trying to do be simple?  
So ... I've been struggling a bit as it seems that if I browse tags the ones with history only have an "attribute" of "history" (or something similar). if I browse the historic tags I get only the history settings ... so what I tried doing, is go through the tags and look for the ones with "history" attribute, then browseHistoricTags using the path I got there ... unfortunately I keep on getting errors that "system" is not defined. Even if I use the example on this page:

> **[system.tag.browseHistoricalTags | Ignition User Manual](https://docs.inductiveautomation.com/docs/8.1/appendix/scripting-functions/system-tag/system-tag-browseHistoricalTags#description)**
>
> Will browse for any historical Tags at the provided historical path.

Has anything changed? It seems as soon as I use "system" inside a locally defined function, I get the errors.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [March 12, 2024, 9:00am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/11 "2024-03-12T09:00:45Z")

</div>

This error usually comes from scoping issues. Where exactly are your "locally defined functions" ?

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 12, 2024, 9:16am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/12 "2024-03-12T09:16:46Z")

</div>

I just added a script to gateway event of "timer" and if I simply paste the example:

```python
def browse(path='histprov:DB:/drv:controller:default:/tag:simulator'):
    for result in system.tag.browseHistoricalTags(path).getResults():
        print result.getPath()
        if result.hasChildren():
            browse(result.getPath())
browse()

```

I get that error.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [March 12, 2024, 9:46am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/13 "2024-03-12T09:46:50Z")

</div>

Gateway events have weird scoping rules, inherited from older versions. Don't code there.  
Instead, put your code in the script library, and call it from the gateway event.

---

<div class="post-metadata">

**Author:** ![Aizhigit\_Mussali](https://avatars.discourse-cdn.com/v4/letter/a/f0a364/32.png) [@Aizhigit\_Mussali](https://forum.inductiveautomation.com/u/Aizhigit_Mussali)\
**Post date:** [March 12, 2024, 9:52am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/14 "2024-03-12T09:52:08Z")

</div>

Alternatively, you can generate many instances of a UDT with  
[UDT Multi-Instance Wizard | Ignition User Manual (inductiveautomation.com)](https://docs.inductiveautomation.com/docs/8.1/platform/tags/user-defined-types-udts/udt-multi-instance-wizard)

---

<div class="post-metadata">

**Author:** ![bschroeder](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bschroeder/32/13260_2.png) [@bschroeder](https://forum.inductiveautomation.com/u/bschroeder)\
**Post date:** [March 12, 2024, 11:06am UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/15 "2024-03-12T11:06:27Z")

</div>

Yep... gateway events should be a single line callout to a project library script.

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 12, 2024, 12:05pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/16 "2024-03-12T12:05:44Z")

</div>

Well I gave up on the whole script things as I thought I'd need to invest quite a bit of time to find out how to do it ... instead I wrote a little program, that generates a json file that has a configurable number of historian tags in them. With this I was able to test my Apache IoTDB historian with 161000 tags ... guess when importing another 500000 I was a bit greedy ... now the UI application doesn't seem to like me anymore 😉

Here's the code for my little tool:

```python
package com.timecho.iotdb.ignition.tools.taggenerator;

import java.io.PrintStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Random;

public class TagGenerator {

    static Device[] devices = {
            new Device("Realistic0", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic0", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic1", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic1", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic2", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic2", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic3", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic3", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic4", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic4", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic5", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic5", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic6", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic6", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic7", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic7", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic8", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic8", "Float8", "Ignition OPC UA Server"),
            new Device("Realistic9", "AtomicTag", "opc", "ns=1;s=[Sample_Device]_Meta:Realistic/Realistic9", "Float8", "Ignition OPC UA Server")
    };

    public static void main(String[] args) throws Exception {
        Random random = new Random();

        if(args.length < 2 || args.length > 3) {
            System.out.println("Usage: TagGenerator {num-total-tags} {num-tags-per-folder} ({output-file-name})");
        }

        int numTags = Integer.parseInt(args[0]);
        int numTagsForFolder = Integer.parseInt(args[1]);

        PrintStream out = System.out;
        if(args.length == 3) {
            out = new PrintStream(Files.newOutputStream(Paths.get(args[2])));
        }

        int folderIndex = 0;

        out.printf(
                        "{\n" +
                        " \"tags\": [\n" +
                        " {\n" +
                        " \"name\": \"Benchmark%08d\",\n" +
                        " \"tagType\": \"Folder\",\n" +
                        " \"tags\": [\n", folderIndex);

        int curNumTagsInFolder = 0;
        for(int i = 0; i < numTags; i++) {
            int deviceIndex = random.nextInt(10);
            Device curDevice = devices[deviceIndex];
            out.printf(" {\n" +
                    " \"valueSource\": \"%s\",\n" +
                    " \"opcItemPath\": \"%s\",\n" +
                    " \"dataType\": \"%s\",\n" +
                    " \"historyProvider\": \"Apache IoTDB History Provider\",\n" +
                    " \"name\": \"BenchmarkTag%08d\",\n" +
                    " \"historyEnabled\": true,\n" +
                    " \"tagType\": \"%s\",\n" +
                    " \"opcServer\": \"%s\"\n" +
                    " }%s\n", curDevice.getValueSource(), curDevice.getOpcItemPath(), curDevice.getDataType(),
                    curNumTagsInFolder,
                    curDevice.getTagType(), curDevice.getOpcServer(),
                    (curNumTagsInFolder == numTagsForFolder || i == (numTags - 1)) ? "" : ",");

            curNumTagsInFolder++;
            if(curNumTagsInFolder > numTagsForFolder) {
                curNumTagsInFolder = 0;
                folderIndex++;
                out.printf(
                        " ]\n" +
                        " },\n" +
                        " {\n" +
                        " \"name\": \"Benchmark%08d\",\n" +
                        " \"tagType\": \"Folder\",\n" +
                        " \"tags\": [\n", folderIndex);
            }
        }

        out.print(
                " ]\n" +
                " }\n" +
                " ]\n" +
                "}\n");

        if(out != System.out) {
            out.flush();
            out.close();
        }
    }

}

```

It's not super battle proven ... I guess there are probably edge-cases, that make it produce invalid JSON, but I didn't run into any issues.

---

<div class="post-metadata">

**Author:** ![christofer.dutz](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/christofer.dutz/32/76634_2.png) [@christofer.dutz](https://forum.inductiveautomation.com/u/christofer.dutz)\
**Post date:** [March 12, 2024, 1:11pm UTC](https://forum.inductiveautomation.com/t/creating-thousands-of-simulated-tags/87115/17 "2024-03-12T13:11:37Z")

</div>

![20240312-140034](https://us1.discourse-cdn.com/inductiveautomation/original/3X/9/7/97d1ef491bad0b5c4829f12f8fe661268fa338c2.jpeg)

Still seems to be running stable ...
