pymscada 0.1.9__tar.gz → 0.1.11__tar.gz

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.
Files changed (85) hide show
  1. {pymscada-0.1.9 → pymscada-0.1.11}/PKG-INFO +3 -1
  2. {pymscada-0.1.9 → pymscada-0.1.11}/pyproject.toml +5 -1
  3. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/files.py +12 -17
  4. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/accuweather.py +4 -2
  5. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/www_server.py +6 -7
  6. {pymscada-0.1.9 → pymscada-0.1.11}/LICENSE +0 -0
  7. {pymscada-0.1.9 → pymscada-0.1.11}/README.md +0 -0
  8. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/__init__.py +0 -0
  9. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/__main__.py +0 -0
  10. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/bus_client.py +0 -0
  11. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/bus_server.py +0 -0
  12. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/checkout.py +0 -0
  13. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/config.py +0 -0
  14. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/console.py +0 -0
  15. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/README.md +0 -0
  16. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/__init__.py +0 -0
  17. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/accuweather.yaml +0 -0
  18. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/bus.yaml +0 -0
  19. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/files.yaml +0 -0
  20. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/history.yaml +0 -0
  21. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/logixclient.yaml +0 -0
  22. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/modbus_plc.py +0 -0
  23. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/modbusclient.yaml +0 -0
  24. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/modbusserver.yaml +0 -0
  25. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/opnotes.yaml +0 -0
  26. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/ping.yaml +0 -0
  27. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-bus.service +0 -0
  28. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-demo-modbus_plc.service +0 -0
  29. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-files.service +0 -0
  30. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-history.service +0 -0
  31. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-accuweather.service +0 -0
  32. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-logixclient.service +0 -0
  33. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-modbusclient.service +0 -0
  34. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-modbusserver.service +0 -0
  35. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-ping.service +0 -0
  36. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-io-snmpclient.service +0 -0
  37. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-opnotes.service +0 -0
  38. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/pymscada-wwwserver.service +0 -0
  39. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/snmpclient.yaml +0 -0
  40. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/tags.yaml +0 -0
  41. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/demo/wwwserver.yaml +0 -0
  42. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/history.py +0 -0
  43. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/__init__.py +0 -0
  44. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/logix_client.py +0 -0
  45. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/logix_map.py +0 -0
  46. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/modbus_client.py +0 -0
  47. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/modbus_map.py +0 -0
  48. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/modbus_server.py +0 -0
  49. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/ping_client.py +0 -0
  50. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/ping_map.py +0 -0
  51. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/snmp_client.py +0 -0
  52. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/iodrivers/snmp_map.py +0 -0
  53. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/main.py +0 -0
  54. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/misc.py +0 -0
  55. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/opnotes.py +0 -0
  56. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/pdf/__init__.py +0 -0
  57. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/pdf/one.pdf +0 -0
  58. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/pdf/two.pdf +0 -0
  59. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/periodic.py +0 -0
  60. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/protocol_constants.py +0 -0
  61. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/samplers.py +0 -0
  62. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/tag.py +0 -0
  63. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/tools/snmp_client2.py +0 -0
  64. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/tools/walk.py +0 -0
  65. {pymscada-0.1.9 → pymscada-0.1.11}/src/pymscada/validate.py +0 -0
  66. {pymscada-0.1.9 → pymscada-0.1.11}/tests/__init__.py +0 -0
  67. {pymscada-0.1.9 → pymscada-0.1.11}/tests/bus_echo.py +0 -0
  68. {pymscada-0.1.9 → pymscada-0.1.11}/tests/iodrivers/test_logix.py +0 -0
  69. {pymscada-0.1.9 → pymscada-0.1.11}/tests/iodrivers/test_modbus.py +0 -0
  70. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/busserver.yaml +0 -0
  71. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/db.sqlite +0 -0
  72. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/hist_tag_0_0.dat +0 -0
  73. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/hist_tag_0_10_2.dat +0 -0
  74. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/hist_tag_0_15.dat +0 -0
  75. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/hist_tag_0_26.dat +0 -0
  76. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_assets/hist_tag_0_50.dat +0 -0
  77. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_bus_server.py +0 -0
  78. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_config.py +0 -0
  79. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_history.py +0 -0
  80. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_misc.py +0 -0
  81. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_opnotes.py +0 -0
  82. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_periodic.py +0 -0
  83. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_samplers.py +0 -0
  84. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_tag.py +0 -0
  85. {pymscada-0.1.9 → pymscada-0.1.11}/tests/test_validate.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pymscada
3
- Version: 0.1.9
3
+ Version: 0.1.11
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
@@ -10,6 +10,8 @@ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Environment :: Console
12
12
  Classifier: Development Status :: 1 - Planning
13
+ Project-URL: Homepage, https://github.com/jamie0walton/pymscada
14
+ Project-URL: Bug tracker, https://github.com/jamie0walton/pymscada/issues
13
15
  Requires-Python: >=3.9
14
16
  Requires-Dist: PyYAML>=6.0.1
15
17
  Requires-Dist: aiohttp>=3.8.5
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pymscada"
3
- version = "0.1.9"
3
+ version = "0.1.11"
4
4
  description = "Shared tag value SCADA with python backup and Angular UI"
5
5
  authors = [
6
6
  { name = "Jamie Walton", email = "jamie@walton.net.nz" },
@@ -30,6 +30,10 @@ text = "GPL-3.0-or-later"
30
30
  [project.scripts]
31
31
  pymscada = "pymscada.__main__:cmd_line"
32
32
 
33
+ [project.urls]
34
+ Homepage = "https://github.com/jamie0walton/pymscada"
35
+ "Bug Tracker" = "https://github.com/jamie0walton/pymscada/issues"
36
+
33
37
  [build-system]
34
38
  requires = [
35
39
  "pdm-backend",
@@ -6,9 +6,6 @@ from pymscada.periodic import Periodic
6
6
  from pymscada.tag import Tag
7
7
 
8
8
 
9
- RATE = 10
10
-
11
-
12
9
  class Files():
13
10
  """Connect to bus_ip:bus_port, store and provide a value history."""
14
11
 
@@ -23,7 +20,6 @@ class Files():
23
20
 
24
21
  Event loop must be running.
25
22
  """
26
- self.busclient = BusClient(bus_ip, bus_port, module='Files')
27
23
  self.path = Path(path)
28
24
  self.files = files
29
25
  for file in self.files:
@@ -33,11 +29,19 @@ class Files():
33
29
  file['mode'] = 'ro'
34
30
  file['_path'] = self.path.joinpath(file['path'])
35
31
  file['st_mtime_ns'] = 0
32
+ self.busclient = BusClient(bus_ip, bus_port, module='Files')
36
33
  self.rta = Tag(rta_tag, dict)
34
+ self.rta.value = {}
37
35
  self.busclient.add_callback_rta(rta_tag, self.rta_cb)
38
- self.scan_files()
39
36
 
40
- def scan_files(self):
37
+ def rta_cb(self, request):
38
+ """Respond to Request to Author and publish on rta_tag as needed."""
39
+ if 'action' not in request:
40
+ logging.warning(f'rta_cb malformed {request}')
41
+ logging.info(f'files rta_cb {request}')
42
+ pass
43
+
44
+ async def scan_files(self):
41
45
  """Scan folders for files."""
42
46
  update = False
43
47
  for file in self.files:
@@ -57,19 +61,10 @@ class Files():
57
61
  'name': fn.name,
58
62
  'desc': file['desc'],
59
63
  'mode': file['mode']})
60
- self.rta.value = {'__rta_id__': 0, 'dat': info}
61
-
62
- def rta_cb(self, tag):
63
- """Respond to bus requests for data to publish on rta."""
64
- logging.info(f'files rta_cb {tag.name} {tag.value}')
65
- pass
66
-
67
- async def check_files(self):
68
- """Check to see if any files have changed."""
69
- self.scan_files()
64
+ self.rta.value = {'dat': info}
70
65
 
71
66
  async def start(self):
72
67
  """Async startup."""
73
68
  await self.busclient.start()
74
- self.periodic = Periodic(self.check_files, RATE)
69
+ self.periodic = Periodic(self.scan_files, 10.0)
75
70
  await self.periodic.start()
@@ -42,7 +42,7 @@ class AccuWeatherClient:
42
42
  for record in json:
43
43
  epoch = record['EpochDateTime']
44
44
  hour = int((epoch - time_mod) / 3600)
45
- logging.warning(f'epoch {epoch} time_s {time_s} hour {hour}')
45
+ logging.info(f'epoch {epoch} time_s {time_s} hour {hour}')
46
46
  if hour not in self.api['times']:
47
47
  continue
48
48
  suffix = ''
@@ -55,11 +55,13 @@ class AccuWeatherClient:
55
55
  ['Rain', 'Rain', None, 'Value'],
56
56
  ['Snow', 'Snow', None, 'Value']
57
57
  ]:
58
- tag = self.tags[f'{site}{parm}{suffix}']
58
+ tagname = f'{site}{parm}{suffix}'
59
+ tag = self.tags[tagname]
59
60
  if key2 is None:
60
61
  value = record[key1][key]
61
62
  else:
62
63
  value = record[key1][key2][key]
64
+ logging.info(f'{tagname} was {tag.value} new {value}')
63
65
  if tag.value != value:
64
66
  tag.value = value, int(epoch * 1e6), self.map_bus
65
67
 
@@ -63,9 +63,8 @@ class WSHandler():
63
63
  # logging.debug(f'{self.rta_id} as json {message}')
64
64
  await self.ws.send_json(message)
65
65
  except asyncio.CancelledError:
66
- logging.warn(f'{self.rta_id}: send queue error, close '
67
- f'{self.ws.exception()}')
68
- return
66
+ logging.warning(f'{self.rta_id}: send queue error, close '
67
+ f'{self.ws.exception()}')
69
68
 
70
69
  def publish(self, tag: Tag):
71
70
  """
@@ -200,8 +199,8 @@ class WSHandler():
200
199
  elif msg.type == WSMsgType.BINARY:
201
200
  logging.info(f'{msg.data}')
202
201
  elif msg.type == WSMsgType.ERROR:
203
- logging.warn(f'{self.rta_id}: ws closing error '
204
- f'{self.ws.exception()}')
202
+ logging.warning(f'{self.rta_id}: ws closing error '
203
+ f'{self.ws.exception()}')
205
204
  send_queue.cancel()
206
205
  for tag in self.tag_by_id.values():
207
206
  tag.del_callback_id(self.notify_id)
@@ -263,8 +262,8 @@ class WwwServer:
263
262
  if not path.exists():
264
263
  return web.HTTPNotFound(reason='no such file in path')
265
264
  return web.FileResponse(path)
266
- logging.warning(f"path not configured {request.match_info['path']}")
267
- return web.HTTPForbidden(reason='path not permitted')
265
+ # logging.warning(f"path not configured {request.match_info['path']}")
266
+ # return web.HTTPForbidden(reason='path not permitted')
268
267
 
269
268
  async def websocket_handler(self, request: web.Request):
270
269
  """Wait for connections. Create a new one each time."""
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes