Skip to content

Commit 1a673af

Browse files
committed
init added min tags functionality
1 parent 6e95176 commit 1a673af

File tree

3 files changed

+200
-1
lines changed

3 files changed

+200
-1
lines changed

kepconfig/adv_tags/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
specific objects within the Kepware Configuration API
99
"""
1010

11-
from . import adv_tag_group, average_tags, derived_tags, complex_tags, cumulative_tags
11+
from . import adv_tag_group, average_tags, derived_tags, complex_tags, cumulative_tags, min_tags
1212
ADV_TAGS_ROOT = '/project/_advancedtags'
1313

1414
def adv_tag_path_split(path: str, *, isItem=False) -> dict:

kepconfig/adv_tags/min_tags.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# -------------------------------------------------------------------------
2+
# Copyright (c) PTC Inc. and/or all its affiliates. All rights reserved.
3+
# See License.txt in the project root for
4+
# license information.
5+
# --------------------------------------------------------------------------
6+
7+
r"""`minimum_tags` exposes an API to allow modifications (add, delete, modify) to
8+
minimum tag objects within the Kepware Configuration API
9+
"""
10+
11+
from ..connection import server
12+
from ..error import KepError, KepHTTPError
13+
from ..utils import _url_parse_object
14+
from typing import Union
15+
from .. import adv_tags
16+
17+
MINIMUM_TAGS_ROOT = '/minimum_tags'
18+
19+
def _get_minimum_tags_url(tag: str = None) -> str:
20+
'''Creates url object for the "minimum_tags" branch of Kepware's project tree.
21+
22+
Returns the minimum tag specific url when a value is passed as the tag name.
23+
'''
24+
if tag is None:
25+
return MINIMUM_TAGS_ROOT
26+
else:
27+
return f'{MINIMUM_TAGS_ROOT}/{_url_parse_object(tag)}'
28+
29+
def add_minimum_tag(server: server, adv_tag_group_path: str, DATA: Union[dict, list]) -> Union[bool, list]:
30+
'''Add `"minimum_tag"` or multiple `"minimum_tag"` objects to a specific path in Kepware.
31+
Can be used to pass a list of minimum tags to be added at one path location.
32+
33+
:param server: instance of the `server` class
34+
:param adv_tag_group_path: path identifying where to add minimum tag(s). Standard Kepware address decimal
35+
notation string such as "_advancedtags.AdvTagGroup1" or "_advancedtags.AdvTagGroup1.AdvTagGroupChild"
36+
:param DATA: Dict or List of Dicts of the minimum tag(s) to add
37+
38+
:return: True - If a "HTTP 201 - Created" is received from Kepware server
39+
:return: If a "HTTP 207 - Multi-Status" is received from Kepware with a list of dict error responses for all
40+
minimum tags added that failed.
41+
42+
:raises KepHTTPError: If urllib provides an HTTPError
43+
:raises KepURLError: If urllib provides an URLError
44+
'''
45+
path_obj = adv_tags.adv_tag_path_split(adv_tag_group_path, isItem=False)
46+
url = adv_tags._create_adv_tags_base_url(server.url, path_obj) + _get_minimum_tags_url()
47+
48+
r = server._config_add(url, DATA)
49+
if r.code == 201:
50+
return True
51+
elif r.code == 207:
52+
errors = [item for item in r.payload if item['code'] != 201]
53+
return errors
54+
else:
55+
raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
56+
57+
def modify_minimum_tag(server: server, min_tag_path: str, DATA: dict, force: bool = False) -> bool:
58+
'''Modify a `"minimum_tag"` object and its properties in Kepware.
59+
60+
:param server: instance of the `server` class
61+
:param min_tag_path: path identifying location and minimum tag to modify. Standard Kepware address decimal
62+
notation string including the minimum tag such as "_advancedtags.AdvTagGroup1.MinTag1"
63+
:param DATA: Dict of the `minimum_tag` properties to be modified
64+
:param force: *(optional)* if True, will force the configuration update to the Kepware server
65+
66+
:return: True - If a "HTTP 200 - OK" is received from Kepware server
67+
68+
:raises KepHTTPError: If urllib provides an HTTPError
69+
:raises KepURLError: If urllib provides an URLError
70+
'''
71+
min_tag_data = server._force_update_check(force, DATA)
72+
path_obj = adv_tags.adv_tag_path_split(min_tag_path, isItem=True)
73+
url = adv_tags._create_adv_tags_base_url(server.url, path_obj) + _get_minimum_tags_url(path_obj['item'])
74+
75+
r = server._config_update(url, min_tag_data)
76+
if r.code == 200:
77+
return True
78+
else:
79+
raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
80+
81+
def del_minimum_tag(server: server, min_tag_path: str) -> bool:
82+
'''Delete `"minimum_tag"` object at a specific path in Kepware.
83+
84+
:param server: instance of the `server` class
85+
:param min_tag_path: path identifying location and minimum tag to delete. Standard Kepware address decimal
86+
notation string including the minimum tag such as "_advancedtags.AdvTagGroup1.MinTag1"
87+
88+
:return: True - If a "HTTP 200 - OK" is received from Kepware server
89+
90+
:raises KepHTTPError: If urllib provides an HTTPError
91+
:raises KepURLError: If urllib provides an URLError
92+
'''
93+
path_obj = adv_tags.adv_tag_path_split(min_tag_path, isItem=True)
94+
url = adv_tags._create_adv_tags_base_url(server.url, path_obj) + _get_minimum_tags_url(path_obj['item'])
95+
96+
r = server._config_del(url)
97+
if r.code == 200:
98+
return True
99+
else:
100+
raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
101+
102+
def get_minimum_tag(server: server, min_tag_path: str) -> dict:
103+
'''Returns the properties of the `"minimum_tag"` object at a specific path in Kepware.
104+
105+
:param server: instance of the `server` class
106+
:param min_tag_path: path identifying location and minimum tag to retrieve. Standard Kepware address decimal
107+
notation string including the minimum tag such as "_advancedtags.AdvTagGroup1.MinTag1"
108+
109+
:return: Dict of data for the minimum tag requested
110+
111+
:raises KepHTTPError: If urllib provides an HTTPError
112+
:raises KepURLError: If urllib provides an URLError
113+
'''
114+
path_obj = adv_tags.adv_tag_path_split(min_tag_path, isItem=True)
115+
url = adv_tags._create_adv_tags_base_url(server.url, path_obj) + _get_minimum_tags_url(path_obj['item'])
116+
117+
r = server._config_get(url)
118+
return r.payload
119+
120+
def get_all_minimum_tags(server: server, adv_tag_group_path: str, *, options: dict = None) -> list:
121+
'''Returns the properties of all `"minimum_tag"` objects at a specific path in Kepware.
122+
123+
:param server: instance of the `server` class
124+
:param adv_tag_group_path: path identifying location to retrieve minimum tag list. Standard Kepware address decimal
125+
notation string such as "_advancedtags.AdvTagGroup1" or "_advancedtags.AdvTagGroup1.AdvTagGroupChild"
126+
:param options: *(optional)* Dict of parameters to filter, sort or paginate the list of minimum tags. Options are `filter`,
127+
`sortOrder`, `sortProperty`, `pageNumber`, and `pageSize`
128+
129+
:return: List of data for all minimum tags
130+
131+
:raises KepHTTPError: If urllib provides an HTTPError
132+
:raises KepURLError: If urllib provides an URLError
133+
'''
134+
path_obj = adv_tags.adv_tag_path_split(adv_tag_group_path, isItem=False)
135+
url = adv_tags._create_adv_tags_base_url(server.url, path_obj) + _get_minimum_tags_url()
136+
137+
r = server._config_get(url, params=options)
138+
return r.payload

tests/adv_tags_test.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@
6161
}
6262
]
6363

64+
minimum_tag_name = 'MinimumTag1'
65+
minimum_tag_data = [
66+
{
67+
"common.ALLTYPES_NAME": minimum_tag_name,
68+
"common.ALLTYPES_DESCRIPTION": "",
69+
"advanced_tags.ENABLED": True,
70+
"advanced_tags.MINIMUM_TAG": "_System._Time_Hour",
71+
"advanced_tags.RUN_TAG": "_System._Time_Second"
72+
}
73+
]
74+
6475
def HTTPErrorHandler(err):
6576
if err.__class__ is error.KepHTTPError:
6677
print(err.code)
@@ -96,6 +107,15 @@ def complete(server: connection.server):
96107
for obj in obj_list:
97108
complex_tag_path = f'_advancedtags.{obj["name"]}'
98109
adv_tags.complex_tags.del_complex_tag(server, complex_tag_path)
110+
elif key == 'cumulative_tags':
111+
for obj in obj_list:
112+
cumulative_tag_path = f'_advancedtags.{obj["name"]}'
113+
adv_tags.cumulative_tags.del_cumulative_tag(server, cumulative_tag_path)
114+
elif key == 'minimum_tags':
115+
for obj in obj_list:
116+
minimum_tag_path = f'_advancedtags.{obj["name"]}'
117+
adv_tags.min_tags.del_minimum_tag(server, minimum_tag_path)
118+
99119
pass
100120

101121
@pytest.fixture(scope="module")
@@ -307,6 +327,47 @@ def test_cumulative_tag_del(server):
307327
cumulative_tag_path = f'_advancedtags.{adv_tag_group_name}.{cumulative_tag_name}'
308328
assert adv_tags.cumulative_tags.del_cumulative_tag(server, cumulative_tag_path)
309329

330+
def test_minimum_tag_add(server):
331+
# Add a minimum tag to the root advanced tag plug-in
332+
assert adv_tags.min_tags.add_minimum_tag(server, f'_advancedtags', minimum_tag_data)
333+
334+
testTag = {
335+
"common.ALLTYPES_NAME": "newMinimumTag",
336+
"common.ALLTYPES_DESCRIPTION": "",
337+
"advanced_tags.ENABLED": True,
338+
"advanced_tags.MINIMUM_TAG": "_System._Time_Hour",
339+
"advanced_tags.RUN_TAG": "_System._Time_Second"
340+
}
341+
minimum_tag_data.append(testTag)
342+
# Add a minimum tag to the advanced tag group
343+
assert adv_tags.min_tags.add_minimum_tag(server, f'_advancedtags.{adv_tag_group_name}', minimum_tag_data)
344+
345+
def test_minimum_tag_get(server):
346+
# Get the minimum tag
347+
minimum_tag_path = f'_advancedtags.{adv_tag_group_name}.{minimum_tag_name}'
348+
result = adv_tags.min_tags.get_minimum_tag(server, minimum_tag_path)
349+
assert type(result) == dict
350+
assert result.get("common.ALLTYPES_NAME") == minimum_tag_name
351+
352+
def test_minimum_tag_modify(server):
353+
# Modify the minimum tag
354+
minimum_tag_path = f'_advancedtags.{adv_tag_group_name}.{minimum_tag_name}'
355+
tag_data = {
356+
"common.ALLTYPES_DESCRIPTION": "Modified minimum tag"
357+
}
358+
assert adv_tags.min_tags.modify_minimum_tag(server, minimum_tag_path, tag_data, force=True)
359+
360+
def test_minimum_tag_get_all(server):
361+
# Get all minimum tags under the group
362+
result = adv_tags.min_tags.get_all_minimum_tags(server, f'_advancedtags.{adv_tag_group_name}')
363+
assert type(result) == list
364+
assert any(tag.get("common.ALLTYPES_NAME") == minimum_tag_name for tag in result)
365+
366+
def test_minimum_tag_del(server):
367+
# Delete the minimum tag
368+
minimum_tag_path = f'_advancedtags.{adv_tag_group_name}.{minimum_tag_name}'
369+
assert adv_tags.min_tags.del_minimum_tag(server, minimum_tag_path)
370+
310371
def test_adv_tag_group_del(server):
311372
# Delete parent advanced tag group
312373
assert adv_tags.adv_tag_group.del_tag_group(server, f'_advancedtags.{adv_tag_group_name}')

0 commit comments

Comments
 (0)