refactor(config): 重构配置模块并优化应用依赖注入

- 将配置相关类移动到model模块
- 实现依赖注入容器管理各组件依赖关系
- 重构配置加载逻辑支持多层级键值查找
- 更新主应用入口支持命令行参数解析
- 统一日志输出格式替换原有打印语句
- 引入钻井实时数据模型简化数据处理
- 移除硬编码字段映射改用动态配置方式
- 优化数据库写入逻辑基于新的数据模型
This commit is contained in:
2026-03-12 10:41:26 +08:00
parent 6d13da4cc2
commit 6557479a2f
16 changed files with 783 additions and 589 deletions

View File

@@ -1,5 +1,6 @@
import argparse
import json
import logging
import os
import time
from datetime import datetime
@@ -7,57 +8,11 @@ from urllib.parse import urlparse
import paho.mqtt.client as mqtt
from config.config import build_mock_dependencies
from config import build_mock_dependencies
from model import DrillingRealtimeData
DATA_KEYS = [
"ts",
"wellid",
"stknum",
"recid",
"seqid",
"actual_date",
"actual_time",
"actcod",
"deptbitm",
"deptbitv",
"deptmeas",
"deptvert",
"blkpos",
"ropa",
"hkla",
"hklx",
"woba",
"wobx",
"torqa",
"torqx",
"rpma",
"sppa",
"chkp",
"spm1",
"spm2",
"spm3",
"tvolact",
"tvolcact",
"mfop",
"mfoa",
"mfia",
"mdoa",
"mdia",
"mtoa",
"mtia",
"mcoa",
"mcia",
"stkc",
"lagstks",
"deptretm",
"gasa",
"space1",
"space2",
"space3",
"space4",
"space5",
]
logger = logging.getLogger(__name__)
def parse_broker(broker):
@@ -81,16 +36,7 @@ def ensure_dir(path):
def build_server_payload(equipment_code):
data = {key: 0 for key in DATA_KEYS}
data["ts"] = int(time.time() * 1000)
data["wellid"] = ""
return {
"meta": {
"equipment_code": equipment_code,
"equipment_sn": equipment_code,
},
"data": data,
}
return DrillingRealtimeData.empty(wellid=equipment_code).to_payload(equipment_code)
def parse_payload(raw_payload):
@@ -146,67 +92,52 @@ def run_mock_service(args, deps):
tdengine_writer = deps.tdengine_writer
scheme, host, port = parse_broker(mqtt_config.broker)
print("MQTT mock config:")
print(f" broker: {scheme}://{host}:{port}")
print(f" client-id: {mqtt_config.mock_client_id}")
print(f" pub-topic (ingest): {mqtt_config.pub_topic}")
print(f" sub-topic (forward): {mqtt_config.sub_topic}")
print(f" ack-topic: {mqtt_config.ack_topic}")
print(f" data-file: {deps.data_file}")
print(f" device-code: {tms_config.device_code}")
print(f" tdengine enabled: {tdengine_writer.enabled}")
logger.info("MQTT mock config broker=%s://%s:%s client_id=%s mode=%s", scheme, host, port, mqtt_config.mock_client_id, args.mode)
logger.info("Topics ingest=%s forward=%s ack=%s", mqtt_config.pub_topic, mqtt_config.sub_topic, mqtt_config.ack_topic)
logger.info("Data file=%s device_code=%s tdengine_enabled=%s", deps.data_file, tms_config.device_code, tdengine_writer.enabled)
if tdengine_writer.enabled:
print(f" tdengine host: {tdengine_config.base_url}")
print(f" tdengine database: {tdengine_config.database}")
print(f" tdengine stable: {tdengine_config.stable}")
print(f" tdengine pool-size: {tdengine_config.pool_size}")
print(f" mode: {args.mode}")
logger.info("TDengine host=%s database=%s stable=%s pool_size=%s", tdengine_config.base_url, tdengine_config.database, tdengine_config.stable, tdengine_config.pool_size)
client = mqtt.Client(client_id=mqtt_config.mock_client_id, clean_session=True)
if mqtt_config.username is not None:
client.username_pw_set(mqtt_config.username, mqtt_config.password)
if scheme in ("ssl", "tls", "mqtts"):
client.tls_set()
def on_connect(c, userdata, flags, rc):
if rc == 0:
print("Connected")
logger.info("Connected")
else:
print(f"Connect failed rc={rc}")
logger.error("Connect failed rc=%s", rc)
return
if args.mode in ("listen", "both") and mqtt_config.pub_topic:
c.subscribe(mqtt_config.pub_topic)
print(f"Subscribed: {mqtt_config.pub_topic}")
logger.info("Subscribed %s", mqtt_config.pub_topic)
def on_disconnect(c, userdata, rc):
print(f"Disconnected callback rc={rc}")
logger.info("Disconnected callback rc=%s", rc)
def on_message(c, userdata, msg):
payload = msg.payload.decode("utf-8", errors="replace")
print(f"RX {msg.topic}: {payload}")
logger.info("RX topic=%s bytes=%s", msg.topic, len(msg.payload))
if msg.topic != mqtt_config.pub_topic:
return
if deps.data_file:
write_message(deps.data_file, msg.topic, payload)
print(f"Wrote to file: {deps.data_file}")
logger.info("Wrote file %s", deps.data_file)
if tdengine_writer.enabled:
try:
tdengine_writer.write_payload(parse_payload(payload))
print("Wrote to TDengine")
except Exception as exc:
print(f"Write TDengine failed: {exc}")
logger.info("Wrote TDengine")
except Exception:
logger.exception("Write TDengine failed")
if mqtt_config.sub_topic:
c.publish(mqtt_config.sub_topic, payload)
print(f"Forwarded to {mqtt_config.sub_topic}")
logger.info("Forwarded %s", mqtt_config.sub_topic)
if mqtt_config.ack_topic:
ack_payload = build_ack_payload(msg.topic, payload)
c.publish(mqtt_config.ack_topic, json.dumps(ack_payload, ensure_ascii=True))
print(f"TX {mqtt_config.ack_topic}: {ack_payload}")
logger.info("TX ack %s", mqtt_config.ack_topic)
client.on_connect = on_connect
client.on_disconnect = on_disconnect
@@ -217,14 +148,14 @@ def run_mock_service(args, deps):
try:
if args.mode in ("publish", "both"):
if not mqtt_config.pub_topic:
print("pub-topic is empty; nothing to publish")
logger.warning("pub-topic is empty; nothing to publish")
else:
seq = 0
while True:
seq += 1
payload = build_server_payload(tms_config.device_code)
client.publish(mqtt_config.pub_topic, json.dumps(payload, ensure_ascii=True))
print(f"TX {mqtt_config.pub_topic}: {payload}")
logger.info("TX %s #%s", mqtt_config.pub_topic, seq)
if args.count and seq >= args.count:
break
time.sleep(args.interval)
@@ -232,21 +163,25 @@ def run_mock_service(args, deps):
while True:
time.sleep(1)
except KeyboardInterrupt:
pass
logger.info("Mock interrupted")
finally:
client.loop_stop()
client.disconnect()
print("Disconnected")
logger.info("Mock stopped")
def main():
ap = argparse.ArgumentParser(description="MQTT mock service")
ap.add_argument("--config", default="config.yaml", help="Path to config yaml")
ap.add_argument("--mode", choices=["publish", "listen", "both"], default="listen")
ap.add_argument("--interval", type=float, default=2.0, help="Publish interval (seconds)")
ap.add_argument("--count", type=int, default=0, help="Publish count (0 = forever)")
ap.add_argument("--data-file", default="", help="Override data-file in config")
args = ap.parse_args()
def add_arguments(parser):
parser.add_argument("--config", default="config.yaml", help="Path to config yaml")
parser.add_argument("--mode", choices=["publish", "listen", "both"], default="listen")
parser.add_argument("--interval", type=float, default=2.0, help="Publish interval (seconds)")
parser.add_argument("--count", type=int, default=0, help="Publish count (0 = forever)")
parser.add_argument("--data-file", default="", help="Override data-file in config")
def main(argv=None):
parser = argparse.ArgumentParser(description="MQTT mock service")
add_arguments(parser)
args = parser.parse_args(argv)
deps = build_mock_dependencies(args.config, data_file_override=args.data_file)
run_mock_service(args, deps)