# How to set the tag quality in Python scripting in the WebDev module?

**URL:** <https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030>\
**Category:** Ignition\
**Created:** [April 29, 2022, 6:48am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030 "2022-04-29T06:48:26Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [April 29, 2022, 6:48am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/1 "2022-04-29T06:48:26Z")

</div>

Hello,

Is there a way to set the tag quality? In particular in Python scripting in the WebDev module.

[https://docs.inductiveautomation.com/display/DOC81/Quality+Codes+and+Overlays](https://docs.inductiveautomation.com/display/DOC81/Quality+Codes+and+Overlays)

I was thinking of using the following system function but could not find a way.

[https://docs.inductiveautomation.com/display/DOC81/system.tag.configure](https://docs.inductiveautomation.com/display/DOC81/system.tag.configure)

The idea is that an external system will set the tag quality to bad (or uncertain) based on external conditions.

Thanks,

Simon.

---

<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 29, 2022, 8:02am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/2 "2022-04-29T08:02:20Z")

</div>

You can pass a qualified value to the `system.tag.write*` functions.  
You can make a qualified value from [`BasicQualifiedValue`](http://files.inductiveautomation.com/sdk/javadoc/ignition80/8.0.0-beta/com/inductiveautomation/ignition/common/model/values/BasicQualifiedValue.html), which takes up to 3 arguments: a value, a quality, and a timestamp.  
If you pass one of those to a `system.tag.write*` function, only the specified arguments will be used to modify the tag.

```python
from com.inductiveautomation.ignition.common.model.values import BasicQualifiedValue, QualityCode

qval = BasicQualifiedValue(quality=QualityCode.Bad)
system.tag.writeBlocking([tag_path], [qval])

```

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 2, 2022, 8:40am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/3 "2022-05-02T08:40:50Z")

</div>

Thanks!

I would like to create a generic API that can be used to set tag value, quality etc.

If I display `qval` I get the following value:

```auto
qval = '{ "quality": { "code": -2147483136 }, "timestamp": "May 2, 2022, 10:08:12 AM" }'

```

Is it also possible to do something like: (and set the qval in the body)

```auto
qval = '{ "quality": { "code": -2147483136 }, "timestamp": "May 2, 2022, 10:08:12 AM" }'
system.tag.writeBlocking([tag_path], [qval])

```

This does not seem to work?

---

<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:** [May 2, 2022, 8:49am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/4 "2022-05-02T08:49:29Z")

</div>

That’s not a valid format for a qualified value. Build it using `BasicQualifiedValue()` instead.  
There’s already a generic function that allows setting values, qualities and timestamp: `system.tag.write*` functions ;p

---

<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:** [May 2, 2022, 9:14am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/5 "2022-05-02T09:14:07Z")

</div>

Wait, I’m sorry, I think I was wrong: Passing a qval without a value doesn’t retain the initial value of the tag. I thought I tested this, but it seems I missed something.  
I just tried it again, and forcing a bad quality on a tag, then forcing it back to good, results in a `null` value.

You’ll have to read the tag’s value and pass it to `BasicQualifiedValue(value, quality)`

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 2, 2022, 9:19am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/6 "2022-05-02T09:19:29Z")

</div>

Ah right, thanks for testing. Apart from this…

So there is no way to pass the quality to `writeBlocking` as a JSON value so I can pass it into the body? I always have to use `BasicQualifiedValue`?

I had this generic API defined on WebDev and was hoping I could also use it to set the quality:

```auto
	paths = request['data']['paths']
	values = request['data']['values']

	result = system.tag.writeBlocking(paths, values)
	
	return {'json': result}

```

Body:

```auto
{
    "paths": [
        "[SolidRed]/TT-111-11-11/ARF8200AA/DeviceEUI",
        "[SolidRed]/TT-111-11-11/ARF8200AA/HealthOK",
        "[SolidRed]/TT-111-11-11/ARF8200AA/LastSeen",
        "[SolidRed]/TT-111-11-11/ARF8200AA/MeasuredCurrentMicroA"
        ],
    "values": [
        "TT6482921",
        false,
        "2012-04-21 18:25:43",
        "2892.1519"
        ]
}

```

---

<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:** [May 2, 2022, 9:36am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/7 "2022-05-02T09:36:53Z")

</div>

Import `BasicQualifiedValue` and `QualityCode` in your function, pass the wanted quality name in your body’s json, then change your function slightly:

```python
paths = request['data']['paths']
values = request['data']['values']
qualities = request['data']['qualities']
qvals = [BasicQualifiedValue(value, getattr(QualityCode, quality, 'Uncertain')) for value, quality in zip(values, qualities)]

system.tag.writeBlocking(paths, qvals)

```

---

<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:** [May 2, 2022, 2:20pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/8 "2022-05-02T14:20:09Z")

</div>

> [@Simon.de.Kraa](#):
>
> So there is no way to pass the quality to `writeBlocking` as a JSON value so I can pass it into the body?

No.

> [@Simon.de.Kraa](#):
>
> I always have to use `BasicQualifiedValue` ?

Yes. Or any other specialized implementation of `QualifiedValue` you might encounter.

The whole point of the WebDev module is to translate web requests (where json is popular) to Ignition's java APIs (where json is fringe), and to translates results from java APIs back to web-friendly formats. Ignition is fundamentally Java, not javascript.

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 2, 2022, 6:37pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/9 "2022-05-02T18:37:58Z")

</div>

BTW

About the `null` value when the quality is set to `BAD`:

[https://opcfoundation.org/forum/opc-ua-standard/usage-of-bad-opcqualitycode/](https://opcfoundation.org/forum/opc-ua-standard/usage-of-bad-opcqualitycode/)

I think this is intended behavior…

---

<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:** [May 2, 2022, 7:06pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/10 "2022-05-02T19:06:59Z")

</div>

It might, but this is not always the required behavior… In which case, passing a value when constructing the qualified value does the job.  
I do it for an array of different qualities, some of which aren’t plain bad and need to be able to be restored to good and retain their original values.

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 2, 2022, 8:29pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/11 "2022-05-02T20:29:31Z")

</div>

Yes, I guess you are right. I just noticed that if you set the quality to `UNCERTAIN`, the value is also set to `null`.

Any idea how I can get the current values and feed them to the write?

Really sorry for asking… And about my Python skills… This is getting awkward… 🤪

```auto
	paths = request['data']['paths']
	values = system.tag.readBlocking(paths)
	qualities = request['data']['qualities']
	qvals = [BasicQualifiedValue(value, getattr(QualityCode, quality, 'Uncertain')) for value, quality in zip(values, qualities)]
	
	result = system.tag.writeBlocking(paths, qvals)

	return {'json': result}

```

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 2, 2022, 8:36pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/12 "2022-05-02T20:36:32Z")

</div>

The `QualifiedValue` interface defines a `derive(QualityCode)` method, so you can construct your new QVs like this:

```auto
	qualities = request['data']['qualities']
	qvals = [qv.derive(getattr(QualityCode, quality, 'Uncertain')) for qv, quality in zip(values, qualities)]

```

`derive()` copies the current value into the new QualifiedValue object.

---

<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:** [May 3, 2022, 7:40am UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/13 "2022-05-03T07:40:28Z")

</div>

Is that any different than building a qualified value and passing it the value directly ?

```python
qval = BasicQualifiedValue(value, quality)

```

In your example, the values passed to `zip(values, qualities)` have to be qualified values already, which he doesn't have if he's passing values through a request body json, so he'd still have to be building the qvals. Derive would only help if he was reading the values with a `system.tag.read*` function, right ?

> [@Simon.de.Kraa](#):
>
> Any idea how I can get the current values and feed them to the write?

I thought you were receiving the values through a json ?

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 3, 2022, 12:59pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/14 "2022-05-03T12:59:06Z")

</div>

> [@pascal.fragnoud](#):
>
> I thought you were receiving the values through a json ?

Well, for setting the quality to e.g. `Uncertain` I would like to keep the existing value. I do not want to send the values through the body because I don't know the values beforehand. I just want to set the quality and preserving the current value.

```auto
{
    "paths": [
        "[SolidRed]/Path/To/Device/MyString"
    ],
    "qualities": [
        "Uncertain"
    ]
}

```

So I tried getting the current values using `system.tag.readBlocking` and passing the output to `system.tag.writeBlocking` later on.

```auto
	from com.inductiveautomation.ignition.common.model.values import BasicQualifiedValue, QualityCode
	
	paths = request['data']['paths']	
	values = system.tag.readBlocking(paths)
	qualities = request['data']['qualities']	
	qvals = [qv.derive(getattr(QualityCode, quality, 'Uncertain')) for qv, quality in zip(values, qualities)]
	
    result = system.tag.writeBlocking(paths, qvals)
    
	return {'json': result}

```

But then I get the following error.

```auto
HTTP ERROR 501 Not Implemented

```

---

<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:** [May 3, 2022, 1:10pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/15 "2022-05-03T13:10:36Z")

</div>

> [@Simon.de.Kraa](#):
>
> Well, for setting the quality to e.g. `Uncertain` I would like to keep the existing value. I do not want to send the values through the body because I don’t know the values beforehand

What if the quality is good ? Your original json did have values, I thought you'd be using those.

I'm not familiar with WebDev, but this looks like an issue with your endpoint. Is `{'json': result}` a proper response ?

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 3, 2022, 1:31pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/16 "2022-05-03T13:31:56Z")

</div>

In the example below, for the last update I only want to set the quality and keep the last value. I do not want to send over the value again (because I do not know it; I just want to invalidate the value by setting the quality).

```auto
Value Quality Message
1 Good Path, Value
2 Good Path, Value
4 Good Path, Value
1 Good Path, Value
1 Uncertain Path, Quality

```

Yes, `return {'json': result}` is a valid response.

Similar script for creating tags is as follows:

```auto
	basePath = request['data']['basePath']
	tags = request['data']['tags']
	collisionPolicy = request['data']['collisionPolicy']

	result = system.tag.configure(basePath, tags, collisionPolicy)

	return {'json': result}

```

---

<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:** [May 3, 2022, 1:37pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/17 "2022-05-03T13:37:36Z")

</div>

> [@Simon.de.Kraa](#):
>
> In the example below, for the last update I only want to set the quality and keep the last value. I do not want to send over the value again (because I do not know it; I just want to invalidate the value by setting the quality).
> 
> ```auto
> Value Quality Message
> 1 Good Path, Value
> 2 Good Path, Value
> 4 Good Path, Value
> 1 Good Path, Value
> 1 Uncertain Path, Quality
> 
> ```

Where do the values come from for the first 4 rows then ?  
It all seemed clear in the beginning and now I'm getting confused...

---

<div class="post-metadata">

**Author:** ![Simon.de.Kraa](https://avatars.discourse-cdn.com/v4/letter/s/82dd89/32.png) [@Simon.de.Kraa](https://forum.inductiveautomation.com/u/Simon.de.Kraa)\
**Post date:** [May 3, 2022, 2:08pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/18 "2022-05-03T14:08:46Z")

</div>

I can imagine. Sorry about that.

I have a couple of HTTP methods defined for CRUD of tags. See below the resource `tag`. This works as expected. This is what we talked about earlier. Like e.g. when I update a tag I provide the paths and values. When I read the tag I only provide the paths. And so on...

What I would like to do is to add a resource to update the tag quality. In the example below the resource is called `setTagQuality`. I believe that I only need to (and can) provide the paths and qualities.

Suppose a tag is updated every 30 seconds and the latest value is 4. If the tag is not updated for let's say 60 seconds I want to set the quality to `Uncertain` and keep the latest value of 4. Note that I do not have this value ready anymore so I cannot send it in the body of the API call. It is stored in the tag value itself. So I think I need to retrieve it using `system.tag.read*` and afterwards write it using `system.tag.write*`.

* * *

# setTagQuality

## Update

```python
def doPut(request, session):
  from com.inductiveautomation.ignition.common.model.values import BasicQualifiedValue, QualityCode
  paths = request['data']['paths']	
  values = system.tag.readBlocking(paths)
  qualities = request['data']['qualities']	
  qvals = [qv.derive(getattr(QualityCode, quality, 'Uncertain')) for qv, quality in zip(values, qualities)]	
  result = system.tag.writeBlocking(paths, qvals)  
  return {'json': result}

```

* * *

# tag

## Create

```python
def doPost(request, session):
  basePath = request['data']['basePath']
  tags = request['data']['tags']
  collisionPolicy = request['data']['collisionPolicy']
  result = system.tag.configure(basePath, tags, collisionPolicy)
  return {'json': result}

```

Details about system.tag.configure can be found [here](https://docs.inductiveautomation.com/display/DOC80/system.tag.configure).

## Read

```python
def doGet(request, session):
  values = system.tag.readBlocking(request['data']['paths'])
  return {'json': values}

```

Details about system.tag.readBlocking can be found [here](https://docs.inductiveautomation.com/display/DOC80/system.tag.readBlocking).

## Update

```python
def doPut(request, session):
  paths = request['data']['paths']
  values = request['data']['values']
  result = system.tag.writeBlocking(paths, values)
  return {'json': result}

```

Details about system.tag.writeBlocking can be found [here](https://docs.inductiveautomation.com/display/DOC80/system.tag.writeBlocking).

## Delete

```python
def doDelete(request, session):
  paths = request['data']['paths']
  result = system.tag.deleteTags(paths)
  return {'json': result}

```

Details about system.tag.deleteTags can be found [here](https://docs.inductiveautomation.com/display/DOC80/system.tag.deleteTags).

---

<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:** [May 3, 2022, 2:19pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/19 "2022-05-03T14:19:36Z")

</div>

Alright. So, indeed, you’ll have to read the values from the tags. The script you have there should work.  
If sending a PUT request to your endpoint returns an error, I think it comes from your endpoint configuration.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [May 3, 2022, 2:26pm UTC](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030/20 "2022-05-03T14:26:51Z")

</div>

I’m not sure if this actually works, but can you write a quality code directly to the .Quality property node?  
That is - `system.tag.writeBlocking(["path/to/tag.quality"], [qualityCode])`. No need to read and derive in that case.

[Next page](https://forum.inductiveautomation.com/t/how-to-set-the-tag-quality-in-python-scripting-in-the-webdev-module/59030.md?page=2)
