kepconfig.connectivity.channel

channel exposes an API to allow modifications (add, delete, modify) to channel 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"""`channel` exposes an API to allow modifications (add, delete, modify) to 
  9channel objects within the Kepware Configuration API
 10"""
 11
 12 
 13import inspect
 14from ..connection import server
 15from ..error import KepHTTPError, KepError
 16from ..utils import _url_parse_object
 17from typing import Union
 18from . import device
 19
 20CHANNEL_ROOT = '/project/channels'
 21
 22def _create_url(channel = None):
 23    '''Creates url object for the "channel" branch of Kepware's project tree. Used 
 24    to build a part of Kepware Configuration API URL structure
 25
 26    Returns the channel specific url when a value is passed as the channel name.
 27    '''
 28    
 29    if channel == None:
 30        return CHANNEL_ROOT
 31    else:
 32        return '{}/{}'.format(CHANNEL_ROOT,_url_parse_object(channel))
 33
 34def add_channel(server: server, DATA: Union[dict, list]) -> Union[bool, list]:
 35    '''Add a `"channel"` or multiple `"channel"` objects to Kepware. Can be used to pass children of a channel object 
 36    such as devices and tags/tag groups. This allows you to create a channel, it's devices and tags 
 37    all in one function, if desired.
 38
 39    Additionally it can be used to pass a list of channels and it's children to be added all at once.
 40
 41    :param server: instance of the `server` class
 42    :param DATA: Dict of the channel 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    channels 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 + _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_channel(server: server, channel: str) -> bool:
 65    '''Delete a `"channel"` object in Kepware. This will delete all children as well
 66    
 67    :param server: instance of the `server` class
 68    :param channel: name of channel
 69    
 70    :return: True - If a "HTTP 200 - OK" is received from Kepware server
 71
 72    :raises KepHTTPError: If urllib provides an HTTPError
 73    :raises KepURLError: If urllib provides an URLError
 74    '''
 75
 76    r = server._config_del(server.url + _create_url(channel))
 77    if r.code == 200: return True 
 78    else: 
 79        raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
 80
 81def modify_channel(server: server, DATA: dict, *, channel: str = None, force: bool = False) -> bool:
 82    '''Modify a channel object and it's properties in Kepware. If a `"channel"` is not provided as an input,
 83    you need to identify the channel in the *'common.ALLTYPES_NAME'* property field in `"DATA"`. It will 
 84    assume that is the channel that is to be modified.
 85
 86    :param server: instance of the `server` class
 87    :param DATA: Dict of the `channel` properties to be modified
 88    :param channel: *(optional)* name of channel to modify. Only needed if not existing in `"DATA"`
 89    :param force: *(optional)* if True, will force the configuration update to the Kepware server
 90    
 91    :return: True - If a "HTTP 200 - OK" is received from Kepware server
 92
 93    :raises KepHTTPError: If urllib provides an HTTPError
 94    :raises KepURLError: If urllib provides an URLError
 95    '''
 96    
 97    channel_data = server._force_update_check(force, DATA)
 98    if channel == None:
 99        try:
100            r = server._config_update(server.url + _create_url(channel_data['common.ALLTYPES_NAME']), channel_data)
101            if r.code == 200: return True 
102            else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
103        except KeyError as err:
104            err_msg = 'Error: No Channel identified in DATA | Key Error: {}'.format(err)
105            raise KepError(err_msg)
106        # except Exception as e:
107        #     return 'Error: Error with {}: {}'.format(inspect.currentframe().f_code.co_name, str(e))
108    else:
109        r = server._config_update(server.url + _create_url(channel), channel_data)
110        if r.code == 200: return True 
111        else: 
112            raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
113
114def get_channel(server: server, channel: str)  -> dict:
115    '''Returns the properties of the channel object.
116    
117    :param server: instance of the `server` class
118    :param channel: name of channel
119    
120    :return: Dict of data for the channel requested
121
122    :raises KepHTTPError: If urllib provides an HTTPError
123    :raises KepURLError: If urllib provides an URLError
124    '''
125
126    r = server._config_get(server.url + _create_url(channel))
127    return r.payload
128
129def get_all_channels(server: server, *, options: dict = None) -> list:
130    '''Returns list of all channel objects and their properties.
131    
132    :param server: instance of the `server` class
133    :param options: *(optional)* Dict of parameters to filter, sort or pagenate the list of channels. Options are `filter`, 
134        `sortOrder`, `sortProperty`, `pageNumber`, and `pageSize`
135    
136    :return: List of data for all channels in Kepware server
137
138    :raises KepHTTPError: If urllib provides an HTTPError
139    :raises KepURLError: If urllib provides an URLError
140    '''
141
142    r = server._config_get(server.url + _create_url(), params= options)
143    return r.payload
144
145def get_channel_structure(server: server, channel: str) -> dict:
146    '''Returns the properties of `"channel"` and includes all `"devices"` and the `"tag"` and `"tag group"` objects for a 
147    channel in Kepware. Returned object is a dict of channel properties including a device list with 
148    tag lists and tag group lists.
149
150    The returned object resembles the example below, nested based on how many 
151    levels the tag_group namespace has tags or tag_groups:
152
153    Example return:
154    
155        {
156            channel_properties,
157            'devices: [
158                {
159                    device1_properties,
160                    'tags': [tag1_dict, tag2_dict,...],
161                    'tag_groups':[
162                        {
163                            tag_group1_properties,
164                            'tags': [tag1_dict, tag2_dict,...]
165                            'tag_groups':[sub_group1, subgroup2,...]
166                        }, 
167                        {
168                            tag_group2_properties,
169                            'tags': [tag1_dict, tag2_dict,...]
170                            'tag_groups':[sub_group1, subgroup2,...]
171                        },...]
172                },...]
173        }       
174
175    :param server: instance of the `server` class
176    :param channel: name of channel
177
178    :return: Dict of data for the channel structure requested for `"channel"`
179
180    :raises KepHTTPError: If urllib provides an HTTPError
181    :raises KepURLError: If urllib provides an URLError
182    '''
183
184    channel_properties = get_channel(server, channel)
185    device_list = device.get_all_devices(server,channel)
186    for dev in device_list:
187        device_properties = []
188        dev_struct = device.get_device_structure(server,channel + '.' + dev['common.ALLTYPES_NAME'])
189        device_properties.append(dev_struct)
190    return {**channel_properties,'device': device_properties}
CHANNEL_ROOT = '/project/channels'
def add_channel( server: kepconfig.connection.server, DATA: Union[dict, list]) -> Union[bool, list]:
35def add_channel(server: server, DATA: Union[dict, list]) -> Union[bool, list]:
36    '''Add a `"channel"` or multiple `"channel"` objects to Kepware. Can be used to pass children of a channel object 
37    such as devices and tags/tag groups. This allows you to create a channel, it's devices and tags 
38    all in one function, if desired.
39
40    Additionally it can be used to pass a list of channels and it's children to be added all at once.
41
42    :param server: instance of the `server` class
43    :param DATA: Dict of the channel 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    channels 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 + _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 "channel" or multiple "channel" objects to Kepware. Can be used to pass children of a channel object such as devices and tags/tag groups. This allows you to create a channel, it's devices and tags all in one function, if desired.

Additionally it can be used to pass a list of channels and it's children to be added all at once.

Parameters
  • server: instance of the server class
  • DATA: Dict of the channel 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 channels added that failed.

Raises
  • KepHTTPError: If urllib provides an HTTPError
  • KepURLError: If urllib provides an URLError
def del_channel(server: kepconfig.connection.server, channel: str) -> bool:
65def del_channel(server: server, channel: str) -> bool:
66    '''Delete a `"channel"` object in Kepware. This will delete all children as well
67    
68    :param server: instance of the `server` class
69    :param channel: name of channel
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    r = server._config_del(server.url + _create_url(channel))
78    if r.code == 200: return True 
79    else: 
80        raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)

Delete a "channel" object in Kepware. This will delete all children as well

Parameters
  • server: instance of the server class
  • channel: name of channel
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
def modify_channel( server: kepconfig.connection.server, DATA: dict, *, channel: str = None, force: bool = False) -> bool:
 82def modify_channel(server: server, DATA: dict, *, channel: str = None, force: bool = False) -> bool:
 83    '''Modify a channel object and it's properties in Kepware. If a `"channel"` is not provided as an input,
 84    you need to identify the channel in the *'common.ALLTYPES_NAME'* property field in `"DATA"`. It will 
 85    assume that is the channel that is to be modified.
 86
 87    :param server: instance of the `server` class
 88    :param DATA: Dict of the `channel` properties to be modified
 89    :param channel: *(optional)* name of channel to modify. Only needed if not existing in `"DATA"`
 90    :param force: *(optional)* if True, will force the configuration update to the Kepware server
 91    
 92    :return: True - If a "HTTP 200 - OK" is received from Kepware server
 93
 94    :raises KepHTTPError: If urllib provides an HTTPError
 95    :raises KepURLError: If urllib provides an URLError
 96    '''
 97    
 98    channel_data = server._force_update_check(force, DATA)
 99    if channel == None:
100        try:
101            r = server._config_update(server.url + _create_url(channel_data['common.ALLTYPES_NAME']), channel_data)
102            if r.code == 200: return True 
103            else: raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)
104        except KeyError as err:
105            err_msg = 'Error: No Channel identified in DATA | Key Error: {}'.format(err)
106            raise KepError(err_msg)
107        # except Exception as e:
108        #     return 'Error: Error with {}: {}'.format(inspect.currentframe().f_code.co_name, str(e))
109    else:
110        r = server._config_update(server.url + _create_url(channel), channel_data)
111        if r.code == 200: return True 
112        else: 
113            raise KepHTTPError(r.url, r.code, r.msg, r.hdrs, r.payload)

Modify a channel object and it's properties in Kepware. If a "channel" is not provided as an input, you need to identify the channel in the 'common.ALLTYPES_NAME' property field in "DATA". It will assume that is the channel that is to be modified.

Parameters
  • server: instance of the server class
  • DATA: Dict of the channel properties to be modified
  • channel: (optional) name of channel to modify. Only needed if not existing in "DATA"
  • 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
def get_channel(server: kepconfig.connection.server, channel: str) -> dict:
115def get_channel(server: server, channel: str)  -> dict:
116    '''Returns the properties of the channel object.
117    
118    :param server: instance of the `server` class
119    :param channel: name of channel
120    
121    :return: Dict of data for the channel requested
122
123    :raises KepHTTPError: If urllib provides an HTTPError
124    :raises KepURLError: If urllib provides an URLError
125    '''
126
127    r = server._config_get(server.url + _create_url(channel))
128    return r.payload

Returns the properties of the channel object.

Parameters
  • server: instance of the server class
  • channel: name of channel
Returns

Dict of data for the channel requested

Raises
  • KepHTTPError: If urllib provides an HTTPError
  • KepURLError: If urllib provides an URLError
def get_all_channels(server: kepconfig.connection.server, *, options: dict = None) -> list:
130def get_all_channels(server: server, *, options: dict = None) -> list:
131    '''Returns list of all channel objects and their properties.
132    
133    :param server: instance of the `server` class
134    :param options: *(optional)* Dict of parameters to filter, sort or pagenate the list of channels. Options are `filter`, 
135        `sortOrder`, `sortProperty`, `pageNumber`, and `pageSize`
136    
137    :return: List of data for all channels in Kepware server
138
139    :raises KepHTTPError: If urllib provides an HTTPError
140    :raises KepURLError: If urllib provides an URLError
141    '''
142
143    r = server._config_get(server.url + _create_url(), params= options)
144    return r.payload

Returns list of all channel objects and their properties.

Parameters
  • server: instance of the server class
  • options: (optional) Dict of parameters to filter, sort or pagenate the list of channels. Options are filter, sortOrder, sortProperty, pageNumber, and pageSize
Returns

List of data for all channels in Kepware server

Raises
  • KepHTTPError: If urllib provides an HTTPError
  • KepURLError: If urllib provides an URLError
def get_channel_structure(server: kepconfig.connection.server, channel: str) -> dict:
146def get_channel_structure(server: server, channel: str) -> dict:
147    '''Returns the properties of `"channel"` and includes all `"devices"` and the `"tag"` and `"tag group"` objects for a 
148    channel in Kepware. Returned object is a dict of channel properties including a device list with 
149    tag lists and tag group lists.
150
151    The returned object resembles the example below, nested based on how many 
152    levels the tag_group namespace has tags or tag_groups:
153
154    Example return:
155    
156        {
157            channel_properties,
158            'devices: [
159                {
160                    device1_properties,
161                    'tags': [tag1_dict, tag2_dict,...],
162                    'tag_groups':[
163                        {
164                            tag_group1_properties,
165                            'tags': [tag1_dict, tag2_dict,...]
166                            'tag_groups':[sub_group1, subgroup2,...]
167                        }, 
168                        {
169                            tag_group2_properties,
170                            'tags': [tag1_dict, tag2_dict,...]
171                            'tag_groups':[sub_group1, subgroup2,...]
172                        },...]
173                },...]
174        }       
175
176    :param server: instance of the `server` class
177    :param channel: name of channel
178
179    :return: Dict of data for the channel structure requested for `"channel"`
180
181    :raises KepHTTPError: If urllib provides an HTTPError
182    :raises KepURLError: If urllib provides an URLError
183    '''
184
185    channel_properties = get_channel(server, channel)
186    device_list = device.get_all_devices(server,channel)
187    for dev in device_list:
188        device_properties = []
189        dev_struct = device.get_device_structure(server,channel + '.' + dev['common.ALLTYPES_NAME'])
190        device_properties.append(dev_struct)
191    return {**channel_properties,'device': device_properties}

Returns the properties of "channel" and includes all "devices" and the "tag" and "tag group" objects for a channel in Kepware. Returned object is a dict of channel properties including a device list with tag lists and tag group lists.

The returned object resembles the example below, nested based on how many levels the tag_group namespace has tags or tag_groups:

Example return:

{
    channel_properties,
    'devices: [
        {
            device1_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 server class
  • channel: name of channel
Returns

Dict of data for the channel structure requested for "channel"

Raises
  • KepHTTPError: If urllib provides an HTTPError
  • KepURLError: If urllib provides an URLError