pymscada 0.1.0a6__py3-none-any.whl → 0.1.1a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pymscada might be problematic. Click here for more details.

pymscada/www_server.py CHANGED
@@ -7,30 +7,20 @@ from struct import pack, unpack_from
7
7
  import time
8
8
  from pymscada.bus_client import BusClient
9
9
  import pymscada.protocol_constants as pc
10
- from pymscada.tag import Tag, TYPES
10
+ from pymscada.tag import Tag, tag_for_web, TYPES
11
11
  from pymscada_html import get_html_file
12
12
 
13
13
 
14
- def tag_for_web(tagname: str, tag: dict):
15
- """Correct tag dictionary in place to be suitable for web client."""
16
- tag['name'] = tagname
17
- tag['id'] = None
18
- if 'desc' not in tag:
19
- tag['desc'] = tag.name
20
- if 'multi' in tag:
21
- tag['type'] = 'int'
22
- else:
23
- if 'type' not in tag:
24
- tag['type'] = 'float'
25
- else:
26
- if tag['type'] not in TYPES:
27
- tag['type'] = 'str'
28
- if tag['type'] == 'int':
29
- tag['dp'] = 0
30
- elif tag['type'] == 'float' and 'dp' not in tag:
31
- tag['dp'] = 2
32
- elif tag['type'] == 'str' and 'dp' in tag:
33
- del tag['dp']
14
+ class Interface():
15
+ """Provide an interface between web client rta and the action."""
16
+
17
+ def __init__(self, tagname: str) -> None:
18
+ """Return path tagname for rta requests."""
19
+ self.tag = Tag(tagname, dict)
20
+
21
+ def ask(self, message):
22
+ """Process the message."""
23
+ logging.warning(message)
34
24
 
35
25
 
36
26
  class WSHandler():
@@ -44,7 +34,7 @@ class WSHandler():
44
34
  ids = set(range(1, 100))
45
35
 
46
36
  def __init__(self, ws: web.WebSocketResponse, pages: dict,
47
- tag_info: dict[str, Tag], do_rqs):
37
+ tag_info: dict[str, Tag], do_rta, interface: Interface):
48
38
  """Create callbacks to monitor tag values."""
49
39
  self.ws = ws
50
40
  self.pages = pages
@@ -52,13 +42,14 @@ class WSHandler():
52
42
  self.tag_by_id: dict[int, Tag] = {}
53
43
  self.tag_by_name: dict[str, Tag] = {}
54
44
  self.queue = asyncio.Queue()
55
- self.do_rqs = do_rqs
56
- self.rqs_id = self.ids.pop()
57
- logging.info(f'weksocket id {self.rqs_id}')
45
+ self.do_rta = do_rta
46
+ self.rta_id = self.ids.pop()
47
+ logging.info(f'websocket id {self.rta_id}')
48
+ self.interface = interface
58
49
 
59
50
  def __del__(self):
60
51
  """Depends on garbage collector. Is OK."""
61
- self.ids.add(self.rqs_id)
52
+ self.ids.add(self.rta_id)
62
53
 
63
54
  async def send_queue(self):
64
55
  """Run forever, write from queue."""
@@ -70,7 +61,7 @@ class WSHandler():
70
61
  else:
71
62
  await self.ws.send_json(message)
72
63
  except asyncio.CancelledError:
73
- logging.warn(f'{self.rqs_id}: send queue error, close '
64
+ logging.warn(f'{self.rta_id}: send queue error, close '
74
65
  f'{self.ws.exception()}')
75
66
  return
76
67
 
@@ -91,7 +82,7 @@ class WSHandler():
91
82
  self.queue.put_nowait((True, pack(
92
83
  '!HHQq', # Network big-endian
93
84
  tag.id, # Uint16
94
- pc.TYPE_INT, # Uint16
85
+ pc.TYPE_INT, # Uint16
95
86
  tag.time_us, # Uint64
96
87
  tag.value # Int64
97
88
  )))
@@ -99,7 +90,7 @@ class WSHandler():
99
90
  self.queue.put_nowait((True, pack(
100
91
  '!HHQd', # Network big-endian
101
92
  tag.id, # Uint16
102
- pc.TYPE_FLOAT, # Uint16
93
+ pc.TYPE_FLOAT, # Uint16
103
94
  tag.time_us, # Uint64
104
95
  tag.value # Float64
105
96
  )))
@@ -113,17 +104,17 @@ class WSHandler():
113
104
  asbytes # Char as needed
114
105
  )))
115
106
  elif tag.type == bytes:
116
- rqs_id = unpack_from('>H', tag.value)[0]
117
- if rqs_id in [0, self.rqs_id]:
107
+ rta_id = unpack_from('>H', tag.value)[0]
108
+ if rta_id in [0, self.rta_id]:
118
109
  self.queue.put_nowait((True, pack(
119
110
  f'!HHQ{len(tag.value)}s', # Network big-endian
120
111
  tag.id, # Uint16
121
- pc.TYPE_BYTES, # Uint16
112
+ pc.TYPE_BYTES, # Uint16
122
113
  tag.time_us, # Uint64
123
114
  tag.value # Char as needed
124
115
  )))
125
116
  else:
126
- logging.info(f'{self.rqs_id}: {tag.name} bytes mismatch id')
117
+ logging.info(f'{self.rta_id}: {tag.name} bytes mismatch id')
127
118
  elif tag.type in [dict, list]:
128
119
  self.queue.put_nowait((False, {
129
120
  'type': 'tag',
@@ -136,7 +127,7 @@ class WSHandler():
136
127
 
137
128
  def notify_id(self, tag: Tag):
138
129
  """Must be done here."""
139
- logging.info(f'{self.rqs_id}: send id to webclient for {tag.name}')
130
+ logging.info(f'{self.rta_id}: send id to webclient for {tag.name}')
140
131
  self.tag_info[tag.name]['id'] = tag.id
141
132
  self.tag_by_id[tag.id] = tag
142
133
  self.tag_by_name[tag.name] = tag
@@ -151,7 +142,7 @@ class WSHandler():
151
142
  tag = self.tag_by_name[tagname]
152
143
  except KeyError:
153
144
  if tagname not in self.tag_info:
154
- logging.warning(f'{self.rqs_id}: no {tagname} in tag_info')
145
+ logging.warning(f'{self.rta_id}: no {tagname} in tag_info')
155
146
  return
156
147
  tag = Tag(tagname, TYPES[self.tag_info[tagname]['type']])
157
148
  if tag.id is None:
@@ -168,7 +159,7 @@ class WSHandler():
168
159
  (False, {'type': 'pages', 'payload': self.pages}))
169
160
  async for msg in self.ws:
170
161
  if msg.type == WSMsgType.TEXT:
171
- logging.info(f'{self.rqs_id}: websocket recv {msg.json()}')
162
+ logging.info(f'{self.rta_id}: websocket recv {msg.json()}')
172
163
  command = msg.json()
173
164
  action = command['type']
174
165
  tagname = command['tagname']
@@ -177,23 +168,25 @@ class WSHandler():
177
168
  bus = None
178
169
  if action == 'set': # pc.CMD_SET
179
170
  self.tag_by_name[tagname].value = value, time_us, bus
180
- elif action == 'rqs': # pc.CMD_RQS
171
+ elif action == 'rta': # pc.CMD_RTA
181
172
  if 'File' in value:
182
173
  file = await anext(self.ws)
183
174
  value['_file_data'] = file.data
184
- value['__rqs_id__'] = self.rqs_id
185
- self.do_rqs(tagname, value)
175
+ value['__rta_id__'] = self.rta_id
176
+ self.do_rta(tagname, value)
177
+ elif action == 'request_to_author':
178
+ self.interface.ask(command)
186
179
  elif action == 'sub': # pc.CMD_SUB
187
180
  self.do_sub(tagname)
188
181
  elif action == 'get': # pc.CMD_GET
189
- logging.warning(f'{self.rqs_id}: CMD_GET not implemented.')
182
+ logging.warning(f'{self.rta_id}: CMD_GET not implemented.')
190
183
  elif action == 'unsub': # pc.CMD_UNSUB
191
- logging.warning(f'{self.rqs_id}: CMD_UNSUB not '
184
+ logging.warning(f'{self.rta_id}: CMD_UNSUB not '
192
185
  'implemented.')
193
186
  elif msg.type == WSMsgType.BINARY:
194
187
  logging.info(f'{msg.data}')
195
188
  elif msg.type == WSMsgType.ERROR:
196
- logging.warn(f'{self.rqs_id}: ws closing error '
189
+ logging.warn(f'{self.rta_id}: ws closing error '
197
190
  f'{self.ws.exception()}')
198
191
  send_queue.cancel()
199
192
  for tag in self.tag_by_id.values():
@@ -206,7 +199,8 @@ class WwwServer:
206
199
 
207
200
  def __init__(self, bus_ip: str = '127.0.0.1', bus_port: int = 1324,
208
201
  ip: str = '127.0.0.1', port: int = 8324, get_path: str = None,
209
- tag_info: dict = {}, pages: dict = {}, paths: list[str] = []
202
+ tag_info: dict = {}, pages: dict = {}, serve_path: str = None,
203
+ www_tag: str = '__wwwserver__'
210
204
  ) -> None:
211
205
  """
212
206
  Connect to bus on bus_ip:bus_port, serve on ip:port for webclient.
@@ -217,15 +211,17 @@ class WwwServer:
217
211
 
218
212
  Event loop must be running.
219
213
  """
220
- self.busclient = BusClient(bus_ip, bus_port, tag_info)
214
+ self.busclient = BusClient(bus_ip, bus_port, tag_info,
215
+ module='WWW Server')
221
216
  self.ip = ip
222
217
  self.port = port
223
218
  self.get_path = get_path
219
+ self.serve_path = Path(serve_path)
224
220
  for tagname, tag in tag_info.items():
225
221
  tag_for_web(tagname, tag)
226
222
  self.tag_info = tag_info
227
223
  self.pages = pages
228
- self.paths = paths
224
+ self.interface = Interface(www_tag)
229
225
 
230
226
  async def redirect_handler(self, _request: web.Request):
231
227
  """Point an empty request to the index."""
@@ -247,13 +243,12 @@ class WwwServer:
247
243
  async def path_handler(self, request: web.Request):
248
244
  """Plain files."""
249
245
  logging.info(f"path {request.match_info['path']}")
250
- path = Path(request.match_info['path'])
246
+ path = self.serve_path.joinpath(request.match_info['path'])
251
247
  if path.is_dir():
252
248
  return web.HTTPForbidden(reason='folder not permitted')
253
- if '/'.join(path.parts[:-1]) in self.paths:
254
- if not path.exists():
255
- return web.HTTPNotFound(reason='no such file in path')
256
- return web.FileResponse(path)
249
+ if not path.exists():
250
+ return web.HTTPNotFound(reason='no such file in path')
251
+ return web.FileResponse(path)
257
252
  logging.warning(f"path not configured {request.match_info['path']}")
258
253
  return web.HTTPForbidden(reason='path not permitted')
259
254
 
@@ -263,8 +258,8 @@ class WwwServer:
263
258
  logging.info(f"WS from {peer}")
264
259
  ws = web.WebSocketResponse(max_msg_size=0) # disables max message size
265
260
  await ws.prepare(request)
266
- await WSHandler(ws, self.pages, self.tag_info, self.busclient.rqs
267
- ).connection_active()
261
+ await WSHandler(ws, self.pages, self.tag_info, self.busclient.rta,
262
+ self.interface).connection_active()
268
263
  await ws.close()
269
264
  logging.info(f"WS closed {peer}")
270
265
  return ws
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymscada
3
- Version: 0.1.0a6
3
+ Version: 0.1.1a2
4
4
  Summary: Shared tag value SCADA with python backup and Angular UI
5
5
  Author-Email: Jamie Walton <jamie@walton.net.nz>
6
6
  License: GPL-3.0-or-later
@@ -13,7 +13,7 @@ Classifier: Development Status :: 1 - Planning
13
13
  Requires-Python: >=3.9
14
14
  Requires-Dist: PyYAML>=6.0.1
15
15
  Requires-Dist: aiohttp>=3.8.5
16
- Requires-Dist: pymscada-html==0.1.0a1
16
+ Requires-Dist: pymscada-html==0.1.0
17
17
  Requires-Dist: cerberus>=1.3.5
18
18
  Requires-Dist: pycomm3>=1.2.14
19
19
  Requires-Dist: pysnmplib>=5.0.24
@@ -1,23 +1,24 @@
1
- pymscada-0.1.0a6.dist-info/METADATA,sha256=sx8uSsELBZGSQfYO2gnHoRln4LYXrEMjrqXoPeCUNao,3216
2
- pymscada-0.1.0a6.dist-info/WHEEL,sha256=N2J68yzZqJh3mI_Wg92rwhw0rtJDFpZj9bwQIMJgaVg,90
3
- pymscada-0.1.0a6.dist-info/entry_points.txt,sha256=AcZZ7HFj8k1ztP6ge-5bdRinYF8glW2s6lFEQG3esN4,57
4
- pymscada-0.1.0a6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
1
+ pymscada-0.1.1a2.dist-info/METADATA,sha256=dOIdGvZZT4QA4yp4O2v9oYVUNmyDSJb9uOkfq3MkSpw,3214
2
+ pymscada-0.1.1a2.dist-info/WHEEL,sha256=vnE8JVcI2Wz7GRKorsPArnBdnW2SWKWGow5gu5tHlRU,90
3
+ pymscada-0.1.1a2.dist-info/entry_points.txt,sha256=AcZZ7HFj8k1ztP6ge-5bdRinYF8glW2s6lFEQG3esN4,57
4
+ pymscada-0.1.1a2.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
5
5
  pymscada/__init__.py,sha256=D_4aEDWkW6xMVQane3CbehBKPxT3FCaDY_QpFwglCe8,653
6
6
  pymscada/__main__.py,sha256=WcyVlrYOoDdktJhOoyubTOycMwpayksFdxwelRU5xpQ,272
7
- pymscada/bus_client.py,sha256=A6EI3OafyOBKd8UVFXS4K39SpmwBoFE-kSIwldVeDKE,8695
8
- pymscada/bus_server.py,sha256=-Bn4rfdE4OWXE0av459sROnCwAqV0VKFWulF0m1abHE,11255
7
+ pymscada/bus_client.py,sha256=PncKysSCWhcpCPTVq9kkfb4NOjds7bZBwH7jaLHX3nI,8884
8
+ pymscada/bus_server.py,sha256=3ZLT2QFfKMndrTVd1TRWk15rYtaXnW1Ls2dlZe5nsyM,11544
9
9
  pymscada/checkout.py,sha256=ISXhwRJbZBRu0cMeVHwgHzMgk9YslhnPtjs7-0lgjRo,3351
10
10
  pymscada/config.py,sha256=vwGxieaJBYXiHNQEOYVDFaPuGmnUlCnbNm_W9bugKlc,1851
11
- pymscada/console.py,sha256=sw1k6eXY53S8qMR-kx8pHOyhXHHt88e4RTcXmC7AQlw,946
11
+ pymscada/console.py,sha256=oNsZjGlu16B7_2jCIl8Sw6bVfmJeoDdN-JcmA3LyzUw,8011
12
12
  pymscada/demo/README.md,sha256=iNcVbCTkq-d4agLV-979lNRaqf_hbJCn3OFzY-6qfU8,880
13
13
  pymscada/demo/__init__.py,sha256=WsDDgkWnZBJbt2-cJCdc2NvRAv_T4a7WOC1Q0k_l0gI,29
14
14
  pymscada/demo/bus.yaml,sha256=zde5JDo2Yv5s7NvJ569gAEoTDvsvgBwRPxfrYhsxj3w,26
15
- pymscada/demo/files.yaml,sha256=Uizvo-LEhHCRePGNLdvl9m_Z40qOlT7aZDLE4zTFSMc,169
15
+ pymscada/demo/files.yaml,sha256=9jhZ7H5dSUz0oKXUiIB9dVYF8J8nwgt4QaFbvhKRPh0,197
16
16
  pymscada/demo/history.yaml,sha256=mn_Xf4h_bK6vwZVQ0Iz9BzJpwWok2gEgSKbDgEM8AOQ,46
17
17
  pymscada/demo/logixclient.yaml,sha256=G_NlJhBYwT1a9ceHDgO6fCNKFmBM2pVO_t9Xa1NqlRY,912
18
18
  pymscada/demo/modbus_plc.py,sha256=3zZHHbyrdxyryEHBeNIw-fpcDGcS1MaJiqEwQDr6zWI,2397
19
19
  pymscada/demo/modbusclient.yaml,sha256=geeCsUJZkkEj7jjXR_Yk6R5zA5Ta9IczrHsARz7ZgXY,1099
20
20
  pymscada/demo/modbusserver.yaml,sha256=67_mED6jXgtnzlDIky9Cg4j-nXur06iz9ve3JUwSyG8,1133
21
+ pymscada/demo/opnotes.yaml,sha256=1uxAdimPiWlckkRqszh-I3NEi47BNtGraBGLgq8C4L4,111
21
22
  pymscada/demo/ping.yaml,sha256=r_VBGTLU5r4cZi9bIGL3M4eNw70KnoBptOUoNrSbnFY,210
22
23
  pymscada/demo/pymscada-bus.service,sha256=rRTFwHaS8XWd9YAIB3cET4QvASaIO9emmxFiUAbl14g,257
23
24
  pymscada/demo/pymscada-demo-modbus_plc.service,sha256=jmgk_peoxwKVXe-LbyK2VluMS1JMmoTud4JZHi9Tgec,316
@@ -28,33 +29,35 @@ pymscada/demo/pymscada-io-modbusclient.service,sha256=4tenKcrfRi0iMdv8-k2gtMQA4O
28
29
  pymscada/demo/pymscada-io-modbusserver.service,sha256=FqCMD3EJKoiq6EbYnoijRLX5UeUWbZrNzDs50eQj7iE,344
29
30
  pymscada/demo/pymscada-io-ping.service,sha256=d1n32srVKGd8qo8JWeBYEEznCRZWRWaBQLOYzdqEXWg,327
30
31
  pymscada/demo/pymscada-io-snmpclient.service,sha256=wrA2kDR3bgO30lP_lNJrIsVXNQiXmWKnphoqUj3QTRI,339
32
+ pymscada/demo/pymscada-opnotes.service,sha256=5CyKOBlToqyjbyeBE6A68IEov7Y0sPdC_uC1TEJDPRw,350
31
33
  pymscada/demo/pymscada-wwwserver.service,sha256=uDnqzfvAdAnTrqOCqDm1PN7SmeMSuOdmAhorHPJdEVI,366
32
34
  pymscada/demo/snmpclient.yaml,sha256=z8iACrFvMftYUtqGrRjPZYZTpn7aOXI-Kp675NAM8cU,2013
33
35
  pymscada/demo/tags.yaml,sha256=GH90X3QRBANUhvd2E9OuyIoiZD25OBihHHlDBw1uzlw,4231
34
- pymscada/demo/wwwserver.yaml,sha256=jyboShIbwkwgMAcFLkpn88VMvGfoc7a44jNrI_B6OqY,12493
35
- pymscada/files.py,sha256=kEkiD7j5k69EK4jfMHEp-lbTnulYyrtUjkQDa5xmGPc,1784
36
- pymscada/history.py,sha256=yAUfjzo4O3w9-hGEAbtvz9UseMTwRVz7NqS832RtvIs,9455
36
+ pymscada/demo/wwwserver.yaml,sha256=vkRbnZLCf3HXMXmgG_3q0aSShEVzxpGCJLJeWa9REmM,12543
37
+ pymscada/files.py,sha256=FSEvFs6gNgErx_B7mtWkt6EsGNSc-TlxEbDW59NxIZs,2439
38
+ pymscada/history.py,sha256=G079gHfzasmGtI5ANS8MdETD4bdZg5vHE_yTKk7atHw,9504
37
39
  pymscada/iodrivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
- pymscada/iodrivers/logix_client.py,sha256=wDhl0pCqs_k7Hd1MtbOuBrEx9emOwDrLJqBNussH1qU,2806
40
+ pymscada/iodrivers/logix_client.py,sha256=eqmiYLYUBHbr7wTljomGIZVNvXe-5WleGKfzwcHXO8w,2829
39
41
  pymscada/iodrivers/logix_map.py,sha256=ljjBAMJcw199v1V5u0Yfl38U6zbZzba5mdY4I3ZvdIM,5401
40
- pymscada/iodrivers/modbus_client.py,sha256=mo7VRLWi4W2J5Ft3M6Y5jSbK5vbd6wn4R2dncbiL4nU,9529
41
- pymscada/iodrivers/modbus_map.py,sha256=ihkb6xEXNQa5JDFklajjq4W8I4UHPsdOGe2MyHHwXYw,7172
42
- pymscada/iodrivers/modbus_server.py,sha256=nnUjd6iCny_Abylk06J8dq4slNAyNPQC2Rw2ZWEElKM,6507
43
- pymscada/iodrivers/ping_client.py,sha256=dIR4SuKeNCu2FyhUNfTbkv-El3qPFMb0zUG1GJSD-80,4166
42
+ pymscada/iodrivers/modbus_client.py,sha256=DIGrEPz_Bwwj9CEeog5fQqiAu1UMV7xVL6KxlKgXNPs,9592
43
+ pymscada/iodrivers/modbus_map.py,sha256=af2J3CGSeYQ4mSy8rNsERp9z7fRgRUYk3it5Mrc_IQA,7255
44
+ pymscada/iodrivers/modbus_server.py,sha256=VqvjOJ4-LOVaD1jOK22raXhrCshJEaWlMxLvn5xMnFc,6570
45
+ pymscada/iodrivers/ping_client.py,sha256=UOQgUfoIcYqy5VvKyJ8XGHHjeSRTfjmrhyWEojhIZQk,4188
44
46
  pymscada/iodrivers/ping_map.py,sha256=EbOteqfEYKIOMqPymROJ4now2If-ekEj6jnM5hthoSA,1403
45
- pymscada/iodrivers/snmp_client.py,sha256=fBBE7SJjfcf9Y9zKRqgGMktnk6RoVMVc5Mj05ffk6ds,2601
46
- pymscada/iodrivers/snmp_map.py,sha256=rCTniik40Yy6avooIW8PqWanrnUglwBLKReIM7Ab5lA,2369
47
- pymscada/main.py,sha256=KbKX_NzEAX7uwmx9Ms4vbgq4kvg-Aiw5eMjxS8D3A5M,5998
47
+ pymscada/iodrivers/snmp_client.py,sha256=GykrHqKhT-TRIEowLlt90pNQrbm4SXeMBFscflSHtCw,2623
48
+ pymscada/iodrivers/snmp_map.py,sha256=sDdIR5ZPAETpozDfBt_XQiZ-f4t99UCPlzj7BxFxQyM,2369
49
+ pymscada/main.py,sha256=ifu6DuQcI6QpK8w28QAKpbf8gWiaG-zzPoRVorxjFpY,8097
48
50
  pymscada/misc.py,sha256=0Cj6OFhQonyhyk9x0BG5MiS-6EPk_w6zvavt8o_Hlf0,622
51
+ pymscada/opnotes.py,sha256=jo9E0if2dcv1ziGjrLqyzaf-eZvBihtLizP9GmWt5ok,4377
49
52
  pymscada/pdf/__init__.py,sha256=WsDDgkWnZBJbt2-cJCdc2NvRAv_T4a7WOC1Q0k_l0gI,29
50
53
  pymscada/pdf/one.pdf,sha256=eoJ45DrAjVZrwmwdA_EAz1fwmT44eRnt_tkc2pmMrKY,1488
51
54
  pymscada/pdf/two.pdf,sha256=TAuW5yLU1_wfmTH_I5ezHwY0pxhCVuZh3ixu0kwmJwE,1516
52
55
  pymscada/periodic.py,sha256=MLlL93VLvFqBBgjO1Us1t0aLHTZ5BFdW0B__G02T1nQ,1235
53
- pymscada/protocol_constants.py,sha256=ndFeuzhWjKTr_ahvmGJc6Cs5pYkHM8CRgNNDe0Tqecs,1997
56
+ pymscada/protocol_constants.py,sha256=scqu_vecB4U8WxbFbn3mdIhKuZWgNO7fyd-RMP5O_14,2094
54
57
  pymscada/samplers.py,sha256=t0IscgsCm5YByioOZ6aOKMO_guDFS_wxnJSiOGKI4Nw,2583
55
- pymscada/tag.py,sha256=Q2EgacTnsxnGLM_zoHYsVWdwmd1faqfbxw9byI5fCgY,9463
58
+ pymscada/tag.py,sha256=E9xQkf3b0trDRshhsaz_2baa4CAvTCgcZQXqWd3oHEM,10095
56
59
  pymscada/tools/snmp_client2.py,sha256=pdn5dYyEv4q-ubA0zQ8X-3tQDYxGC7f7Xexa7QPaL40,1675
57
60
  pymscada/tools/walk.py,sha256=OgpprUbKLhEWMvJGfU1ckUt_PFEpwZVOD8HucCgzmOc,1625
58
61
  pymscada/validate.py,sha256=VPpAVEwfgori5OREEwWlbPoPxz5Tfqr6dw-O5pINHyI,13125
59
- pymscada/www_server.py,sha256=BW6-ctE5BgyFDiyUJsOpe3c06DRp8k83MCGjwPh5fco,11473
60
- pymscada-0.1.0a6.dist-info/RECORD,,
62
+ pymscada/www_server.py,sha256=ToTddnrnmcLdL2JDviBZ1nflw8wi8bBIk8uSxE6jvWk,11465
63
+ pymscada-0.1.1a2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.1.8)
2
+ Generator: pdm-backend (2.3.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any