opensampl 1.2.0__tar.gz → 1.2.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 (99) hide show
  1. {opensampl-1.2.0 → opensampl-1.2.2}/PKG-INFO +5 -5
  2. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/db/orm.py +4 -1
  3. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/load_data.py +19 -9
  4. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/metrics.py +4 -0
  5. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-dashboards/ntp_dash.json +1 -1
  6. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-dashboards/public-timing-dashboard.json +4 -4
  7. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-dashboards/public_twst_dash.json +6 -6
  8. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-dashboards/timing-dashboard2.json +4 -4
  9. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-dashboards/twst_dash.json +6 -6
  10. opensampl-1.2.2/opensampl/server/migrations/_migrations/versions/2026_09_11_1445_update_probe_data_types.py +56 -0
  11. {opensampl-1.2.0 → opensampl-1.2.2}/pyproject.toml +5 -5
  12. {opensampl-1.2.0 → opensampl-1.2.2}/.gitignore +0 -0
  13. {opensampl-1.2.0 → opensampl-1.2.2}/LICENSE +0 -0
  14. {opensampl-1.2.0 → opensampl-1.2.2}/README.md +0 -0
  15. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/__init__.py +0 -0
  16. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/cli.py +0 -0
  17. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/__init__.py +0 -0
  18. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/cli.py +0 -0
  19. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/__init__.py +0 -0
  20. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/tp4100/__init__.py +0 -0
  21. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/tp4100/collect_4100.py +0 -0
  22. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/twst/__init__.py +0 -0
  23. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/twst/context.py +0 -0
  24. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/twst/generate_twst_files.py +0 -0
  25. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/microchip/twst/readings.py +0 -0
  26. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/collect/modem.py +0 -0
  27. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/config/__init__.py +0 -0
  28. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/config/base.py +0 -0
  29. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/config/server.py +0 -0
  30. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/config/tp4100.py +0 -0
  31. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/__init__.py +0 -0
  32. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/create_vendor.py +0 -0
  33. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/insert_markers.py +0 -0
  34. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/collect_mixin_template.txt +0 -0
  35. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/compound_reference_template.txt +0 -0
  36. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/metric_template.txt +0 -0
  37. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/orm_metadata.txt +0 -0
  38. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/parser_template.txt +0 -0
  39. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/reference_template.txt +0 -0
  40. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/create/templates/vendor_template.txt +0 -0
  41. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/db/__init__.py +0 -0
  42. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/db/access_orm.py +0 -0
  43. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/helpers/__init__.py +0 -0
  44. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/helpers/geolocator.py +0 -0
  45. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/load/__init__.py +0 -0
  46. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/load/data.py +0 -0
  47. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/load/routing.py +0 -0
  48. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/load/table_factory.py +0 -0
  49. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/mixins/__init__.py +0 -0
  50. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/mixins/collect.py +0 -0
  51. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/mixins/random_data.py +0 -0
  52. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/references.py +0 -0
  53. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/__init__.py +0 -0
  54. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/backend/Dockerfile +0 -0
  55. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/backend/__init__.py +0 -0
  56. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/backend/main.py +0 -0
  57. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/cli.py +0 -0
  58. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/cli2.py +0 -0
  59. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/default.env +0 -0
  60. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/docker-compose.dev.yaml +0 -0
  61. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/docker-compose.yaml +0 -0
  62. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/Dockerfile +0 -0
  63. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-provisioning/dashboards/dashboard.yaml +0 -0
  64. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana-provisioning/datasources/postgresql.yaml +0 -0
  65. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/grafana/grafana.env +0 -0
  66. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/Dockerfile +0 -0
  67. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/README +0 -0
  68. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/env.py +0 -0
  69. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/script.py.mako +0 -0
  70. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2024_03_26_1145_create_schema_initialize_orm.py +0 -0
  71. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2024_12_04_1155_update_db_tables.py +0 -0
  72. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_01_28_2212_create_time_buckets.py +0 -0
  73. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_01_29_0909_updating_location_and_test_tables.py +0 -0
  74. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_03_05_0958_add_grafana_user_access.py +0 -0
  75. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_03_26_0743_create_campus_view.py +0 -0
  76. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_04_14_1231_update_retention_policy.py +0 -0
  77. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_04_22_1531_add_access_tokens.py +0 -0
  78. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_04_22_1650_turn_off_matviews.py +0 -0
  79. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1223_add_column_comments.py +0 -0
  80. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1235_create_reference_and_metric_tables.py +0 -0
  81. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1254_update_probe_data_to_take_reference_and_.py +0 -0
  82. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1318_adding_freeform_metadata_to_adva.py +0 -0
  83. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1358_setting_default_reference_and_metric.py +0 -0
  84. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_03_1539_making_default_trigger_functions.py +0 -0
  85. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_23_0825_data_filtering_functions.py +0 -0
  86. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_06_23_1654_making_microsemi_table.py +0 -0
  87. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_08_15_0840_create_microchip_tp400_metadata.py +0 -0
  88. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2025_09_22_0915_campus_view_not_forced.py +0 -0
  89. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2026_04_17_1243_add_ntp_values.py +0 -0
  90. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/_migrations/versions/2026_04_17_1254_add_reference_view.py +0 -0
  91. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/server/migrations/alembic.ini +0 -0
  92. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/__init__.py +0 -0
  93. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/adva.py +0 -0
  94. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/base_probe.py +0 -0
  95. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/constants.py +0 -0
  96. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/microchip/__init__.py +0 -0
  97. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/microchip/tp4100.py +0 -0
  98. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/microchip/twst.py +0 -0
  99. {opensampl-1.2.0 → opensampl-1.2.2}/opensampl/vendors/ntp.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: opensampl
3
- Version: 1.2.0
3
+ Version: 1.2.2
4
4
  Summary: Python tools for adding clock data to a timescale db.
5
5
  Project-URL: Homepage, https://github.com/ORNL/OpenSAMPL
6
6
  Project-URL: Repository, https://github.com/ORNL/OpenSAMPL
@@ -70,11 +70,11 @@ Requires-Dist: psycopg2-binary<3,>=2.9.0
70
70
  Requires-Dist: pydanclick
71
71
  Requires-Dist: pydantic-settings>=2.9.0
72
72
  Requires-Dist: pydantic<3,>=2.10.3
73
- Requires-Dist: python-dotenv
74
- Requires-Dist: python-multipart<0.0.27,>=0.0.26
73
+ Requires-Dist: python-dotenv<2,>=1.1.1
74
+ Requires-Dist: python-multipart<0.1,>=0.0.27
75
75
  Requires-Dist: pytz~=2024.1
76
76
  Requires-Dist: pyyaml<7,>=6.0.0
77
- Requires-Dist: requests<3,>=2.31.0
77
+ Requires-Dist: requests<3,>=2.32.4
78
78
  Requires-Dist: sqlalchemy<3,>=2.0.39
79
79
  Requires-Dist: tabulate
80
80
  Requires-Dist: tqdm<5,>=4.66.2
@@ -280,7 +280,10 @@ class ProbeData(Base):
280
280
  primary_key=True,
281
281
  comment="Foreign key to the metric type being measured",
282
282
  )
283
- value = Column(JSONB, comment="Measurement value stored as JSON; value's expected type defined via metric")
283
+ value_float = Column(Float, nullable=True, comment="Float type value; value's expected type defined via metric")
284
+ value_jsonb = Column(
285
+ JSONB, nullable=True, comment="Measurement value stored as JSON; value's expected type defined via metric"
286
+ )
284
287
 
285
288
 
286
289
  class MetricType(Base):
@@ -138,18 +138,28 @@ def load_time_data(
138
138
  df["probe_uuid"] = data_definition.probe.uuid # ty: ignore[possibly-unbound-attribute]
139
139
  df["reference_uuid"] = data_definition.reference.uuid # ty: ignore[possibly-unbound-attribute]
140
140
  df["metric_type_uuid"] = data_definition.metric.uuid # ty: ignore[possibly-unbound-attribute]
141
- logger.debug(df.head())
142
- # Ensure correct dtypes
141
+
142
+ # Ensure correct time dtypes
143
143
  df["time"] = pd.to_datetime(df["time"], format="mixed", utc=True, errors="raise")
144
- df["value"] = df["value"].apply(json.dumps)
144
+
145
+ if data_definition.metric.is_numeric():
146
+ df["value_float"] = pd.to_numeric(df["value"], errors="raise")
147
+ df["value_jsonb"] = None
148
+ else:
149
+ df["value_float"] = None
150
+ df["value_jsonb"] = df["value"].apply(json.dumps)
151
+
152
+ df = df.drop(columns=["value"]) # Drop original value column, as we now have value_float and value_jsonb
153
+ logger.debug(df.head())
154
+
145
155
  records = df.to_dict(orient="records")
146
156
  insert_stmt = text(f"""
147
- INSERT INTO {ProbeData.__table__.schema}.{ProbeData.__tablename__}
148
- (time, probe_uuid, reference_uuid, metric_type_uuid, value)
149
- VALUES (:time, :probe_uuid, :reference_uuid, :metric_type_uuid, :value)
150
- ON CONFLICT (time, probe_uuid, reference_uuid, metric_type_uuid)
151
- DO NOTHING
152
- """) # noqa: S608
157
+ INSERT INTO {ProbeData.__table__.schema}.{ProbeData.__tablename__}
158
+ (time, probe_uuid, reference_uuid, metric_type_uuid, value_float, value_jsonb)
159
+ VALUES (:time, :probe_uuid, :reference_uuid, :metric_type_uuid, :value_float, :value_jsonb)
160
+ ON CONFLICT (time, probe_uuid, reference_uuid, metric_type_uuid)
161
+ DO NOTHING
162
+ """) # noqa: S608
153
163
 
154
164
  try:
155
165
  result = session.execute(insert_stmt, records)
@@ -21,6 +21,10 @@ class MetricType(BaseModel):
21
21
  """Convert a given value to the expected type for the Metric"""
22
22
  return self.value_type(value)
23
23
 
24
+ def is_numeric(self) -> bool:
25
+ """Return True if the metric's value_type is numeric (int or float)"""
26
+ return self.value_type in [int, float]
27
+
24
28
  @field_serializer("value_type")
25
29
  def serialize_type(self, value: type):
26
30
  """Return the name of value_type for serializing"""
@@ -1313,7 +1313,7 @@
1313
1313
  "editorMode": "code",
1314
1314
  "format": "table",
1315
1315
  "rawQuery": true,
1316
- "rawSql": "WITH probe_ref AS (\n SELECT\n uuid,\n COALESCE(pm.name, CONCAT(pm.ip_address, ' ', pm.probe_id)) AS probe_name\n FROM castdb.probe_metadata pm\n)\nSELECT\n time_bucket('1 minute'::interval, pd.time AT TIME ZONE 'UTC') AS time,\n pd.probe_uuid,\n pr.probe_name,\n pd.reference_uuid,\n AVG(pd.value::float * 1e9) FILTER (WHERE lower(m.name) = 'phase offset') AS phase_offset,\n AVG(pd.value::float * 1e9) FILTER (WHERE lower(m.name) = 'jitter') AS jitter,\n AVG((pd.value)::float) FILTER (WHERE lower(m.name) = 'stratum') AS stratum,\n AVG((pd.value)::float) FILTER (WHERE lower(m.name) = 'sync health') AS sync_health\nFROM castdb.probe_data pd\nJOIN probe_ref pr\n ON pd.probe_uuid = pr.uuid\nJOIN castdb.metric_type m\n ON pd.metric_type_uuid = m.uuid\nWHERE pd.probe_uuid = ANY(ARRAY[${ntp_probe:sqlstring}]::text[]) AND $__timeFilter(pd.time)\nGROUP BY 1, 2, 3, 4\nORDER BY\n 1, 3;",
1316
+ "rawSql": "WITH probe_ref AS (\n SELECT\n uuid,\n COALESCE(pm.name, CONCAT(pm.ip_address, ' ', pm.probe_id)) AS probe_name\n FROM castdb.probe_metadata pm\n)\nSELECT\n time_bucket('1 minute'::interval, pd.time AT TIME ZONE 'UTC') AS time,\n pd.probe_uuid,\n pr.probe_name,\n pd.reference_uuid,\n AVG(pd.value_float * 1e9) FILTER (WHERE lower(m.name) = 'phase offset') AS phase_offset,\n AVG(pd.value_float * 1e9) FILTER (WHERE lower(m.name) = 'jitter') AS jitter,\n AVG((pd.value)::float) FILTER (WHERE lower(m.name) = 'stratum') AS stratum,\n AVG((pd.value)::float) FILTER (WHERE lower(m.name) = 'sync health') AS sync_health\nFROM castdb.probe_data pd\nJOIN probe_ref pr\n ON pd.probe_uuid = pr.uuid\nJOIN castdb.metric_type m\n ON pd.metric_type_uuid = m.uuid\nWHERE pd.probe_uuid = ANY(ARRAY[${ntp_probe:sqlstring}]::text[]) AND $__timeFilter(pd.time)\nGROUP BY 1, 2, 3, 4\nORDER BY\n 1, 3;",
1317
1317
  "refId": "A",
1318
1318
  "sql": {
1319
1319
  "columns": [
@@ -650,7 +650,7 @@
650
650
  "editorMode": "code",
651
651
  "format": "time_series",
652
652
  "rawQuery": true,
653
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, concat(pm.ip_address, ' Interface ', pm.probe_id)),\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM castdb.probe_data pd JOIN castdb.probe_metadata pm ON pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pm.vendor IN ('ADVA', 'MicrochipTP4100', 'NTP')\n AND coalesce(pm.public, true)\n AND (trim('${clock_name:csv}') = '' OR pd.probe_uuid = ANY(string_to_array(trim('${clock_name:csv}'), ',')))\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
653
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, concat(pm.ip_address, ' Interface ', pm.probe_id)),\n AVG(pd.value_float) * 1e9 AS value\nFROM castdb.probe_data pd JOIN castdb.probe_metadata pm ON pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pm.vendor IN ('ADVA', 'MicrochipTP4100', 'NTP')\n AND coalesce(pm.public, true)\n AND (trim('${clock_name:csv}') = '' OR pd.probe_uuid = ANY(string_to_array(trim('${clock_name:csv}'), ',')))\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
654
654
  "refId": "A",
655
655
  "sql": {
656
656
  "columns": [
@@ -776,7 +776,7 @@
776
776
  "editorMode": "code",
777
777
  "format": "time_series",
778
778
  "rawQuery": true,
779
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, CONCAT(pm.ip_address, ' Interface ', pm.probe_id)),\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM castdb.probe_data pd JOIN castdb.probe_metadata pm ON pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pm.vendor IN ('ADVA', 'MicrochipTP4100', 'NTP')\n AND coalesce(pm.public, true)\n AND (trim('${clock_name:csv}') = '' OR pd.probe_uuid = ANY(string_to_array(trim('${clock_name:csv}'), ',')))\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
779
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, CONCAT(pm.ip_address, ' Interface ', pm.probe_id)),\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM castdb.probe_data pd JOIN castdb.probe_metadata pm ON pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pm.vendor IN ('ADVA', 'MicrochipTP4100', 'NTP')\n AND coalesce(pm.public, true)\n AND (trim('${clock_name:csv}') = '' OR pd.probe_uuid = ANY(string_to_array(trim('${clock_name:csv}'), ',')))\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
780
780
  "refId": "A",
781
781
  "sql": {
782
782
  "columns": [
@@ -916,7 +916,7 @@
916
916
  "editorMode": "code",
917
917
  "format": "time_series",
918
918
  "rawQuery": true,
919
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
919
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
920
920
  "refId": "A",
921
921
  "sql": {
922
922
  "columns": [
@@ -1027,7 +1027,7 @@
1027
1027
  "editorMode": "code",
1028
1028
  "format": "time_series",
1029
1029
  "rawQuery": true,
1030
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
1030
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
1031
1031
  "refId": "A",
1032
1032
  "sql": {
1033
1033
  "columns": [
@@ -493,7 +493,7 @@
493
493
  "format": "table",
494
494
  "hide": false,
495
495
  "rawQuery": true,
496
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, pm.probe_id) AS channel,\n AVG(pd.value::FLOAT) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\nJOIN \n castdb.reference r ON pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nWHERE \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.name,\n pm.probe_id\nORDER BY \n time\n",
496
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, pm.probe_id) AS channel,\n AVG(pd.value_float) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\nJOIN \n castdb.reference r ON pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nWHERE \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.name,\n pm.probe_id\nORDER BY \n time\n",
497
497
  "refId": "B",
498
498
  "sql": {
499
499
  "columns": [
@@ -628,7 +628,7 @@
628
628
  "format": "table",
629
629
  "hide": false,
630
630
  "rawQuery": true,
631
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
631
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n AVG(pd.value_float) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
632
632
  "refId": "B",
633
633
  "sql": {
634
634
  "columns": [
@@ -763,7 +763,7 @@
763
763
  "format": "table",
764
764
  "hide": false,
765
765
  "rawQuery": true,
766
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
766
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
767
767
  "refId": "B",
768
768
  "sql": {
769
769
  "columns": [
@@ -1246,7 +1246,7 @@
1246
1246
  "format": "table",
1247
1247
  "hide": false,
1248
1248
  "rawQuery": true,
1249
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1249
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1250
1250
  "refId": "B",
1251
1251
  "sql": {
1252
1252
  "columns": [
@@ -1367,7 +1367,7 @@
1367
1367
  "format": "table",
1368
1368
  "hide": false,
1369
1369
  "rawQuery": true,
1370
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1370
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1371
1371
  "refId": "B",
1372
1372
  "sql": {
1373
1373
  "columns": [
@@ -1488,7 +1488,7 @@
1488
1488
  "format": "table",
1489
1489
  "hide": false,
1490
1490
  "rawQuery": true,
1491
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1491
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1492
1492
  "refId": "B",
1493
1493
  "sql": {
1494
1494
  "columns": [
@@ -653,7 +653,7 @@
653
653
  "editorMode": "code",
654
654
  "format": "time_series",
655
655
  "rawQuery": true,
656
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, concat(pm.ip_address, ' Interface ', pm.probe_id)),\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM castdb.probe_data pd join castdb.probe_metadata pm on pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid IN (${clock_name:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
656
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, concat(pm.ip_address, ' Interface ', pm.probe_id)),\n AVG(pd.value_float) * 1e9 AS value\nFROM castdb.probe_data pd join castdb.probe_metadata pm on pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid IN (${clock_name:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
657
657
  "refId": "A",
658
658
  "sql": {
659
659
  "columns": [
@@ -778,7 +778,7 @@
778
778
  "editorMode": "code",
779
779
  "format": "time_series",
780
780
  "rawQuery": true,
781
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(name, CONCAT(ip_address, ' Interface ', probe_id)),\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM castdb.probe_data pd join castdb.probe_metadata pm on pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid in (${clock_name:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
781
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(name, CONCAT(ip_address, ' Interface ', probe_id)),\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM castdb.probe_data pd join castdb.probe_metadata pm on pd.probe_uuid = pm.uuid\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid in (${clock_name:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid,\n pm.name,\n pm.ip_address,\n pm.probe_id\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
782
782
  "refId": "A",
783
783
  "sql": {
784
784
  "columns": [
@@ -917,7 +917,7 @@
917
917
  "editorMode": "code",
918
918
  "format": "time_series",
919
919
  "rawQuery": true,
920
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
920
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
921
921
  "refId": "A",
922
922
  "sql": {
923
923
  "columns": [
@@ -1027,7 +1027,7 @@
1027
1027
  "editorMode": "code",
1028
1028
  "format": "time_series",
1029
1029
  "rawQuery": true,
1030
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
1030
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM castdb.probe_data pd\nWHERE\n $__timeFilter(pd.time)\n AND pd.probe_uuid = ${clock_name:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')\n",
1031
1031
  "refId": "A",
1032
1032
  "sql": {
1033
1033
  "columns": [
@@ -492,7 +492,7 @@
492
492
  "format": "table",
493
493
  "hide": false,
494
494
  "rawQuery": true,
495
- "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, pm.probe_id) AS channel,\n AVG(pd.value::FLOAT) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\nJOIN \n castdb.reference r ON pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nWHERE \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.name,\n pm.probe_id\nORDER BY \n time\n",
495
+ "rawSql": "SELECT \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n coalesce(pm.name, pm.probe_id) AS channel,\n AVG(pd.value_float) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\nJOIN \n castdb.reference r ON pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nWHERE \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.name,\n pm.probe_id\nORDER BY \n time\n",
496
496
  "refId": "B",
497
497
  "sql": {
498
498
  "columns": [
@@ -627,7 +627,7 @@
627
627
  "format": "table",
628
628
  "hide": false,
629
629
  "rawQuery": true,
630
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
630
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n AVG(pd.value_float) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
631
631
  "refId": "B",
632
632
  "sql": {
633
633
  "columns": [
@@ -762,7 +762,7 @@
762
762
  "format": "table",
763
763
  "hide": false,
764
764
  "rawQuery": true,
765
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
765
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n COALESCE(pm.name, pm.probe_id) as name,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nJOIN \n castdb.probe_metadata pm ON r.compound_reference_uuid = pm.uuid\nwhere \n $__timeFilter(pd.time)\n and r.compound_reference_uuid in (${compound_ref:sqlstring})\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pm.uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
766
766
  "refId": "B",
767
767
  "sql": {
768
768
  "columns": [
@@ -1247,7 +1247,7 @@
1247
1247
  "format": "table",
1248
1248
  "hide": false,
1249
1249
  "rawQuery": true,
1250
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1250
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${ebno_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1251
1251
  "refId": "B",
1252
1252
  "sql": {
1253
1253
  "columns": [
@@ -1368,7 +1368,7 @@
1368
1368
  "format": "table",
1369
1369
  "hide": false,
1370
1370
  "rawQuery": true,
1371
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value::FLOAT) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1371
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n AVG(pd.value_float) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1372
1372
  "refId": "B",
1373
1373
  "sql": {
1374
1374
  "columns": [
@@ -1489,7 +1489,7 @@
1489
1489
  "format": "table",
1490
1490
  "hide": false,
1491
1491
  "rawQuery": true,
1492
- "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value::FLOAT) - MIN(pd.value::FLOAT)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1492
+ "rawSql": "select \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC') AS time,\n (MAX(pd.value_float) - MIN(pd.value_float)) * 1e9 AS value\nFROM \n get_probe_data_by_probe_and_metric(${modem:sqlstring}, ${phase_offset_uuid:sqlstring}) pd\njoin castdb.reference r on pd.reference_uuid = r.uuid\nwhere \n $__timeFilter(pd.time)\n AND r.compound_reference_uuid = ${compound_ref:sqlstring}\nGROUP BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC'),\n pd.probe_uuid\nORDER BY \n time_bucket(${resolution:sqlstring}, pd.time AT TIME ZONE 'UTC')",
1493
1493
  "refId": "B",
1494
1494
  "sql": {
1495
1495
  "columns": [
@@ -0,0 +1,56 @@
1
+ """update probe_data types
2
+
3
+ Revision ID: b88042bae240
4
+ Revises: c95e49e551be
5
+ Create Date: 2026-09-11 14:45:53.382353
6
+
7
+ """
8
+ from typing import Sequence, Union
9
+
10
+ from alembic import op
11
+ import sqlalchemy as sa
12
+
13
+
14
+ # revision identifiers, used by Alembic.
15
+ revision: str = 'b88042bae240'
16
+ down_revision: Union[str, None] = 'c95e49e551be'
17
+ branch_labels: Union[str, Sequence[str], None] = None
18
+ depends_on: Union[str, Sequence[str], None] = None
19
+
20
+
21
+ SCHEMA = 'castdb'
22
+
23
+ def upgrade() -> None:
24
+ op.alter_column("probe_data",
25
+ "value",
26
+ new_column_name="value_jsonb",
27
+ nullable=True,
28
+ schema=SCHEMA)
29
+ op.add_column("probe_data",
30
+ sa.Column("value_float", sa.Float(), nullable=True),
31
+ schema=SCHEMA)
32
+
33
+ # Backfill value_float from the numeric jsonb values
34
+ op.execute(
35
+ """
36
+ UPDATE castdb.probe_data pd
37
+ SET value_float = (pd.value_jsonb #>> '{}')::double precision
38
+ FROM castdb.metric_type mt
39
+ WHERE pd.metric_type_uuid = mt.uuid
40
+ AND mt.value_type IN ('float'
41
+ , 'int')
42
+ """
43
+ )
44
+
45
+
46
+ def downgrade() -> None:
47
+ op.execute(
48
+ """
49
+ UPDATE castdb.probe_data
50
+ SET value_jsonb = to_jsonb(value_float)
51
+ WHERE value_float IS NOT NULL
52
+ """
53
+ )
54
+ op.drop_column("probe_data", "value_float", schema=SCHEMA)
55
+
56
+ op.alter_column("probe_data", "value_jsonb", nullable=False, new_column_name="value", schema=SCHEMA)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "opensampl"
3
- version = "1.2.0"
3
+ version = "1.2.2"
4
4
  description = "Python tools for adding clock data to a timescale db."
5
5
  license = {file = "LICENSE"}
6
6
  authors = [
@@ -49,13 +49,13 @@ dependencies = [
49
49
  "tqdm>=4.66.2,<5",
50
50
  "numpy>=1.26.4,<2",
51
51
  "pytz~=2024.1",
52
- "requests>=2.31.0,<3",
52
+ "requests>=2.32.4,<3",
53
53
  "pyyaml>=6.0.0,<7",
54
54
  "allantools",
55
55
  "loguru>=0.7.0,<0.8",
56
56
  "psycopg2-binary>=2.9.0,<3",
57
- "python-dotenv",
58
- "python-multipart>=0.0.26,<0.0.27",
57
+ "python-dotenv>=1.1.1,<2",
58
+ "python-multipart>=0.0.27,<0.1",
59
59
  "astor",
60
60
  "libcst",
61
61
  "jinja2>=3.1.6",
@@ -92,7 +92,7 @@ opensampl-collect = "opensampl.collect.cli:cli"
92
92
  [dependency-groups]
93
93
  dev = [
94
94
  "ty",
95
- "pytest",
95
+ "pytest>=8.4.0",
96
96
  "pytest-cov",
97
97
  "pytest-mock",
98
98
  "ruff",
File without changes
File without changes
File without changes
File without changes