sciveo 0.1.72__tar.gz → 0.1.74__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 (175) hide show
  1. {sciveo-0.1.72 → sciveo-0.1.74}/PKG-INFO +3 -1
  2. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/cli.py +11 -3
  3. sciveo-0.1.74/sciveo/db/read_table.py +204 -0
  4. sciveo-0.1.74/sciveo/monitoring/power/ems300.py +107 -0
  5. sciveo-0.1.74/sciveo/monitoring/power/sim.py +71 -0
  6. sciveo-0.1.74/sciveo/monitoring/power/tools.py +394 -0
  7. sciveo-0.1.74/sciveo/tools/draw/__init__.py +0 -0
  8. sciveo-0.1.74/sciveo/version.py +2 -0
  9. sciveo-0.1.74/sciveo/web/__init__.py +0 -0
  10. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/PKG-INFO +3 -1
  11. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/SOURCES.txt +6 -0
  12. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/requires.txt +8 -0
  13. {sciveo-0.1.72 → sciveo-0.1.74}/setup.py +8 -0
  14. sciveo-0.1.72/sciveo/version.py +0 -2
  15. {sciveo-0.1.72 → sciveo-0.1.74}/README.md +0 -0
  16. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/__init__.py +0 -0
  17. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/api/__init__.py +0 -0
  18. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/api/base.py +0 -0
  19. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/api/predictors.py +0 -0
  20. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/api/server.py +0 -0
  21. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/api/upload.py +0 -0
  22. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/common/__init__.py +0 -0
  23. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/common/configuration.py +0 -0
  24. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/common/model.py +0 -0
  25. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/common/optimizers.py +0 -0
  26. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/common/sampling.py +0 -0
  27. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/content/__init__.py +0 -0
  28. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/content/dataset.py +0 -0
  29. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/content/experiment.py +0 -0
  30. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/content/project.py +0 -0
  31. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/content/runner.py +0 -0
  32. {sciveo-0.1.72/sciveo/media → sciveo-0.1.74/sciveo/db}/__init__.py +0 -0
  33. {sciveo-0.1.72/sciveo/media/capture → sciveo-0.1.74/sciveo/media}/__init__.py +0 -0
  34. {sciveo-0.1.72/sciveo/media/ml → sciveo-0.1.74/sciveo/media/capture}/__init__.py +0 -0
  35. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/capture/cam.py +0 -0
  36. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/capture/motion_detection.py +0 -0
  37. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/capture/nvr.py +0 -0
  38. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/capture/readers.py +0 -0
  39. {sciveo-0.1.72/sciveo/media/ml/encoders → sciveo-0.1.74/sciveo/media/ml}/__init__.py +0 -0
  40. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/base.py +0 -0
  41. {sciveo-0.1.72/sciveo/media/ml/nlp → sciveo-0.1.74/sciveo/media/ml/encoders}/__init__.py +0 -0
  42. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/encoders/base.py +0 -0
  43. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/encoders/normalizer.py +0 -0
  44. {sciveo-0.1.72/sciveo/media/ml/time_series → sciveo-0.1.74/sciveo/media/ml/nlp}/__init__.py +0 -0
  45. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/nlp/search.py +0 -0
  46. {sciveo-0.1.72/sciveo/media/pipelines → sciveo-0.1.74/sciveo/media/ml/time_series}/__init__.py +0 -0
  47. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/time_series/dataset.py +0 -0
  48. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/time_series/predictor.py +0 -0
  49. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/time_series/trainer.py +0 -0
  50. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/ml/time_series/window_generator.py +0 -0
  51. {sciveo-0.1.72/sciveo/media/pipelines/layouts → sciveo-0.1.74/sciveo/media/pipelines}/__init__.py +0 -0
  52. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/base.py +0 -0
  53. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/job_daemon.py +0 -0
  54. {sciveo-0.1.72/sciveo/media/pipelines/postprocessors → sciveo-0.1.74/sciveo/media/pipelines/layouts}/__init__.py +0 -0
  55. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/layouts/base.py +0 -0
  56. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/pipeline.py +0 -0
  57. {sciveo-0.1.72/sciveo/media/pipelines/processors → sciveo-0.1.74/sciveo/media/pipelines/postprocessors}/__init__.py +0 -0
  58. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/postprocessors/base.py +0 -0
  59. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/postprocessors/default.py +0 -0
  60. {sciveo-0.1.72/sciveo/media/pipelines/processors/audio → sciveo-0.1.74/sciveo/media/pipelines/processors}/__init__.py +0 -0
  61. {sciveo-0.1.72/sciveo/media/pipelines/processors/file → sciveo-0.1.74/sciveo/media/pipelines/processors/audio}/__init__.py +0 -0
  62. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/audio/audio.py +0 -0
  63. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/audio/audio_extractor_process.py +0 -0
  64. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/aws.py +0 -0
  65. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/base.py +0 -0
  66. {sciveo-0.1.72/sciveo/media/pipelines/processors/image → sciveo-0.1.74/sciveo/media/pipelines/processors/file}/__init__.py +0 -0
  67. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/file/archive.py +0 -0
  68. {sciveo-0.1.72/sciveo/media/pipelines/processors/nlp → sciveo-0.1.74/sciveo/media/pipelines/processors/image}/__init__.py +0 -0
  69. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/album.py +0 -0
  70. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/album_in_image.py +0 -0
  71. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/depth_esimation.py +0 -0
  72. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/embeddings.py +0 -0
  73. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/filters.py +0 -0
  74. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/generators.py +0 -0
  75. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/histogram.py +0 -0
  76. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/mask.py +0 -0
  77. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/object_detection.py +0 -0
  78. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/resize.py +0 -0
  79. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/segmentation.py +0 -0
  80. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/image/watermark.py +0 -0
  81. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/media_info.py +0 -0
  82. {sciveo-0.1.72/sciveo/media/pipelines/processors/sci → sciveo-0.1.74/sciveo/media/pipelines/processors/nlp}/__init__.py +0 -0
  83. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/nlp/address.py +0 -0
  84. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/qr.py +0 -0
  85. {sciveo-0.1.72/sciveo/media/pipelines/processors/sci/time_series → sciveo-0.1.74/sciveo/media/pipelines/processors/sci}/__init__.py +0 -0
  86. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/sci/base.py +0 -0
  87. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/sci/dataset.py +0 -0
  88. {sciveo-0.1.72/sciveo/media/pipelines/processors/video → sciveo-0.1.74/sciveo/media/pipelines/processors/sci/time_series}/__init__.py +0 -0
  89. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/sci/time_series/predictor.py +0 -0
  90. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/sci/time_series/trainer.py +0 -0
  91. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/tpu_base.py +0 -0
  92. {sciveo-0.1.72/sciveo/media/pipelines/web → sciveo-0.1.74/sciveo/media/pipelines/processors/video}/__init__.py +0 -0
  93. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/generators.py +0 -0
  94. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/motion_detection.py +0 -0
  95. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/resize.py +0 -0
  96. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/video_album.py +0 -0
  97. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/video_frames.py +0 -0
  98. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/processors/video/video_resample.py +0 -0
  99. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/queues.py +0 -0
  100. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/server.py +0 -0
  101. {sciveo-0.1.72/sciveo/media/tools → sciveo-0.1.74/sciveo/media/pipelines/web}/__init__.py +0 -0
  102. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/pipelines/web/server.py +0 -0
  103. {sciveo-0.1.72/sciveo/ml → sciveo-0.1.74/sciveo/media/tools}/__init__.py +0 -0
  104. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/media/tools/video_interactive.py +0 -0
  105. {sciveo-0.1.72/sciveo/ml/dataset → sciveo-0.1.74/sciveo/ml}/__init__.py +0 -0
  106. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/base.py +0 -0
  107. {sciveo-0.1.72/sciveo/ml/evaluation → sciveo-0.1.74/sciveo/ml/dataset}/__init__.py +0 -0
  108. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/dataset/object_detection.py +0 -0
  109. {sciveo-0.1.72/sciveo/ml/images → sciveo-0.1.74/sciveo/ml/evaluation}/__init__.py +0 -0
  110. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/evaluation/markdown.py +0 -0
  111. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/evaluation/object_detection.py +0 -0
  112. {sciveo-0.1.72/sciveo/ml/nlp → sciveo-0.1.74/sciveo/ml/images}/__init__.py +0 -0
  113. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/base.py +0 -0
  114. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/description.py +0 -0
  115. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/embeddings.py +0 -0
  116. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/object_detection.py +0 -0
  117. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/tools.py +0 -0
  118. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/images/transformers.py +0 -0
  119. {sciveo-0.1.72/sciveo/ml/nlp/tokenizers → sciveo-0.1.74/sciveo/ml/nlp}/__init__.py +0 -0
  120. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/nlp/embeddings.py +0 -0
  121. {sciveo-0.1.72/sciveo/ml/video → sciveo-0.1.74/sciveo/ml/nlp/tokenizers}/__init__.py +0 -0
  122. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/nlp/tokenizers/bpe.py +0 -0
  123. {sciveo-0.1.72/sciveo/monitoring → sciveo-0.1.74/sciveo/ml/video}/__init__.py +0 -0
  124. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/ml/video/description.py +0 -0
  125. {sciveo-0.1.72/sciveo/monitoring/watchdog → sciveo-0.1.74/sciveo/monitoring}/__init__.py +0 -0
  126. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/monitoring/monitor.py +0 -0
  127. {sciveo-0.1.72/sciveo/network → sciveo-0.1.74/sciveo/monitoring/power}/__init__.py +0 -0
  128. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/monitoring/start.py +0 -0
  129. {sciveo-0.1.72/sciveo/tools → sciveo-0.1.74/sciveo/monitoring/watchdog}/__init__.py +0 -0
  130. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/monitoring/watchdog/base.py +0 -0
  131. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/monitoring/watchdog/process.py +0 -0
  132. {sciveo-0.1.72/sciveo/tools/aws → sciveo-0.1.74/sciveo/network}/__init__.py +0 -0
  133. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/network/camera.py +0 -0
  134. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/network/sniffer.py +0 -0
  135. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/network/tools.py +0 -0
  136. {sciveo-0.1.72/sciveo/tools/draw → sciveo-0.1.74/sciveo/tools}/__init__.py +0 -0
  137. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/array.py +0 -0
  138. {sciveo-0.1.72/sciveo/web → sciveo-0.1.74/sciveo/tools/aws}/__init__.py +0 -0
  139. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/aws/priority_queue.py +0 -0
  140. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/aws/s3.py +0 -0
  141. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/common.py +0 -0
  142. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/complexity.py +0 -0
  143. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/compress.py +0 -0
  144. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/configuration.py +0 -0
  145. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/crypto.py +0 -0
  146. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/daemon.py +0 -0
  147. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/draw/contours.py +0 -0
  148. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/formating.py +0 -0
  149. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/hardware.py +0 -0
  150. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/http.py +0 -0
  151. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/logger.py +0 -0
  152. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/os.py +0 -0
  153. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/queue.py +0 -0
  154. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/random.py +0 -0
  155. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/remote.py +0 -0
  156. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/simple_counter.py +0 -0
  157. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/synchronized.py +0 -0
  158. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/timers.py +0 -0
  159. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/tools/totp.py +0 -0
  160. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo/web/common.py +0 -0
  161. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/dependency_links.txt +0 -0
  162. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/entry_points.txt +0 -0
  163. {sciveo-0.1.72 → sciveo-0.1.74}/sciveo.egg-info/top_level.txt +0 -0
  164. {sciveo-0.1.72 → sciveo-0.1.74}/setup.cfg +0 -0
  165. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_complexity.py +0 -0
  166. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_compress.py +0 -0
  167. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_configuration.py +0 -0
  168. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_crypto.py +0 -0
  169. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_eval_markdown.py +0 -0
  170. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_ml_datasets.py +0 -0
  171. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_monitoring.py +0 -0
  172. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_runner.py +0 -0
  173. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_sampling.py +0 -0
  174. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_tokenizers.py +0 -0
  175. {sciveo-0.1.72 → sciveo-0.1.74}/test/test_totp.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: sciveo
3
- Version: 0.1.72
3
+ Version: 0.1.74
4
4
  Description-Content-Type: text/markdown
5
5
  Provides-Extra: mon
6
6
  Provides-Extra: net
@@ -8,6 +8,8 @@ Provides-Extra: server
8
8
  Provides-Extra: media
9
9
  Provides-Extra: media-ml
10
10
  Provides-Extra: web
11
+ Provides-Extra: db
12
+ Provides-Extra: power
11
13
  Provides-Extra: all
12
14
  Provides-Extra: ml
13
15
 
@@ -29,7 +29,7 @@ def main():
29
29
  choices=[
30
30
  'init', 'monitor', 'scan', 'nvr', 'predictors-server',
31
31
  'media-server', 'media-run',
32
- 'watchdog'
32
+ 'watchdog',
33
33
  ],
34
34
  help='Command to execute')
35
35
 
@@ -54,12 +54,20 @@ def main():
54
54
  parser.add_argument('--threshold', type=float, default=None, help='Threshold')
55
55
  parser.add_argument('--execute', type=str, default=None, help='Execute command')
56
56
  parser.add_argument('--pid', type=int, default=None, help='Process PID')
57
+ parser.add_argument('--serial', type=str, default=None, help='Serial Name')
57
58
 
58
59
  args = parser.parse_args()
59
60
 
60
61
  if args.command == 'monitor':
61
- from sciveo.monitoring.start import MonitorStart
62
- MonitorStart(period=args.period, block=args.block, output_path=args.output_path)()
62
+ if args.src is None:
63
+ from sciveo.monitoring.start import MonitorStart
64
+ MonitorStart(period=args.period, block=args.block, output_path=args.output_path)()
65
+ elif args.src.startswith("power"):
66
+ from sciveo.monitoring.power.ems300 import PowerEMS300
67
+ mon = PowerEMS300(serial=args.serial, host=args.host, port=args.port, period=args.period, output_path=args.output_path)
68
+ mon.start()
69
+ while(True):
70
+ time.sleep(3600)
63
71
  elif args.command == 'scan':
64
72
  from sciveo.network.tools import NetworkTools
65
73
  host=args.host
@@ -0,0 +1,204 @@
1
+ #
2
+ # Pavlin Georgiev, Softel Labs
3
+ #
4
+ # This is a proprietary file and may not be copied,
5
+ # distributed, or modified without express permission
6
+ # from the owner. For licensing inquiries, please
7
+ # contact pavlin@softel.bg.
8
+ #
9
+ # 2025
10
+ #
11
+
12
+ import os
13
+ import json
14
+ import psycopg2
15
+ import numpy as np
16
+ import pandas as pd
17
+ from sciveo.tools.logger import *
18
+
19
+
20
+ class BaseTable:
21
+ def __init__(self, table_name, config=None, batch_size=10_000, save_path=None, id_col="id"):
22
+ self.table_name = table_name
23
+ self.batch_size = batch_size
24
+ self.save_path = save_path
25
+ self.id_col = id_col
26
+ self.last_id = None
27
+
28
+ if config is None:
29
+ self.config = {
30
+ 'dbname': os.environ.get('DB_NAME'),
31
+ 'user': os.environ.get('DB_USERNAME'),
32
+ 'password': os.environ.get('DB_PASSWORD'),
33
+ 'host': os.environ.get('DB_HOST', 'localhost'),
34
+ 'port': int(os.environ.get('DB_PORT', 5432)),
35
+ }
36
+ else:
37
+ self.config = config
38
+
39
+ self.conn = psycopg2.connect(**self.config)
40
+ self.cursor = self.conn.cursor()
41
+ self.df = pd.DataFrame()
42
+
43
+ def load_file(self, file_path=None):
44
+ if not os.path.exists(file_path):
45
+ warning(f"File not found: {file_path}")
46
+ self.latest_df = pd.DataFrame()
47
+ return self.latest_df
48
+
49
+ if file_path.endswith(".parquet"):
50
+ self.latest_df = pd.read_parquet(file_path)
51
+ else:
52
+ self.latest_df = pd.read_csv(file_path)
53
+ info(f"Loaded {len(self.latest_df)} records from {file_path}")
54
+ return self.latest_df
55
+
56
+ def load(self, base_path=None):
57
+ if base_path is None and self.save_path is not None:
58
+ base_path = self.save_path
59
+
60
+ if base_path is None:
61
+ self.df = pd.DataFrame()
62
+ return self.df
63
+
64
+ files = [os.path.join(base_path, f) for f in os.listdir(base_path) if f.startswith(self.table_name) and f.endswith(".parquet")]
65
+
66
+ if not files:
67
+ info(f"There are no files in {base_path} to read")
68
+ self.df = pd.DataFrame()
69
+ return self.df
70
+
71
+ dfs = []
72
+ for file_path in sorted(files):
73
+ try:
74
+ df_part = self.load_file(file_path)
75
+ from_id = int(df_part[self.id_col].min())
76
+ to_id = int(df_part[self.id_col].max())
77
+ dfs.append(df_part)
78
+ debug(f"Loaded {len(df_part)} records from {file_path} id: [{from_id} - {to_id}]")
79
+ except Exception as e:
80
+ warning(f"Failed to load {file_path}: {e}")
81
+
82
+ if dfs:
83
+ self.df = pd.concat(dfs, ignore_index=True)
84
+ else:
85
+ self.df = pd.DataFrame()
86
+
87
+ self.last_id = int(self.df[self.id_col].max()) if not self.df.empty else None
88
+
89
+ info(f"Total loaded records: {len(self.df)} last_id: {self.last_id}")
90
+ return self.df
91
+
92
+ def _sanitize_df(self, df):
93
+ PANDAS_MIN_YEAR = 1677
94
+ PANDAS_MAX_YEAR = 2262
95
+ datetime_cols = []
96
+
97
+ # datetime cleanup
98
+ for col in df.columns:
99
+ if pd.api.types.is_datetime64_any_dtype(df[col]) or 'date' in col.lower() or 'time' in col.lower():
100
+ datetime_cols.append(col)
101
+
102
+ for col in datetime_cols:
103
+ def safe_dt(x):
104
+ if pd.isna(x):
105
+ return pd.NaT
106
+ if isinstance(x, str):
107
+ return pd.to_datetime(x, errors='coerce')
108
+ if hasattr(x, 'year'):
109
+ year = x.year
110
+ else:
111
+ return pd.NaT
112
+ if PANDAS_MIN_YEAR <= year <= PANDAS_MAX_YEAR:
113
+ return pd.Timestamp(x)
114
+ return pd.NaT
115
+ df[col] = df[col].apply(safe_dt)
116
+
117
+ # drop rows with invalid datetime
118
+ df = df.dropna(subset=datetime_cols)
119
+
120
+ # object columns: convert dict/list to JSON string
121
+ for col in df.columns:
122
+ if df[col].dtype == object:
123
+ df[col] = df[col].apply(lambda x: json.dumps(x) if isinstance(x, (dict, list)) else str(x) if x is not None else None)
124
+
125
+ df = df.reset_index(drop=True)
126
+ return df
127
+
128
+ def fetch_next_batch(self, last_id=None):
129
+ query = f"SELECT * FROM {self.table_name}"
130
+ if last_id is not None:
131
+ query += f" WHERE id > {last_id}"
132
+ query += f" ORDER BY id ASC LIMIT {self.batch_size};"
133
+
134
+ self.cursor.execute(query)
135
+ rows = self.cursor.fetchall()
136
+ if not rows:
137
+ return pd.DataFrame()
138
+
139
+ colnames = [desc[0] for desc in self.cursor.description]
140
+ df_new = pd.DataFrame(rows, columns=colnames)
141
+ return self._sanitize_df(df_new)
142
+
143
+ def append(self, df_new):
144
+ if not df_new.empty:
145
+ self.df = pd.concat([self.df, df_new], ignore_index=True)
146
+ debug(f"Added {len(df_new)} new rows (total {len(self.df)})")
147
+ self.last_id = int(self.df[self.id_col].max()) if not self.df.empty else None
148
+ debug(f"last {self.id_col} [{self.last_id}]")
149
+
150
+ def sync_incremental(self, last_id=None):
151
+ if last_id is None:
152
+ last_id = int(self.df[self.id_col].max()) if not self.df.empty else None
153
+ debug("reading from", last_id)
154
+ df_new = self.fetch_next_batch(last_id)
155
+ self.append(df_new)
156
+ if df_new.empty:
157
+ info("No new rows found")
158
+ return df_new
159
+
160
+ def save(self, file_path=None):
161
+ if self.save_path is not None and self.last_id is not None:
162
+ from_id = int(self.latest_df[self.id_col].min())
163
+ to_id = int(self.latest_df[self.id_col].max())
164
+ file_path = os.path.join(self.save_path, f"{self.table_name}--{from_id}-{to_id}.parquet")
165
+
166
+ if file_path.endswith(".parquet"):
167
+ self.latest_df.to_parquet(file_path, index=False)
168
+ else:
169
+ self.latest_df.to_csv(file_path, index=False)
170
+ info(f"Saved {len(self.latest_df)} rows to {file_path}")
171
+
172
+ def update(self, last_id=None):
173
+ if self.df.empty:
174
+ self.load()
175
+ self.latest_df = self.sync_incremental(last_id=last_id)
176
+ self.save()
177
+ return self.latest_df
178
+
179
+ def close(self):
180
+ self.cursor.close()
181
+ self.conn.close()
182
+
183
+ def __enter__(self):
184
+ return self
185
+
186
+ def __exit__(self, exc_type, exc_val, exc_tb):
187
+ self.close()
188
+
189
+
190
+ if __name__ == "__main__":
191
+ with BaseTable("video_record_predictions", batch_size=10_000, save_path="/home/ml/video_predictions/data") as T:
192
+
193
+ T.update(last_id=1_000_000)
194
+ T.load()
195
+ if not T.df.empty:
196
+ debug(T.df.columns)
197
+ debug(T.df[["key", "people", "is_valid", "updated_at", "data"]].head())
198
+
199
+ while(True):
200
+ df = T.update()
201
+ if df.empty:
202
+ info("Finished", T.df.shape)
203
+ break
204
+ info("read", df.shape, df[["key", "people"]].head())
@@ -0,0 +1,107 @@
1
+ #
2
+ # Stanislav Georgiev, Softel Labs
3
+ #
4
+ # This is a proprietary file and may not be copied,
5
+ # distributed, or modified without express permission
6
+ # from the owner. For licensing inquiries, please
7
+ # contact s.georgiev@softel.bg.
8
+ #
9
+ # 2025
10
+ #
11
+
12
+ import os
13
+ import json
14
+ import datetime
15
+ import time
16
+ from pymodbus.client import ModbusTcpClient
17
+ from sciveo.tools.logger import *
18
+ from sciveo.tools.daemon import DaemonBase
19
+ # from sciveo.api.base import APIRemoteClient
20
+ from sciveo.monitoring.power.tools import *
21
+
22
+
23
+ class PowerEMS300(DaemonBase):
24
+ def __init__(self, serial, host, port=502, device_id=247, delay=0.01, period=30, output_path=None):
25
+ super().__init__(period=period)
26
+ self.serial = serial
27
+ self.host = host
28
+ self.port = port
29
+ self.device_id = device_id
30
+ self.delay = delay
31
+ self.client = None
32
+
33
+ if output_path is not None and os.path.isdir(output_path):
34
+ self.output_path = os.path.join(output_path, f"{self.serial}.json")
35
+ else:
36
+ self.output_path = output_path
37
+
38
+ # self.api = APIRemoteClient()
39
+ self.client = ModbusTcpClient(host=self.host, port=self.port)
40
+
41
+ def connect(self):
42
+ if not self.client.connected:
43
+ if self.client.connect():
44
+ info(type(self.client).__name__, "connected", (self.host, self.port))
45
+ else:
46
+ error("Connect FAIL", (self.host, self.port))
47
+ return self.client.connected
48
+
49
+ def send(self, data):
50
+ api_result = self.api.POST_SCI("monitor", {"data": data})
51
+ debug(data, "api_result", api_result)
52
+
53
+ def output_write(self, data):
54
+ if os.path.isfile(self.output_path):
55
+ with open(self.output_path, "rb+") as fp:
56
+ fp.seek(-2, 2)
57
+ fp.truncate()
58
+ with open(self.output_path, "a") as fp:
59
+ fp.write(f", {json.dumps(data)}]\n")
60
+ else:
61
+ with open(self.output_path, "w") as fp:
62
+ fp.write(json.dumps([data]) + "\n")
63
+
64
+ def save(self, data):
65
+ try:
66
+ if self.output_path is not None:
67
+ info("save", self.output_path, data)
68
+ self.output_write(data)
69
+ except Exception as e:
70
+ error(e, "writing failed for", self.output_path)
71
+
72
+ def loop(self):
73
+ if not self.connect():
74
+ warning("Not connected", (self.host, self.port))
75
+ return
76
+
77
+ try:
78
+ data = {
79
+ "local_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
80
+ "serial": self.serial,
81
+ }
82
+
83
+ current_info = [8026, 8044, 8060, 8776, 8778, 10101, 10103, 10105, 10713, 10715, 10716, 10945]
84
+ for addr in current_info:
85
+ result = read_input_registers(self.client, EMS300_REG_MAP, addr, self.device_id)
86
+ if result is not None:
87
+ value, name, dtype = result
88
+ debug(f"{name}: {value}")
89
+ data[name] = value
90
+ time.sleep(self.delay)
91
+
92
+ # self.send(data)
93
+ self.save(data)
94
+ except Exception as e:
95
+ exception(e)
96
+
97
+ def close(self):
98
+ self.client.close()
99
+
100
+
101
+ if __name__ == "__main__":
102
+
103
+ mon = PowerEMS300(serial="EMS300-1", host="192.168.86.184", port=502, period=30, output_path="ems300.json")
104
+ mon.start()
105
+
106
+ while(True):
107
+ time.sleep(30)
@@ -0,0 +1,71 @@
1
+ #
2
+ # Stanislav Georgiev, Softel Labs
3
+ #
4
+ # This is a proprietary file and may not be copied,
5
+ # distributed, or modified without express permission
6
+ # from the owner. For licensing inquiries, please
7
+ # contact s.georgiev@softel.bg.
8
+ #
9
+ # 2025
10
+ #
11
+
12
+ import time
13
+ import threading
14
+ import time
15
+ from pymodbus.server import StartTcpServer
16
+ from pymodbus.datastore import ModbusServerContext, ModbusSparseDataBlock
17
+ from threading import Thread
18
+ from sciveo.tools.logger import *
19
+ from sciveo.tools.daemon import DaemonBase
20
+
21
+
22
+ # Example read-only registers
23
+ # INITIAL_REGISTERS = {
24
+ # 8044: 12500, # Plant Active Power
25
+ # 8060: 8200, # PV Active Power
26
+ # 8038: -1500, # Storage Power
27
+ # 8048: 600, # Reactive Power
28
+ # 9082: 3000, # Dynamic Allowable Charge Power
29
+ # 9084: 3500, # Dynamic Allowable Discharge Power
30
+ # }
31
+ INITIAL_REGISTERS = {
32
+ 8060: 8200, # PV Active Power
33
+ }
34
+
35
+ class SimulatorEMS300(DaemonBase):
36
+ def __init__(self, host="127.0.0.1", port=5020, period=1):
37
+ super().__init__(num_threads=1, period=period)
38
+ self.host = host
39
+ self.port = port
40
+
41
+ # Only input registers
42
+ self.ir_block = ModbusSparseDataBlock(INITIAL_REGISTERS.copy())
43
+
44
+ self.context = ModbusServerContext(
45
+ { 247: { # unit_id -> datastore dict
46
+ 'di': ModbusSparseDataBlock({}), # discrete inputs
47
+ 'co': ModbusSparseDataBlock({}), # coils
48
+ 'hr': ModbusSparseDataBlock({}), # holding registers
49
+ 'ir': self.ir_block # input registers
50
+ }
51
+ },
52
+ single=False # multiple units not used here, keep False
53
+ )
54
+
55
+ def loop(self):
56
+ # Slowly vary PV Active Power
57
+ pv = self.ir_block.getValues(8060, count=1)[0]
58
+ pv = (pv + 50) % 15000
59
+ self.ir_block.setValues(8060, [pv])
60
+ info(f"Simulated PV Active Power: {pv}")
61
+
62
+ def start_server(self):
63
+ StartTcpServer(self.context, address=(self.host, self.port))
64
+
65
+
66
+ if __name__ == "__main__":
67
+ sim = SimulatorEMS300(host="127.0.0.1", port=1502)
68
+ sim.start()
69
+ sim.start_server()
70
+ while True:
71
+ time.sleep(10)