equipment.py 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. """重大设备历史曲线取数;未确认的返回字段由 Agent 读取原始数据解释。"""
  2. import asyncio
  3. from extensions.main_fan import gateway_queries
  4. CURVE_PATH = '/zdsb/sbnode/selectSbNodeCurve'
  5. def describe_data(value, depth=0):
  6. """只展示实际JSON结构、数量和少量原值,不推断业务语义。"""
  7. if isinstance(value, dict):
  8. return {key: describe_data(item, depth + 1) for key, item in list(value.items())[:12]} if depth < 5 else {'type': 'object', 'keys': list(value)[:12]}
  9. if isinstance(value, list):
  10. return {'type': 'array', 'count': len(value),
  11. 'first': describe_data(value[0], depth + 1) if value and depth < 5 else None}
  12. return {'type': type(value).__name__, 'example': value[:120] if isinstance(value, str) else value}
  13. def _curve_data(body, node_id=None):
  14. if not isinstance(body, (dict, list)):
  15. raise ValueError('重大设备曲线未返回 JSON 对象或数组,请核对上游接口')
  16. data = body.get('data') if isinstance(body, dict) and 'data' in body else body
  17. series, known = [], data == []
  18. if isinstance(data, list) and data and all(isinstance(row, dict) and 'nodeId' in row
  19. and isinstance(row.get('sbNodeCurve'), list) for row in data):
  20. known = True
  21. try:
  22. for row in data:
  23. if node_id is not None and str(row['nodeId']) != node_id:
  24. raise ValueError('重大设备曲线返回测点与本次请求不一致')
  25. samples = []
  26. for sample in row['sbNodeCurve']:
  27. if not isinstance(sample, dict) or not {'dataTime', 'realData'} <= sample.keys():
  28. known = False
  29. break
  30. samples.append({'time': gateway_queries.parse_time(sample['dataTime']).isoformat(),
  31. 'value': sample['realData']})
  32. series.append({'node_id': str(row['nodeId']), 'node_place': row.get('nodePlace'), 'samples': samples})
  33. except ValueError as exc:
  34. if '返回测点' in str(exc):
  35. raise
  36. known = False
  37. summary = {'response_type': type(body).__name__,
  38. 'response_keys': list(body) if isinstance(body, dict) else None,
  39. 'data_type': type(data).__name__,
  40. 'data_keys': list(data) if isinstance(data, dict) else None,
  41. 'data_item_count': len(data) if isinstance(data, list) else None,
  42. 'sample_count': sum(len(row['samples']) for row in series) if known else None,
  43. 'normalization': 'sbNodeCurve' if known else 'unrecognized',
  44. 'data_structure': describe_data(data),
  45. 'next_action': '读取完整 data_path 的 payload 并核对实际曲线字段、测点、时间和单位;数组项数不等于已确认的采样点数。'}
  46. return {'payload': body, 'series': series if known else None}, summary
  47. async def query_timeseries(identifier, node_id, dept_id, start_time, end_time, user, session):
  48. params, _, _ = gateway_queries.curve_parameters(node_id, dept_id, start_time, end_time, node_key='nodeId')
  49. workflow, request, body = await gateway_queries.fetch(identifier, user, session, CURVE_PATH, params)
  50. data, summary = await asyncio.to_thread(_curve_data, body, node_id)
  51. return await asyncio.to_thread(gateway_queries.archive, workflow, user, session, request, body, data, summary,
  52. kind='equipment_timeseries', collection='equipment_queries', operation='查询重大设备历史时序',
  53. filename='equipment-curve.json')