feat: 完成 issue #23 ① 采集配置外置(点位/采样率/协议参数化,去硬编码)

This commit is contained in:
2026-08-04 23:44:04 +08:00
parent 50b51d4a27
commit ecb181a79e
5 changed files with 90 additions and 7 deletions
@@ -146,6 +146,52 @@ class EngineMetricsTest(unittest.TestCase):
self.assertLessEqual(metrics.p99_latency(), 0.6)
self.assertEqual(metrics.total_samples, 100)
def test_per_point_sample_rate_schedule(self):
"""点位级 sampleRate 调度(issue #23):低频点位按比例降频,去硬编码。"""
# interval_ms=1000:A 点 1s 采样、B 点 5s 采样、C 点 500ms(小于 tick,退化为每 tick)
pd = PointDict([
Point(device_id="CLF-01", point_id="CLF-01.A", name="A", unit="℃",
data_type="float", sample_rate=1000, quality_code=True, row_number=2),
Point(device_id="CLF-01", point_id="CLF-01.B", name="B", unit="℃",
data_type="float", sample_rate=5000, quality_code=True, row_number=3),
Point(device_id="CLF-01", point_id="CLF-01.C", name="C", unit="℃",
data_type="float", sample_rate=500, quality_code=True, row_number=4),
])
spool = SpoolStore(os.path.join(self._tmp, "spool"))
metrics = HealthMetrics()
engine = CollectorEngine(
point_dict=pd,
driver_slots=[("simulator", SimulatorDriver(), [])],
spool=spool,
metrics=metrics,
interval_ms=1000,
)
# 记录每个点位在 10 个 tick 内被读取的次数(读驱动时计数)
read_counts = {"CLF-01.A": 0, "CLF-01.B": 0, "CLF-01.C": 0}
original = SimulatorDriver.read_points
def counting_read(self, points):
for p in points:
read_counts[p.point_id] += 1
return original(self, points)
SimulatorDriver.read_points = counting_read
try:
for _ in range(10):
engine.collect_once()
finally:
SimulatorDriver.read_points = original
# A:1000ms / 1000ms tick → 每 tick 都读 = 10 次
self.assertEqual(read_counts["CLF-01.A"], 10)
# B:5000ms / 1000ms tick → 每 5 tick 读一次 ≈ 2 次(tick1、tick6)
self.assertEqual(read_counts["CLF-01.B"], 2)
# C:500ms < tick → 每 tick 读 = 10 次(不做高于 tick 频率的超采样)
self.assertEqual(read_counts["CLF-01.C"], 10)
# 调度推进:低频点位不再被硬编码为每 tick 读取
self.assertEqual(engine._ticks_per_sample(pd.points[0]), 1)
self.assertEqual(engine._ticks_per_sample(pd.points[1]), 5)
self.assertEqual(engine._ticks_per_sample(pd.points[2]), 1)
if __name__ == "__main__":
unittest.main()