PyAutomationIO 1.1.0__tar.gz → 1.1.2__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 (147) hide show
  1. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PKG-INFO +1 -1
  2. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PyAutomationIO.egg-info/PKG-INFO +1 -1
  3. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/core.py +10 -2
  4. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/alarms.py +30 -5
  5. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/events.py +30 -5
  6. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/alarms.py +11 -3
  7. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/datalogger.py +78 -20
  8. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/events.py +11 -3
  9. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/alarms/resources/summary.py +3 -1
  10. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/events/resources/events.py +3 -1
  11. pyautomationio-1.1.2/version.py +2 -0
  12. pyautomationio-1.1.0/version.py +0 -2
  13. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/LICENSE +0 -0
  14. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/MANIFEST.in +0 -0
  15. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PyAutomationIO.egg-info/SOURCES.txt +0 -0
  16. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PyAutomationIO.egg-info/dependency_links.txt +0 -0
  17. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PyAutomationIO.egg-info/requires.txt +0 -0
  18. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/PyAutomationIO.egg-info/top_level.txt +0 -0
  19. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/README.md +0 -0
  20. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/__init__.py +0 -0
  21. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/alarms/__init__.py +0 -0
  22. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/alarms/states.py +0 -0
  23. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/alarms/trigger.py +0 -0
  24. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/buffer.py +0 -0
  25. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/__init__.py +0 -0
  26. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/core.py +0 -0
  27. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/logs.py +0 -0
  28. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/machines.py +0 -0
  29. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/opcua.py +0 -0
  30. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/opcua_server.py +0 -0
  31. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/tags.py +0 -0
  32. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/dbmodels/users.py +0 -0
  33. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/extensions/__init__.py +0 -0
  34. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/extensions/api.py +0 -0
  35. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/extensions/cors.py +0 -0
  36. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/filter/__init__.py +0 -0
  37. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/iad/__init__.py +0 -0
  38. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/iad/frozen_data.py +0 -0
  39. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/iad/out_of_range.py +0 -0
  40. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/iad/outliers.py +0 -0
  41. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/__init__.py +0 -0
  42. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/core.py +0 -0
  43. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/logdict.py +0 -0
  44. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/logs.py +0 -0
  45. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/machines.py +0 -0
  46. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/opcua_server.py +0 -0
  47. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/logger/users.py +0 -0
  48. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/managers/__init__.py +0 -0
  49. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/managers/alarms.py +0 -0
  50. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/managers/db.py +0 -0
  51. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/managers/opcua_client.py +0 -0
  52. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/managers/state_machine.py +0 -0
  53. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/models.py +0 -0
  54. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/__init__.py +0 -0
  55. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/alarms/__init__.py +0 -0
  56. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/alarms/resources/__init__.py +0 -0
  57. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/alarms/resources/alarms.py +0 -0
  58. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/events/__init__.py +0 -0
  59. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/events/resources/__init__.py +0 -0
  60. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/events/resources/logs.py +0 -0
  61. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/tags/__init__.py +0 -0
  62. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/tags/resources/__init__.py +0 -0
  63. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/tags/resources/tags.py +0 -0
  64. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/__init__.py +0 -0
  65. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/__init__.py +0 -0
  66. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/models/__init__.py +0 -0
  67. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/models/roles.py +0 -0
  68. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/models/users.py +0 -0
  69. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/roles.py +0 -0
  70. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/resources/users.py +0 -0
  71. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/roles.py +0 -0
  72. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/modules/users/users.py +0 -0
  73. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/opcua/__init__.py +0 -0
  74. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/opcua/models.py +0 -0
  75. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/opcua/subscription.py +0 -0
  76. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/__init__.py +0 -0
  77. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/alarms.py +0 -0
  78. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/alarms_history.py +0 -0
  79. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/assets/styles.css +0 -0
  80. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/__init__.py +0 -0
  81. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/alarms.py +0 -0
  82. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/alarms_summary.py +0 -0
  83. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/db.py +0 -0
  84. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/filter.py +0 -0
  85. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/machines.py +0 -0
  86. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/machines_detailed.py +0 -0
  87. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/opcua.py +0 -0
  88. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/opcua_server.py +0 -0
  89. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/tags.py +0 -0
  90. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/callbacks/trends.py +0 -0
  91. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/communications.py +0 -0
  92. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/__init__.py +0 -0
  93. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/alarms.py +0 -0
  94. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/alarms_summary.py +0 -0
  95. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/database.py +0 -0
  96. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/gaussian_filter.py +0 -0
  97. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/machines.py +0 -0
  98. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/opcua.py +0 -0
  99. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/opcua_server.py +0 -0
  100. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/tags.py +0 -0
  101. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/components/trends.py +0 -0
  102. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/database.py +0 -0
  103. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/filter.py +0 -0
  104. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/machines.py +0 -0
  105. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/machines_detailed.py +0 -0
  106. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/main.py +0 -0
  107. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/opcua_server.py +0 -0
  108. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/tags.py +0 -0
  109. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/pages/trends.py +0 -0
  110. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/singleton.py +0 -0
  111. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/state_machine.py +0 -0
  112. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tags/__init__.py +0 -0
  113. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tags/cvt.py +0 -0
  114. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tags/filter.py +0 -0
  115. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tags/tag.py +0 -0
  116. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tests/__init__.py +0 -0
  117. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tests/test_alarms.py +0 -0
  118. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tests/test_core.py +0 -0
  119. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tests/test_unit.py +0 -0
  120. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/tests/test_user.py +0 -0
  121. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/utils/__init__.py +0 -0
  122. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/utils/decorators.py +0 -0
  123. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/utils/npw.py +0 -0
  124. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/utils/observer.py +0 -0
  125. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/utils/units.py +0 -0
  126. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/__init__.py +0 -0
  127. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/adimentional.py +0 -0
  128. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/current.py +0 -0
  129. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/density.py +0 -0
  130. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/eng_time.py +0 -0
  131. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/force.py +0 -0
  132. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/length.py +0 -0
  133. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/mass.py +0 -0
  134. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/mass_flow.py +0 -0
  135. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/percentage.py +0 -0
  136. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/power.py +0 -0
  137. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/pressure.py +0 -0
  138. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/temperature.py +0 -0
  139. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/volume.py +0 -0
  140. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/variables/volumetric_flow.py +0 -0
  141. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/workers/__init__.py +0 -0
  142. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/workers/logger.py +0 -0
  143. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/workers/state_machine.py +0 -0
  144. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/automation/workers/worker.py +0 -0
  145. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/requirements.txt +0 -0
  146. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/setup.cfg +0 -0
  147. {pyautomationio-1.1.0 → pyautomationio-1.1.2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAutomationIO
3
- Version: 1.1.0
3
+ Version: 1.1.2
4
4
  Summary: A python library to develop automation continuous tasks using sync or async concurrent threads
5
5
  Home-page: https://github.com/know-ai/PyAutomation
6
6
  Author: KnowAI
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyAutomationIO
3
- Version: 1.1.0
3
+ Version: 1.1.2
4
4
  Summary: A python library to develop automation continuous tasks using sync or async concurrent threads
5
5
  Home-page: https://github.com/know-ai/PyAutomation
6
6
  Author: KnowAI
@@ -1370,6 +1370,10 @@ class PyAutomation(Singleton):
1370
1370
  Documentation here
1371
1371
  """
1372
1372
  if self.is_db_connected():
1373
+
1374
+ # Ensure pagination parameters are present or defaulted
1375
+ if 'page' not in fields: fields['page'] = 1
1376
+ if 'limit' not in fields: fields['limit'] = 20
1373
1377
 
1374
1378
  return self.alarms_engine.filter_alarm_summary_by(**fields)
1375
1379
 
@@ -1542,7 +1546,9 @@ class PyAutomation(Singleton):
1542
1546
  description:str="",
1543
1547
  greater_than_timestamp:datetime=None,
1544
1548
  less_than_timestamp:datetime=None,
1545
- timezone:str="UTC")->list:
1549
+ timezone:str="UTC",
1550
+ page:int=1,
1551
+ limit:int=20)->list:
1546
1552
  r"""
1547
1553
  Documentation here
1548
1554
  """
@@ -1557,7 +1563,9 @@ class PyAutomation(Singleton):
1557
1563
  classification=classification,
1558
1564
  greater_than_timestamp=greater_than_timestamp,
1559
1565
  less_than_timestamp=less_than_timestamp,
1560
- timezone=timezone
1566
+ timezone=timezone,
1567
+ page=page,
1568
+ limit=limit
1561
1569
  )
1562
1570
 
1563
1571
  return list()
@@ -448,11 +448,14 @@ class AlarmSummary(BaseModel):
448
448
  tags:list[str]=None,
449
449
  greater_than_timestamp:datetime=None,
450
450
  less_than_timestamp:datetime=None,
451
- timezone:str='UTC'
451
+ timezone:str='UTC',
452
+ page:int=1,
453
+ limit:int=20
452
454
  ):
453
455
  r"""
454
456
  Documentation here
455
457
  """
458
+ import math
456
459
  _timezone = pytz.timezone(timezone)
457
460
  query = cls.select()
458
461
 
@@ -478,11 +481,33 @@ class AlarmSummary(BaseModel):
478
481
  query = query.where(cls.alarm_time < less_than_timestamp)
479
482
 
480
483
  query = query.order_by(cls.id.desc())
481
- if not query.exists():
482
-
483
- return []
484
484
 
485
- return [alarm.serialize() for alarm in query]
485
+ total_records = query.count()
486
+
487
+ if limit <= 0: limit = 20
488
+ if page <= 0: page = 1
489
+
490
+ total_pages = math.ceil(total_records / limit)
491
+ if total_pages == 0: total_pages = 1
492
+
493
+ has_next = page < total_pages
494
+ has_prev = page > 1
495
+
496
+ paginated_query = query.paginate(page, limit)
497
+
498
+ data = [alarm.serialize() for alarm in paginated_query]
499
+
500
+ return {
501
+ "data": data,
502
+ "pagination": {
503
+ "page": page,
504
+ "limit": limit,
505
+ "total_records": total_records,
506
+ "total_pages": total_pages,
507
+ "has_next": has_next,
508
+ "has_prev": has_prev
509
+ }
510
+ }
486
511
 
487
512
  @classmethod
488
513
  def get_alarm_summary_comments(cls, id:int):
@@ -77,10 +77,14 @@ class Events(BaseModel):
77
77
  description:str="",
78
78
  message:str="",
79
79
  classification:str="",
80
- timezone:str='UTC'):
80
+ timezone:str='UTC',
81
+ page:int=1,
82
+ limit:int=20
83
+ ):
81
84
  r"""
82
85
  Documentation here
83
86
  """
87
+ import math
84
88
  _timezone = pytz.timezone(timezone)
85
89
  query = cls.select()
86
90
 
@@ -113,11 +117,32 @@ class Events(BaseModel):
113
117
 
114
118
  query = query.order_by(cls.id.desc())
115
119
 
116
- if not query.exists():
117
-
118
- return []
120
+ total_records = query.count()
121
+
122
+ if limit <= 0: limit = 20
123
+ if page <= 0: page = 1
124
+
125
+ total_pages = math.ceil(total_records / limit)
126
+ if total_pages == 0: total_pages = 1
127
+
128
+ has_next = page < total_pages
129
+ has_prev = page > 1
119
130
 
120
- return [event.serialize() for event in query]
131
+ paginated_query = query.paginate(page, limit)
132
+
133
+ data = [event.serialize() for event in paginated_query]
134
+
135
+ return {
136
+ "data": data,
137
+ "pagination": {
138
+ "page": page,
139
+ "limit": limit,
140
+ "total_records": total_records,
141
+ "total_pages": total_pages,
142
+ "has_next": has_next,
143
+ "has_prev": has_prev
144
+ }
145
+ }
121
146
 
122
147
  @classmethod
123
148
  def get_comments(cls, id:int):
@@ -119,7 +119,9 @@ class AlarmsLogger(BaseLogger):
119
119
  tags:list[str]=None,
120
120
  greater_than_timestamp:datetime=None,
121
121
  less_than_timestamp:datetime=None,
122
- timezone:str="UTC"
122
+ timezone:str="UTC",
123
+ page:int=1,
124
+ limit:int=20
123
125
  ):
124
126
  r"""
125
127
  Documentation here
@@ -138,7 +140,9 @@ class AlarmsLogger(BaseLogger):
138
140
  tags=tags,
139
141
  greater_than_timestamp=greater_than_timestamp,
140
142
  less_than_timestamp=less_than_timestamp,
141
- timezone=timezone
143
+ timezone=timezone,
144
+ page=page,
145
+ limit=limit
142
146
  )
143
147
 
144
148
  @db_rollback
@@ -326,7 +330,9 @@ class AlarmsLoggerEngine(BaseEngine):
326
330
  tags:list[int]=None,
327
331
  greater_than_timestamp:datetime=None,
328
332
  less_than_timestamp:datetime=None,
329
- timezone:str='UTC'
333
+ timezone:str='UTC',
334
+ page:int=1,
335
+ limit:int=20
330
336
  ):
331
337
 
332
338
  _query = dict()
@@ -338,6 +344,8 @@ class AlarmsLoggerEngine(BaseEngine):
338
344
  _query["parameters"]["greater_than_timestamp"] = greater_than_timestamp
339
345
  _query["parameters"]["less_than_timestamp"] = less_than_timestamp
340
346
  _query["parameters"]["timezone"] = timezone
347
+ _query["parameters"]["page"] = page
348
+ _query["parameters"]["limit"] = limit
341
349
 
342
350
  return self.query(_query)
343
351
 
@@ -5,6 +5,7 @@ This module implements a database logger for the CVT instance,
5
5
  will create a time-serie for each tag in a short memory data base.
6
6
  """
7
7
  import pytz, logging, math
8
+ from peewee import fn
8
9
  from collections import defaultdict
9
10
  from datetime import datetime
10
11
  from ..tags.tag import Tag
@@ -404,7 +405,9 @@ class DataLogger(BaseLogger):
404
405
 
405
406
  Returns:
406
407
  dict: {
407
- "data": [...],
408
+ "tag_names": ["timestamp", "tag1", ...],
409
+ "display_names": ["timestamp", "Display Tag 1", ...],
410
+ "values": [[ts, val1, ...], ...],
408
411
  "pagination": {...}
409
412
  }
410
413
  """
@@ -425,10 +428,70 @@ class DataLogger(BaseLogger):
425
428
  except ValueError:
426
429
  return dict()
427
430
 
431
+ if sample_time <= 0:
432
+ return dict()
433
+
434
+ # Get display names mapping early
435
+ try:
436
+ tags_info = Tags.select(Tags.name, Tags.display_name).where(Tags.name.in_(tags)).dicts()
437
+ display_map = {t['name']: t['display_name'] for t in tags_info}
438
+ except Exception:
439
+ display_map = {}
440
+
441
+ tag_names = ["timestamp"] + tags
442
+ display_names = ["timestamp"] + [display_map.get(tag, tag) for tag in tags]
443
+
444
+ empty_result = {
445
+ "tag_names": tag_names,
446
+ "display_names": display_names,
447
+ "values": [],
448
+ "pagination": {}
449
+ }
450
+
451
+ # Check for data presence to adjust start time if necessary
452
+ # 1. Check if there is any data BEFORE or AT start_dt (history)
453
+ has_history = (TagValue
454
+ .select()
455
+ .join(Tags)
456
+ .where(
457
+ (Tags.name.in_(tags)) &
458
+ (TagValue.timestamp <= start_dt)
459
+ )
460
+ .limit(1)
461
+ .count() > 0)
462
+
463
+ if not has_history:
464
+ # 2. If no history, find the first actual data point within the requested range
465
+ min_ts = (TagValue
466
+ .select(fn.Min(TagValue.timestamp))
467
+ .join(Tags)
468
+ .where(
469
+ (Tags.name.in_(tags)) &
470
+ (TagValue.timestamp >= start_dt) &
471
+ (TagValue.timestamp <= stop_dt) &
472
+ (TagValue.value.is_null(False))
473
+ )
474
+ .scalar())
475
+
476
+ if min_ts is None:
477
+ # No data in range and no history
478
+ return empty_result
479
+
480
+ # Adjust start to the first actual data point
481
+ # Ensure min_ts is timezone aware if needed, though scalar() returns DB format
482
+ if isinstance(min_ts, datetime):
483
+ if min_ts.tzinfo is None:
484
+ min_ts = utc_timezone.localize(min_ts)
485
+ start_dt = min_ts
486
+ start_ts = start_dt.timestamp()
487
+ elif isinstance(min_ts, (int, float)):
488
+ start_ts = float(min_ts)
489
+ start_dt = datetime.fromtimestamp(start_ts, pytz.UTC)
490
+
428
491
  # Calculate total records based on time range and sample time
429
492
  total_duration = stop_ts - start_ts
430
493
  if total_duration < 0:
431
- return {"data": [], "pagination": {}}
494
+ return empty_result
432
495
 
433
496
  total_records = math.floor(total_duration / sample_time) + 1
434
497
 
@@ -456,13 +519,6 @@ class DataLogger(BaseLogger):
456
519
  data_points = []
457
520
  current_ts = page_start_ts
458
521
 
459
- # Pre-fetch data for optimization could be complex due to forward fill requirement across large gaps.
460
- # However, we can query per tag or query all data in range.
461
- # For efficiency with many tags/large range, we should query intelligently.
462
- # But to guarantee "last known value", we might need to look back indefinitely if no recent data.
463
- # A simple approach for now: Query "last value before or at page_start_ts" for each tag,
464
- # and all values between page_start_ts and page_end_ts.
465
-
466
522
  # 1. Get initial values (state at page_start_ts)
467
523
  current_values = {}
468
524
  # Convert float timestamp to datetime for Peewee comparison
@@ -497,7 +553,8 @@ class DataLogger(BaseLogger):
497
553
  .where(
498
554
  (Tags.name.in_(tags)) &
499
555
  (TagValue.timestamp > page_start_dt) &
500
- (TagValue.timestamp <= page_end_dt)
556
+ (TagValue.timestamp <= page_end_dt) &
557
+ (TagValue.value.is_null(False))
501
558
  )
502
559
  .order_by(TagValue.timestamp.asc())
503
560
  .dicts())
@@ -521,12 +578,6 @@ class DataLogger(BaseLogger):
521
578
  # We iterate step by step. This might be slow if step is small and range is large,
522
579
  # but we are limited by pagination 'limit' (e.g. 20 rows), so it's fast!
523
580
 
524
- # We need to process from page_start_ts to page_end_ts in sample_time steps.
525
- # BUT we have a list of changes.
526
- # The simple way: Iterate steps.
527
-
528
- # Optimization: We have 'limit' steps.
529
-
530
581
  changes_iter = sorted(changes_by_ts.keys())
531
582
  change_idx = 0
532
583
 
@@ -550,14 +601,21 @@ class DataLogger(BaseLogger):
550
601
  dt_object = datetime.fromtimestamp(step_ts, pytz.UTC)
551
602
  formatted_ts = dt_object.astimezone(_timezone).strftime(DATETIME_FORMAT)
552
603
 
553
- row = {"timestamp": formatted_ts}
604
+ row_values = [formatted_ts]
605
+ has_data = False
554
606
  for tag in tags:
555
- row[tag] = current_values.get(tag) # None if no value ever recorded
607
+ val = current_values.get(tag)
608
+ row_values.append(val)
609
+ if val is not None:
610
+ has_data = True
556
611
 
557
- data_points.append(row)
612
+ if has_data:
613
+ data_points.append(row_values)
558
614
 
559
615
  return {
560
- "data": data_points,
616
+ "tag_names": tag_names,
617
+ "display_names": display_names,
618
+ "values": data_points,
561
619
  "pagination": {
562
620
  "page": page,
563
621
  "limit": limit,
@@ -68,7 +68,9 @@ class EventsLogger(BaseLogger):
68
68
  classification:str="",
69
69
  greater_than_timestamp:datetime=None,
70
70
  less_than_timestamp:datetime=None,
71
- timezone:str="UTC"
71
+ timezone:str="UTC",
72
+ page:int=1,
73
+ limit:int=20
72
74
  ):
73
75
  r"""
74
76
  Documentation here
@@ -90,7 +92,9 @@ class EventsLogger(BaseLogger):
90
92
  description=description,
91
93
  greater_than_timestamp=greater_than_timestamp,
92
94
  less_than_timestamp=less_than_timestamp,
93
- timezone=timezone
95
+ timezone=timezone,
96
+ page=page,
97
+ limit=limit
94
98
  )
95
99
 
96
100
  def get_summary(self)->tuple[list, str]:
@@ -164,7 +168,9 @@ class EventsLoggerEngine(BaseEngine):
164
168
  description:str="",
165
169
  greater_than_timestamp:datetime=None,
166
170
  less_than_timestamp:datetime=None,
167
- timezone:str='UTC'
171
+ timezone:str='UTC',
172
+ page:int=1,
173
+ limit:int=20
168
174
  ):
169
175
 
170
176
  _query = dict()
@@ -179,6 +185,8 @@ class EventsLoggerEngine(BaseEngine):
179
185
  _query["parameters"]["greater_than_timestamp"] = greater_than_timestamp
180
186
  _query["parameters"]["less_than_timestamp"] = less_than_timestamp
181
187
  _query["parameters"]["timezone"] = timezone
188
+ _query["parameters"]["page"] = page
189
+ _query["parameters"]["limit"] = limit
182
190
 
183
191
  return self.query(_query)
184
192
 
@@ -16,7 +16,9 @@ alarms_summary_filter_model = api.model("alarms_summary_filter_model",{
16
16
  'tags': fields.List(fields.String(), required=False),
17
17
  'greater_than_timestamp': fields.DateTime(required=False, default=datetime.now(pytz.utc).astimezone(TIMEZONE) - timedelta(minutes=30), description=f'Greater than timestamp - DateTime Format: {app.cvt.DATETIME_FORMAT}'),
18
18
  'less_than_timestamp': fields.DateTime(required=False, default=datetime.now(pytz.utc).astimezone(TIMEZONE), description=f'Less than timestamp - DateTime Format: {app.cvt.DATETIME_FORMAT}'),
19
- 'timezone': fields.String(required=False, default=_TIMEZONE)
19
+ 'timezone': fields.String(required=False, default=_TIMEZONE),
20
+ 'page': fields.Integer(required=False, default=1, description='Page number'),
21
+ 'limit': fields.Integer(required=False, default=20, description='Items per page')
20
22
  })
21
23
 
22
24
 
@@ -20,7 +20,9 @@ events_filter_model = api.model("events_filter_model",{
20
20
  'description': fields.String(required=False),
21
21
  'greater_than_timestamp': fields.DateTime(required=False, default=datetime.now(pytz.utc).astimezone(TIMEZONE) - timedelta(minutes=30), description=f'Greater than timestamp - DateTime Format: {app.cvt.DATETIME_FORMAT}'),
22
22
  'less_than_timestamp': fields.DateTime(required=False, default=datetime.now(pytz.utc).astimezone(TIMEZONE), description=f'Less than timestamp - DateTime Format: {app.cvt.DATETIME_FORMAT}'),
23
- 'timezone': fields.String(required=False, default=_TIMEZONE)
23
+ 'timezone': fields.String(required=False, default=_TIMEZONE),
24
+ 'page': fields.Integer(required=False, default=1, description='Page number'),
25
+ 'limit': fields.Integer(required=False, default=20, description='Items per page')
24
26
  })
25
27
 
26
28
 
@@ -0,0 +1,2 @@
1
+ __version__ = '1.1.2'
2
+
@@ -1,2 +0,0 @@
1
- __version__ = '1.1.0'
2
-
File without changes
File without changes
File without changes
File without changes