# Save machine count on each change of run status

**URL:** <https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492>\
**Category:** Ignition\
**Created:** [April 14, 2022, 9:58pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492 "2022-04-14T21:58:25Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 14, 2022, 9:58pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/1 "2022-04-14T21:58:25Z")

</div>

I would like the machine cycle count to be recorded in the historian on each change from run to stop and from stop to run. This will allow me to create accurate XY Charts for each machine with good accuracy and minimum data handling. How should I do this efficiently?

- The tag editor allows history sample mode to be set to _Tag Group_ but this would require me to create individual tag groups for each machine’s run-status signal. I’d also need to create a duplicate tag for the live count. This doesn’t seem right.
- Transaction groups would require one per machine with the trigger using my run-status tag.

Both seem messy. What trick am I missing?

---

<div class="post-metadata">

**Author:** ![josborn](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@josborn](https://forum.inductiveautomation.com/u/josborn)\
**Post date:** [April 14, 2022, 10:03pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/2 "2022-04-14T22:03:58Z")

</div>

Another option is to use a gateway tag change script to write the data to your own tables. Personally i like this method, you get a lot of flexibility this way.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 14, 2022, 10:51pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/3 "2022-04-14T22:51:04Z")

</div>

Ooooh, @josborn! That’s something I hadn’t considered and can see the advantage.

Can you give me a kick-start on this?

- I’ve created a gateway _Tag Change_ event script triggered by the machine’s run-status.
- I’ve added the code,

```auto
paths = ["[default]path/to/tag"]
value = system.tag.readBlocking(paths)

```

Now how do I write that to my history table? (I’ve had a quick look through the manual but haven’t found an example yet.)  
Can I make a performance gain by making a dedicated historian for this data? (I’d like my production charts to be fairly snappy.)

Many thanks.

---

<div class="post-metadata">

**Author:** ![josborn](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@josborn](https://forum.inductiveautomation.com/u/josborn)\
**Post date:** [April 14, 2022, 11:05pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/4 "2022-04-14T23:05:39Z")

</div>

Well doing it this way doesnt involve historian at all, which is a downside since you don’t have access to any of the nice things historian has built in. I can give you an example where i am logging multiple tags on each event trigger, It will probably get you started.

```auto
	tagPath = ["[default]ION/ION_Admin_KWH",
			"[default]ION/ION_Ag_KWH",
			"[default]ION/ION_CMP_Chiller/KWH_TOT",
			"[default]ION/ION_CMP_KWH",
			"[default]ION/ION_DayCareCenter_KWH",
			"[default]ION/ION_EOC_KWH",
			"[default]ION/ION_Fiscal_KWH",
			"[default]ION/ION_HOJ_KWH",
			"[default]ION/ION_HumanServices_KWH",
			"[default]ION/ION_ISD/KWH_TOT",
			"[default]ION/ION_MADF/KWH_TOT",
			"[default]ION/ION_PRMD_KWH",
			"[default]ION/ION_Sheriff/KWH_TOT"]
	values = system.tag.readBlocking(tagPath)

	for x in range(len(tagPath)):
		system.db.runPrepUpdate("INSERT INTO kwh_log (tag, value) VALUE (?, ?)", [tagPath[x], values[x].value], "ION_MeterData")

```

Edit:  
I think there is actually a way to use historian, ive never tried it though:  
[https://docs.inductiveautomation.com/display/DOC81/system.tag.storeTagHistory](https://docs.inductiveautomation.com/display/DOC81/system.tag.storeTagHistory)

---

<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:** [April 15, 2022, 1:56am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/5 "2022-04-15T01:56:09Z")

</div>

What y’all are describing is a scripted re-implementation of the SQL Bridge module’s transaction group. The key is the use of a wide table, where multiple values are recorded together. In this case, triggered by a state change.

---

<div class="post-metadata">

**Author:** ![josborn](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@josborn](https://forum.inductiveautomation.com/u/josborn)\
**Post date:** [April 15, 2022, 1:58am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/6 "2022-04-15T01:58:00Z")

</div>

> [@pturmel](#):
>
> The key is the use of a wide table

Im curious about this, as i use this approach but with Tall tables.

---

<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:** [April 15, 2022, 2:05am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/7 "2022-04-15T02:05:35Z")

</div>

To do this with tall tables you must ensure the values are actually collected together in a synchronized way (like a transaction’s OPC read mode) and are stored with identical timestamps. Then pivot (or scripted pseudo-pivot) to re-assemble them later into a correlated row.

With a wide table, storage and retrieval are natural SQL insert and select.

Search this forum for “tall versus wide” for more discussions. Each has their strengths.

---

<div class="post-metadata">

**Author:** ![josborn](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@josborn](https://forum.inductiveautomation.com/u/josborn)\
**Post date:** [April 15, 2022, 2:06am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/8 "2022-04-15T02:06:20Z")

</div>

That makes sense, appreciate the insight.

Though if @Transistor intends to use `system.tag.storeTagHistory` that would mean sticking with Tall tables I suppose.

---

<div class="post-metadata">

**Author:** ![bmusson](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/bmusson/32/87530_2.png) [@bmusson](https://forum.inductiveautomation.com/u/bmusson)\
**Post date:** [April 15, 2022, 4:05am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/9 "2022-04-15T04:05:31Z")

</div>

If you need retrieve multiple values with identical time stamps, don’t use the tag historian.

---

<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:** [April 15, 2022, 7:57am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/10 "2022-04-15T07:57:43Z")

</div>

My usual nitpick about `range(len())`:

```python
paths = [...]
tags = system.tag.readBlocking(paths)

for path, tag in zip(paths, tags):
	system.db.runPrepUpdate("INSERT INTO kwh_log (tag, value) VALUE (?, ?)", [path, tag.value], "ION_MeterData")

```

And then it’s @pturmel’s turn, to tell you he’d build a prep query and insert everything in just one call. Listen to Phil.

---

<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:** [April 15, 2022, 11:59am UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/11 "2022-04-15T11:59:03Z")

</div>

Ah, @pascal.fragnoud, I wouldn’t want to deprive you of the opportunity to expound on efficient code techniques… 😇

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 15, 2022, 12:01pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/12 "2022-04-15T12:01:28Z")

</div>

> [@pturmel](#):
>
> ... and are stored with identical timestamps.

Thanks, Phil. You explained this to me well in a previous question.

In this case I don't need simultaneous timestamps. Each machine will start and stop independently so a tall table layout works fine.

---

<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:** [April 15, 2022, 12:08pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/13 "2022-04-15T12:08:44Z")

</div>

But you do need simultaneous timestamps, to keep the run/stop state and count together. Yes, two variables and a timestamp is not very “wide”, but the concept is the same.

---

<div class="post-metadata">

**Author:** ![peter](https://avatars.discourse-cdn.com/v4/letter/p/278dde/32.png) [@peter](https://forum.inductiveautomation.com/u/peter)\
**Post date:** [April 15, 2022, 2:31pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/14 "2022-04-15T14:31:33Z")

</div>

This is more of a philosophical question, but if the machine is stopped, how can the run count change?

So why is there a need to record the run count on the transition from stop to run? or is it that you don’t trust your communications tooth machine and are trying to account for the machine running when you are not aware of it running?

Note that personally I’d still record teh count on both transitions, because I like redundancy 😉

---

<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:** [April 15, 2022, 2:32pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/15 "2022-04-15T14:32:33Z")

</div>

Processor uploads/downloads disturbing the PLC’s contents.

---

<div class="post-metadata">

**Author:** ![josborn](https://avatars.discourse-cdn.com/v4/letter/j/4bbf92/32.png) [@josborn](https://forum.inductiveautomation.com/u/josborn)\
**Post date:** [April 15, 2022, 3:49pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/16 "2022-04-15T15:49:15Z")

</div>

My implementation of this is logging every 15 minutes, and i truly only care about the first and last reading each month, this is sufficient.

---

<div class="post-metadata">

**Author:** ![Transistor](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/transistor/32/3380_2.png) [@Transistor](https://forum.inductiveautomation.com/u/Transistor)\
**Post date:** [April 15, 2022, 7:18pm UTC](https://forum.inductiveautomation.com/t/save-machine-count-on-each-change-of-run-status/58492/17 "2022-04-15T19:18:18Z")

</div>

> [@peter](#):
>
> ... but if the machine is stopped, how can the run count change?

It doesn't, but recording the count at both transitions makes the XY chart very simple to implement.

![Machine cycle count chart](https://us1.discourse-cdn.com/inductiveautomation/original/3X/8/2/82788748d82eb4e2864dc7615c08d5bd29d9021a.png)

_Mock-up of Perspective template (done in Word). Recording counts at 1 and 2 makes graphing simple and accurate._
