[
  {
    "id": "tab_edge_monitor",
    "type": "tab",
    "label": "Edge 시스템 모니터링",
    "disabled": false,
    "info": "",
    "env": []
  },
  {
    "id": "n_inject_mon",
    "type": "inject",
    "z": "tab_edge_monitor",
    "name": "30초 주기",
    "props": [
      {
        "p": "payload"
      }
    ],
    "repeat": "30",
    "crontab": "",
    "once": true,
    "onceDelay": "1",
    "topic": "",
    "payload": "",
    "payloadType": "date",
    "x": 130,
    "y": 100,
    "wires": [
      [
        "n_func_login_prep"
      ]
    ]
  },
  {
    "id": "n_func_login_prep",
    "type": "function",
    "z": "tab_edge_monitor",
    "name": "로그인 준비",
    "func": "msg.url = 'http://127.0.0.1/login/login';\nmsg.method = 'POST';\nmsg.payload = 'user_id=<USER_ID>&password=<PASSWORD>';\nmsg.headers = {'Content-Type': 'application/x-www-form-urlencoded'};\nreturn msg;",
    "outputs": 1,
    "timeout": 0,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 310,
    "y": 100,
    "wires": [
      [
        "n_http_login"
      ]
    ]
  },
  {
    "id": "n_http_login",
    "type": "http request",
    "z": "tab_edge_monitor",
    "name": "POST /login/login",
    "method": "use",
    "ret": "txt",
    "paytoqs": "ignore",
    "url": "",
    "tls": "",
    "persist": true,
    "proxy": "",
    "insecureHTTPParser": false,
    "authType": "",
    "senderr": false,
    "headers": [],
    "x": 510,
    "y": 100,
    "wires": [
      [
        "n_func_cookie"
      ]
    ]
  },
  {
    "id": "n_func_cookie",
    "type": "function",
    "z": "tab_edge_monitor",
    "name": "쿠키 추출 → 모니터 요청",
    "func": "var sid = null;\nvar c = msg.responseCookies;\nif (c && c.PP_EDGE_JSESSIONID) {\n    sid = c.PP_EDGE_JSESSIONID.value || c.PP_EDGE_JSESSIONID;\n}\nif (!sid) {\n    var sc = msg.headers && (msg.headers['set-cookie'] || msg.headers['Set-Cookie']);\n    if (sc) {\n        var m = (Array.isArray(sc) ? sc.join(';') : sc).match(/PP_EDGE_JSESSIONID=([^;]+)/);\n        if (m) sid = m[1];\n    }\n}\nif (!sid) { node.warn('로그인 실패: ' + JSON.stringify(msg.payload)); return null; }\n\n// global에도 저장 → 다른 탭에서 재사용\nglobal.set('jsession', sid);\nflow.set('jsession', sid);\n\nmsg.url = 'http://127.0.0.1/monitor/bean';\nmsg.method = 'GET';\nmsg.payload = '';\nmsg.headers = { Cookie: 'PP_EDGE_JSESSIONID=' + sid };\nreturn msg;",
    "outputs": 1,
    "timeout": 0,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 730,
    "y": 100,
    "wires": [
      [
        "n_http_mon"
      ]
    ]
  },
  {
    "id": "n_http_mon",
    "type": "http request",
    "z": "tab_edge_monitor",
    "name": "GET /monitor/bean",
    "method": "use",
    "ret": "obj",
    "paytoqs": "ignore",
    "url": "",
    "tls": "",
    "persist": true,
    "proxy": "",
    "insecureHTTPParser": false,
    "authType": "",
    "senderr": false,
    "headers": [],
    "x": 980,
    "y": 100,
    "wires": [
      [
        "n_func_metrics"
      ]
    ]
  },
  {
    "id": "n_func_metrics",
    "type": "function",
    "z": "tab_edge_monitor",
    "name": "메트릭 추출",
    "func": "var d = msg.payload && msg.payload.data;\nif (!d) { node.warn('데이터 없음: ' + JSON.stringify(msg.payload)); return null; }\nmsg.payload = {\n    cpu:              d.cpu_used_percent.toFixed(1) + '%',\n    memory:           d.memory_used_percent.toFixed(1) + '%',\n    disk:             d.disk_used_percent.toFixed(1) + '%',\n    tag_count:        d.tag_count,\n    opc_count:        d.opc_count,\n    mps:              d.mps,\n    plc_connected:    d.plc_con_connected_count,\n    plc_disconnected: d.plc_con_disconnected_count,\n    temperature:      d.temperature,\n    net_ip:           d.net_1_ip\n};\nglobal.set('metrics_cache', msg.payload);   // 대시보드 · REST API 탭이 읽는다\nreturn msg;",
    "outputs": 1,
    "timeout": 0,
    "noerr": 0,
    "initialize": "",
    "finalize": "",
    "libs": [],
    "x": 1200,
    "y": 100,
    "wires": [
      [
        "n_debug_metrics"
      ]
    ]
  },
  {
    "id": "n_debug_metrics",
    "type": "debug",
    "z": "tab_edge_monitor",
    "name": "시스템 메트릭",
    "active": true,
    "tosidebar": true,
    "console": false,
    "tostatus": true,
    "complete": "payload",
    "targetType": "msg",
    "statusVal": "payload.cpu",
    "statusType": "auto",
    "x": 1420,
    "y": 100,
    "wires": []
  }
]
