kepconfig.connectivity.device
device exposes an API to allow modifications (add, delete, modify) to
device objects within the Kepware Configuration API
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 8r"""`device` exposes an API to allow modifications (add, delete, modify) to 9device objects within the Kepware Configuration API 10""" 11 12from ..connection import KepServiceResponse, server 13from ..error import KepHTTPError, KepError 14from ..utils import _url_parse_object, path_split 15from typing import Union 16from . import channel, tag 17import inspect 18 19DEVICE_ROOT = '/devices' 20ATG_URL = '/services/TagGeneration' 21 22def _create_url(device = None): 23 '''Creates url object for the "device" branch of Kepware's project tree. Used 24 to build a part of Kepware Configuration API URL structure 25 26 Returns the device specific url when a value is passed as the device name. 27 ''' 28 if device == None: 29 return DEVICE_ROOT 30 else: 31 return '{}/{}'.format(DEVICE_ROOT,_url_parse_object(device)) 32 33def add_device(server: server, channel_name: str, DATA: Union[dict, list]) -> Union[bool, list]: 34 '''Add a `"device"` or multiple `"device"` objects to a channel in Kepware. Can be used to pass children of a device object 35 such as tags and tag groups. This allows you to create a device and tags 36 all in one function, if desired. 37 38 Additionally it can be used to pass a list of devices and it's children to be added all at once. 39 40 :param server: instance of the `server` class 41 :param channel_name: channel to add the device object(s) 42 :param DATA: Dict or List of Dicts of the device(s) and it's children 43 expected by Kepware Configuration API 44 45 :return: True - If a "HTTP 201 - Created" is received from Kepware server 46 :return: If a "HTTP 207 - Multi-Status" is received from Kepware with a list of dict error responses for all 47 devices added that failed. 48 49 :raises KepHTTPError: If urllib provides an HTTPError 50 :raises KepURLError: If urllib provides an URLError 51 ''' 52 53 r = server._config_add(server.url + channel._create_url(channel_name) + _create_url(), DATA) 54 if r.code == 201: return True 55 elif r.code == 207: 56 errors = [] 57 for item in r.payload: 58 if item['code'] != 201: 59 errors.append(item) 60 return errors 61 else: 62 raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload) 63 64def del_device(server: server, device_path: str) -> bool: 65 '''Delete a `"device"` object in Kepware. This will delete all children as well. 66 67 :param server: instance of the `server` class 68 :param device_path: path identifying device to delete. Standard Kepware address decimal notation string including the 69 device such as `"channel1.device1"` 70 71 :return: True - If a "HTTP 200 - OK" is received from Kepware server 72 73 :raises KepHTTPError: If urllib provides an HTTPError 74 :raises KepURLError: If urllib provides an URLError 75 ''' 76 77 path_obj = path_split(device_path) 78 try: 79 r = server._config_del(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device'])) 80 if r.code == 200: return True 81 else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload) 82 except KeyError as err: 83 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 84 raise KepError(err_msg) 85 86def modify_device(server: server, device_path: str, DATA: dict, *, force: bool = False) -> bool: 87 '''Modify a device object and it's properties in Kepware. 88 89 :param server: instance of the `server` class 90 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 91 device such as `"channel1.device1"` 92 :param DATA: Dict of the `device` properties to be modified 93 :param force: *(optional)* if True, will force the configuration update to the Kepware server 94 95 :return: True - If a "HTTP 200 - OK" is received from Kepware server 96 97 :raises KepHTTPError: If urllib provides an HTTPError 98 :raises KepURLError: If urllib provides an URLError 99 ''' 100 101 device_data = server._force_update_check(force, DATA) 102 103 path_obj = path_split(device_path) 104 try: 105 r = server._config_update(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device']), device_data) 106 if r.code == 200: return True 107 else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload) 108 except KeyError as err: 109 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 110 raise KepError(err_msg) 111 112def get_device(server: server, device_path: str) -> dict: 113 '''Returns the properties of the device object. 114 115 :param server: instance of the `server` class 116 :param device_path: path identifying device to retrieve properties. Standard Kepware address decimal notation string including the 117 device such as `"channel1.device1"` 118 119 :return: Dict of data for the device requested 120 121 :raises KepHTTPError: If urllib provides an HTTPError 122 :raises KepURLError: If urllib provides an URLError 123 ''' 124 125 path_obj = path_split(device_path) 126 try: 127 r = server._config_get(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device'])) 128 return r.payload 129 except KeyError as err: 130 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 131 raise KepError(err_msg) 132 # except Exception as err: 133 # print('Error: Error with {}: {}'.format(inspect.currentframe().f_code.co_name, str(err))) 134 # raise err 135 136def get_all_devices(server: server, channel_name: str, *, options: dict = None) -> list: 137 '''Returns list of all device objects and their properties within a channel. Returned object is JSON list. 138 139 :param server: instance of the `server` class 140 :param channel: name of channel 141 :param options: *(optional)* Dict of parameters to filter, sort or pagenate the list of devices. Options are `filter`, 142 `sortOrder`, `sortProperty`, `pageNumber`, and `pageSize` 143 144 :return: List of data for all devices within the channel 145 146 :raises KepHTTPError: If urllib provides an HTTPError 147 :raises KepURLError: If urllib provides an URLError 148 ''' 149 r = server._config_get(f'{server.url}{channel._create_url(channel_name)}{_create_url()}', params= options) 150 return r.payload 151 152def auto_tag_gen(server: server, device_path: str, job_ttl: int = None) -> KepServiceResponse: 153 '''Executes Auto Tag Generation function on devices that support the feature in Kepware 154 155 :param server: instance of the `server` class 156 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 157 device such as `"channel1.device1"` 158 159 :param job_ttl: *(optional)* Determines the number of seconds a job instance will exist following completion. 160 161 :return: `KepServiceResponse` instance with job information 162 163 :raises KepHTTPError: If urllib provides an HTTPError (If not HTTP code 202 [Accepted] or 429 [Too Busy] returned) 164 :raises KepURLError: If urllib provides an URLError 165 ''' 166 167 path_obj = path_split(device_path) 168 try: 169 url = server.url +channel._create_url(path_obj['channel']) + _create_url(path_obj['device']) + ATG_URL 170 job = server._kep_service_execute(url, None, job_ttl) 171 return job 172 except KeyError as err: 173 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 174 raise KepError(err_msg) 175 176def get_all_tags_tag_groups(server: server, device_path: str) -> dict: 177 '''Returns the properties of all `"tag"` and `"tag group"` objects for as specific 178 device in Kepware. Returned object is a dict of tag list and tag group list. 179 180 The returned object resembles the example below, nested based on how many 181 levels the tag_group namespace has tags or tag_groups: 182 183 Example return: 184 185 { 186 'tags': [tag1_dict, tag2_dict,...], 187 'tag_groups':[ 188 { 189 tag_group1_properties, 190 'tags': [tag1_dict, tag2_dict,...] 191 'tag_groups':[sub_group1, subgroup2,...] 192 }, 193 { 194 tag_group2_properties, 195 'tags': [tag1_dict, tag2_dict,...] 196 'tag_groups':[sub_group1, subgroup2,...] 197 },...] 198 } 199 200 :param server: instance of the `server` class 201 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 202 device such as `"channel1.device1"` 203 204 :return: Dict of data for the tag structure for device requested at `"device_path"` location 205 206 :raises KepHTTPError: If urllib provides an HTTPError 207 :raises KepURLError: If urllib provides an URLError 208 ''' 209 210 r = tag.get_full_tag_structure(server, device_path,recursive=True) 211 return r 212 213def get_device_structure(server, device_path) -> dict: 214 '''Returns the properties of `"device"` and includes all `"tag"` and `"tag group"` objects for as specific 215 device in Kepware. Returned object is a dict of device properties including a tag list and tag group list. 216 217 The returned object resembles example below, nested based on how many 218 levels the tag_group namespace has tags or tag_groups: 219 220 Example return: 221 222 { 223 device_properties, 224 'tags': [tag1_dict, tag2_dict,...], 225 'tag_groups':[ 226 { 227 tag_group1_properties, 228 'tags': [tag1_dict, tag2_dict,...] 229 'tag_groups':[sub_group1, subgroup2,...] 230 }, 231 { 232 tag_group2_properties, 233 'tags': [tag1_dict, tag2_dict,...] 234 'tag_groups':[sub_group1, subgroup2,...] 235 },...] 236 } 237 238 :param server: instance of the `server` class 239 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 240 device such as `"channel1.device1"` 241 242 :return: Dict of data for the device structure at `"device_path"` location 243 244 :raises KepHTTPError: If urllib provides an HTTPError 245 :raises KepURLError: If urllib provides an URLError 246 ''' 247 248 tags = tag.get_full_tag_structure(server, device_path,recursive=True) 249 device_properties = get_device(server,device_path) 250 return {**device_properties, **tags}
34def add_device(server: server, channel_name: str, DATA: Union[dict, list]) -> Union[bool, list]: 35 '''Add a `"device"` or multiple `"device"` objects to a channel in Kepware. Can be used to pass children of a device object 36 such as tags and tag groups. This allows you to create a device and tags 37 all in one function, if desired. 38 39 Additionally it can be used to pass a list of devices and it's children to be added all at once. 40 41 :param server: instance of the `server` class 42 :param channel_name: channel to add the device object(s) 43 :param DATA: Dict or List of Dicts of the device(s) and it's children 44 expected by Kepware Configuration API 45 46 :return: True - If a "HTTP 201 - Created" is received from Kepware server 47 :return: If a "HTTP 207 - Multi-Status" is received from Kepware with a list of dict error responses for all 48 devices added that failed. 49 50 :raises KepHTTPError: If urllib provides an HTTPError 51 :raises KepURLError: If urllib provides an URLError 52 ''' 53 54 r = server._config_add(server.url + channel._create_url(channel_name) + _create_url(), DATA) 55 if r.code == 201: return True 56 elif r.code == 207: 57 errors = [] 58 for item in r.payload: 59 if item['code'] != 201: 60 errors.append(item) 61 return errors 62 else: 63 raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
Add a "device" or multiple "device" objects to a channel in Kepware. Can be used to pass children of a device object
such as tags and tag groups. This allows you to create a device and tags
all in one function, if desired.
Additionally it can be used to pass a list of devices and it's children to be added all at once.
Parameters
- server: instance of the
serverclass - channel_name: channel to add the device object(s)
- DATA: Dict or List of Dicts of the device(s) and it's children expected by Kepware Configuration API
Returns
True - If a "HTTP 201 - Created" is received from Kepware server
Returns
If a "HTTP 207 - Multi-Status" is received from Kepware with a list of dict error responses for all devices added that failed.
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError
65def del_device(server: server, device_path: str) -> bool: 66 '''Delete a `"device"` object in Kepware. This will delete all children as well. 67 68 :param server: instance of the `server` class 69 :param device_path: path identifying device to delete. Standard Kepware address decimal notation string including the 70 device such as `"channel1.device1"` 71 72 :return: True - If a "HTTP 200 - OK" is received from Kepware server 73 74 :raises KepHTTPError: If urllib provides an HTTPError 75 :raises KepURLError: If urllib provides an URLError 76 ''' 77 78 path_obj = path_split(device_path) 79 try: 80 r = server._config_del(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device'])) 81 if r.code == 200: return True 82 else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload) 83 except KeyError as err: 84 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 85 raise KepError(err_msg)
Delete a "device" object in Kepware. This will delete all children as well.
Parameters
- server: instance of the
serverclass - device_path: path identifying device to delete. Standard Kepware address decimal notation string including the
device such as
"channel1.device1"
Returns
True - If a "HTTP 200 - OK" is received from Kepware server
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError
87def modify_device(server: server, device_path: str, DATA: dict, *, force: bool = False) -> bool: 88 '''Modify a device object and it's properties in Kepware. 89 90 :param server: instance of the `server` class 91 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 92 device such as `"channel1.device1"` 93 :param DATA: Dict of the `device` properties to be modified 94 :param force: *(optional)* if True, will force the configuration update to the Kepware server 95 96 :return: True - If a "HTTP 200 - OK" is received from Kepware server 97 98 :raises KepHTTPError: If urllib provides an HTTPError 99 :raises KepURLError: If urllib provides an URLError 100 ''' 101 102 device_data = server._force_update_check(force, DATA) 103 104 path_obj = path_split(device_path) 105 try: 106 r = server._config_update(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device']), device_data) 107 if r.code == 200: return True 108 else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload) 109 except KeyError as err: 110 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 111 raise KepError(err_msg)
Modify a device object and it's properties in Kepware.
Parameters
- server: instance of the
serverclass - device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the
device such as
"channel1.device1" - DATA: Dict of the
deviceproperties to be modified - force: (optional) if True, will force the configuration update to the Kepware server
Returns
True - If a "HTTP 200 - OK" is received from Kepware server
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError
113def get_device(server: server, device_path: str) -> dict: 114 '''Returns the properties of the device object. 115 116 :param server: instance of the `server` class 117 :param device_path: path identifying device to retrieve properties. Standard Kepware address decimal notation string including the 118 device such as `"channel1.device1"` 119 120 :return: Dict of data for the device requested 121 122 :raises KepHTTPError: If urllib provides an HTTPError 123 :raises KepURLError: If urllib provides an URLError 124 ''' 125 126 path_obj = path_split(device_path) 127 try: 128 r = server._config_get(server.url + channel._create_url(path_obj['channel']) + _create_url(path_obj['device'])) 129 return r.payload 130 except KeyError as err: 131 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 132 raise KepError(err_msg) 133 # except Exception as err: 134 # print('Error: Error with {}: {}'.format(inspect.currentframe().f_code.co_name, str(err))) 135 # raise err
Returns the properties of the device object.
Parameters
- server: instance of the
serverclass - device_path: path identifying device to retrieve properties. Standard Kepware address decimal notation string including the
device such as
"channel1.device1"
Returns
Dict of data for the device requested
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError
137def get_all_devices(server: server, channel_name: str, *, options: dict = None) -> list: 138 '''Returns list of all device objects and their properties within a channel. Returned object is JSON list. 139 140 :param server: instance of the `server` class 141 :param channel: name of channel 142 :param options: *(optional)* Dict of parameters to filter, sort or pagenate the list of devices. Options are `filter`, 143 `sortOrder`, `sortProperty`, `pageNumber`, and `pageSize` 144 145 :return: List of data for all devices within the channel 146 147 :raises KepHTTPError: If urllib provides an HTTPError 148 :raises KepURLError: If urllib provides an URLError 149 ''' 150 r = server._config_get(f'{server.url}{channel._create_url(channel_name)}{_create_url()}', params= options) 151 return r.payload
Returns list of all device objects and their properties within a channel. Returned object is JSON list.
Parameters
- server: instance of the
serverclass - channel: name of channel
- options: (optional) Dict of parameters to filter, sort or pagenate the list of devices. Options are
filter,sortOrder,sortProperty,pageNumber, andpageSize
Returns
List of data for all devices within the channel
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError
153def auto_tag_gen(server: server, device_path: str, job_ttl: int = None) -> KepServiceResponse: 154 '''Executes Auto Tag Generation function on devices that support the feature in Kepware 155 156 :param server: instance of the `server` class 157 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 158 device such as `"channel1.device1"` 159 160 :param job_ttl: *(optional)* Determines the number of seconds a job instance will exist following completion. 161 162 :return: `KepServiceResponse` instance with job information 163 164 :raises KepHTTPError: If urllib provides an HTTPError (If not HTTP code 202 [Accepted] or 429 [Too Busy] returned) 165 :raises KepURLError: If urllib provides an URLError 166 ''' 167 168 path_obj = path_split(device_path) 169 try: 170 url = server.url +channel._create_url(path_obj['channel']) + _create_url(path_obj['device']) + ATG_URL 171 job = server._kep_service_execute(url, None, job_ttl) 172 return job 173 except KeyError as err: 174 err_msg = 'Error: No {} identified in {} | Function: {}'.format(err,'device_path', inspect.currentframe().f_code.co_name) 175 raise KepError(err_msg)
Executes Auto Tag Generation function on devices that support the feature in Kepware
Parameters
- server: instance of the
serverclass device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the device such as
"channel1.device1"job_ttl: (optional) Determines the number of seconds a job instance will exist following completion.
Returns
KepServiceResponseinstance with job information
Raises
- KepHTTPError: If urllib provides an HTTPError (If not HTTP code 202 [Accepted] or 429 [Too Busy] returned)
- KepURLError: If urllib provides an URLError
214def get_device_structure(server, device_path) -> dict: 215 '''Returns the properties of `"device"` and includes all `"tag"` and `"tag group"` objects for as specific 216 device in Kepware. Returned object is a dict of device properties including a tag list and tag group list. 217 218 The returned object resembles example below, nested based on how many 219 levels the tag_group namespace has tags or tag_groups: 220 221 Example return: 222 223 { 224 device_properties, 225 'tags': [tag1_dict, tag2_dict,...], 226 'tag_groups':[ 227 { 228 tag_group1_properties, 229 'tags': [tag1_dict, tag2_dict,...] 230 'tag_groups':[sub_group1, subgroup2,...] 231 }, 232 { 233 tag_group2_properties, 234 'tags': [tag1_dict, tag2_dict,...] 235 'tag_groups':[sub_group1, subgroup2,...] 236 },...] 237 } 238 239 :param server: instance of the `server` class 240 :param device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the 241 device such as `"channel1.device1"` 242 243 :return: Dict of data for the device structure at `"device_path"` location 244 245 :raises KepHTTPError: If urllib provides an HTTPError 246 :raises KepURLError: If urllib provides an URLError 247 ''' 248 249 tags = tag.get_full_tag_structure(server, device_path,recursive=True) 250 device_properties = get_device(server,device_path) 251 return {**device_properties, **tags}
Returns the properties of "device" and includes all "tag" and "tag group" objects for as specific
device in Kepware. Returned object is a dict of device properties including a tag list and tag group list.
The returned object resembles example below, nested based on how many levels the tag_group namespace has tags or tag_groups:
Example return:
{
device_properties,
'tags': [tag1_dict, tag2_dict,...],
'tag_groups':[
{
tag_group1_properties,
'tags': [tag1_dict, tag2_dict,...]
'tag_groups':[sub_group1, subgroup2,...]
},
{
tag_group2_properties,
'tags': [tag1_dict, tag2_dict,...]
'tag_groups':[sub_group1, subgroup2,...]
},...]
}
Parameters
- server: instance of the
serverclass - device_path: path identifying device to modffy. Standard Kepware address decimal notation string including the
device such as
"channel1.device1"
Returns
Dict of data for the device structure at
"device_path"location
Raises
- KepHTTPError: If urllib provides an HTTPError
- KepURLError: If urllib provides an URLError