{
  "asyncapi": "3.0.0",
  "info": {
    "title": "Tensor Energy蓄電池最適化API",
    "version": "2.2.0",
    "description": "Tensor Cloud蓄電池最適化サービスの通信プロトコル仕様。EMS端末がMQTTメッセージングを通じてTensor Cloudと通信するための仕様。",
    "termsOfService": "https://docs.tensorenergy.jp/legal/terms-of-use/",
    "externalDocs": {
      "description": "Tensor Cloud蓄電池最適化ドキュメンテーション",
      "url": "https://docs.tensorenergy.jp/api/battery-optimization"
    },
    "contact": {
      "name": "Tensor Energy",
      "url": "https://www.tensorenergy.jp"
    }
  },
  "servers": {
    "テスト環境": {
      "host": "mqtt.staging.tensorenergy.jp",
      "protocol": "mqtt",
      "protocolVersion": "3.1.1",
      "description": "テスト用Tensor Cloud MQTTブローカー（AWS IoT Core）",
      "security": [
        {
          "$ref": "#/components/securitySchemes/awsIotCore"
        }
      ]
    },
    "本番環境": {
      "host": "mqtt.tensorenergy.jp",
      "protocol": "mqtt",
      "protocolVersion": "3.1.1",
      "description": "Tensor Cloud本番MQTTブローカー（AWS IoT Core）",
      "security": [
        {
          "$ref": "#/components/securitySchemes/awsIotCore"
        }
      ]
    }
  },
  "defaultContentType": "application/json",
  "channels": {
    "lifetimeTelemetry": {
      "address": "dt/{siteId}/{gatewayId}/{metric}/lifetime",
      "title": "累積エネルギーテレメトリ",
      "summary": "累積エネルギー（kWh）を公開。Tensor Cloudは累積値かウィンドウ集計値のいずれかを必須（可能なら両方）。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        },
        "metric": {
          "$ref": "#/components/parameters/lifetimeMetric"
        }
      },
      "messages": {
        "energyLifetime": {
          "$ref": "#/components/messages/EnergyLifetime"
        }
      }
    },
    "energyTelemetry": {
      "address": "dt/{siteId}/{gatewayId}/{metric}/energy/{window}",
      "title": "ウィンドウエネルギーテレメトリ",
      "summary": "時間ウィンドウあたりのエネルギー（kWh）を公開。累積値かウィンドウ集計値のいずれかを必須（可能なら両方）。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        },
        "metric": {
          "$ref": "#/components/parameters/energyMetric"
        },
        "window": {
          "$ref": "#/components/parameters/window"
        }
      },
      "messages": {
        "energyWindowed": {
          "$ref": "#/components/messages/EnergyWindowed"
        }
      }
    },
    "powerTelemetry": {
      "address": "dt/{siteId}/{gatewayId}/{metric}/power",
      "title": "瞬時電力テレメトリ",
      "description": "瞬時電力（kW）を公開。必須ではないが、高頻度（10分以下）で送信すると推定精度が向上。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        },
        "metric": {
          "$ref": "#/components/parameters/powerMetric"
        }
      },
      "messages": {
        "powerInstant": {
          "$ref": "#/components/messages/PowerInstant"
        }
      }
    },
    "stateTelemetry": {
      "address": "dt/{siteId}/{gatewayId}/{metric}/state",
      "title": "装置状態テレメトリ",
      "summary": "装置の瞬間的な動作状態。蓄電池最適化にはSoEと残存容量が必須。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        },
        "metric": {
          "$ref": "#/components/parameters/batteryStateMetric"
        }
      },
      "messages": {
        "batteryState": {
          "$ref": "#/components/messages/BatteryStateValue"
        }
      }
    },
    "curtailment": {
      "address": "dt/{siteId}/{gatewayId}/curtailment",
      "title": "出力抑制スケジュール",
      "description": "出力抑制スケジュールのテレメトリ。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        }
      },
      "messages": {
        "curtailment": {
          "$ref": "#/components/messages/Curtailment"
        }
      }
    },
    "irradiationTelemetry": {
      "address": "dt/{siteId}/{gatewayId}/irradiation",
      "title": "日射量テレメトリ",
      "description": "発電所に設置された日射量センサーの測定値を公開。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        }
      },
      "messages": {
        "irradiation": {
          "$ref": "#/components/messages/Irradiation"
        }
      }
    },
    "batteryPowerCommand": {
      "address": "cmd/{siteId}/battery/power",
      "title": "蓄電池電力設定値コマンドスケジュール",
      "description": "蓄電池の実電力設定値コマンドスケジュールのトピック。蓄電池が一次調整力モードで運用される場合、このコマンドは一次調整力参加時の基準出力も決定します。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        }
      },
      "messages": {
        "batteryPowerCommand": {
          "$ref": "#/components/messages/BatteryPowerCommand"
        }
      }
    },
    "batteryFcrCommand": {
      "address": "cmd/{siteId}/battery/fcr",
      "title": "一次需給調整市場（オフライン）のコマンドスケジュール",
      "description": "一次需給調整市場（オフライン）のコマンドスケジュールのトピック",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        }
      },
      "messages": {
        "batteryFcrCommand": {
          "$ref": "#/components/messages/BatteryFcrCommand"
        }
      }
    },
    "commandResponse": {
      "address": "ack-cmd/{siteId}",
      "title": "コマンドレスポンス",
      "description": "EMSからTensor Cloudへのコマンド実行結果。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        }
      },
      "messages": {
        "commandResponse": {
          "$ref": "#/components/messages/CommandResponse"
        }
      }
    },
    "alertEvent": {
      "address": "dt/{siteId}/{gatewayId}/alert",
      "title": "アラートイベント",
      "summary": "サイトアラートの状態変更イベント。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        }
      },
      "messages": {
        "alertEvent": {
          "$ref": "#/components/messages/AlertEvent"
        }
      }
    },
    "alertState": {
      "address": "dt/{siteId}/{gatewayId}/alert/active",
      "title": "アラートスナップショット",
      "summary": "現在アクティブなすべてのアラートの定期スナップショット。",
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        }
      },
      "messages": {
        "alertState": {
          "$ref": "#/components/messages/AlertState"
        }
      }
    },
    "telemetryFeedback": {
      "address": "ack-dt/{siteId}/{gatewayId}",
      "title": "テレメトリフィードバック",
      "description": "各テレメトリに対する`error`/`ok`の明示ACK。開発用途。テスト環境のみ（本番では無視）。",
      "servers": [
        {
          "$ref": "#/servers/テスト環境"
        }
      ],
      "parameters": {
        "siteId": {
          "$ref": "#/components/parameters/siteId"
        },
        "gatewayId": {
          "$ref": "#/components/parameters/gatewayId"
        }
      },
      "messages": {
        "telemetryFeedback": {
          "$ref": "#/components/messages/TelemetryFeedback"
        }
      }
    }
  },
  "operations": {
    "sendLifetimeTelemetry": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/lifetimeTelemetry"
      },
      "summary": "累積エネルギー（kWh）を送信。累積かウィンドウ集計のいずれか必須（可能なら両方）。",
      "messages": [
        {
          "$ref": "#/channels/lifetimeTelemetry/messages/energyLifetime"
        }
      ]
    },
    "sendEnergyTelemetry": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/energyTelemetry"
      },
      "summary": "ウィンドウエネルギーを送信",
      "messages": [
        {
          "$ref": "#/channels/energyTelemetry/messages/energyWindowed"
        }
      ]
    },
    "sendPowerTelemetry": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/powerTelemetry"
      },
      "summary": "瞬時電力を送信",
      "messages": [
        {
          "$ref": "#/channels/powerTelemetry/messages/powerInstant"
        }
      ]
    },
    "sendBatteryState": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/stateTelemetry"
      },
      "summary": "単一の蓄電池状態測定値を送信",
      "description": "送信する値はチャンネルのmetric（battery_soe / battery_energy_remaining）で決まる。",
      "messages": [
        {
          "$ref": "#/channels/stateTelemetry/messages/batteryState"
        }
      ]
    },
    "sendCurtailment": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/curtailment"
      },
      "summary": "出力抑制スケジュールを送信",
      "description": "EMSが出力抑制スケジュールを送信。",
      "messages": [
        {
          "$ref": "#/channels/curtailment/messages/curtailment"
        }
      ]
    },
    "sendIrradiation": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/irradiationTelemetry"
      },
      "summary": "日射量テレメトリを送信",
      "description": "EMSが発電所に設置された日射量センサーの測定値を送信。",
      "messages": [
        {
          "$ref": "#/channels/irradiationTelemetry/messages/irradiation"
        }
      ]
    },
    "receivePowerCommand": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/batteryPowerCommand"
      },
      "summary": "充放電コマンドを受信",
      "description": "EMSゲートウェイがTensor Cloudから蓄電池の充放電スケジュールを受信。",
      "messages": [
        {
          "$ref": "#/channels/batteryPowerCommand/messages/batteryPowerCommand"
        }
      ]
    },
    "receiveFcrCommand": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/batteryFcrCommand"
      },
      "summary": "一次需給調整市場（オフライン）のコマンドを受信",
      "description": "EMSゲートウェイがTensor Cloudから一次需給調整市場（オフライン）の落札スケジュールを受信。",
      "messages": [
        {
          "$ref": "#/channels/batteryFcrCommand/messages/batteryFcrCommand"
        }
      ]
    },
    "sendCommandResponse": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/commandResponse"
      },
      "summary": "コマンドレスポンスを送信",
      "description": "レスポンストピックはack-cmd/{siteId}/名前空間内。デフォルトはack-cmd/{siteId}。外れるとブローカーに拒否される。",
      "messages": [
        {
          "$ref": "#/channels/commandResponse/messages/commandResponse"
        }
      ]
    },
    "sendAlertEvent": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/alertEvent"
      },
      "summary": "アラート状態変更イベントを送信",
      "messages": [
        {
          "$ref": "#/channels/alertEvent/messages/alertEvent"
        }
      ]
    },
    "sendAlertState": {
      "action": "send",
      "channel": {
        "$ref": "#/channels/alertState"
      },
      "summary": "現在のアクティブアラートスナップショットを送信",
      "messages": [
        {
          "$ref": "#/channels/alertState/messages/alertState"
        }
      ]
    },
    "receiveTelemetryFeedback": {
      "action": "receive",
      "channel": {
        "$ref": "#/channels/telemetryFeedback"
      },
      "summary": "テレメトリフィードバックを受信",
      "description": "各テレメトリに対するACK/エラー。テスト環境のみ。レスポンストピックはack-dt/{siteId}/{gatewayId}に限定。",
      "messages": [
        {
          "$ref": "#/channels/telemetryFeedback/messages/telemetryFeedback"
        }
      ]
    }
  },
  "components": {
    "parameters": {
      "siteId": {
        "description": "Tensor Cloudが最適化する系統接続ポイントを一意に識別するサイトID。\nフォーマット: 'si_' + 小文字英数字6桁\n例: si_qcf9gn\nオンボーディング時にTensor Energyが付与。"
      },
      "gatewayId": {
        "description": "Tensor Cloud接続EMS端末を一意に識別するゲートウェイID。\nフォーマット: 'gw_' + 小文字英数字6桁\n例: gw_0uv3tf\nオンボーディング時にTensor Energyが付与。"
      },
      "powerMetric": {
        "description": "瞬時電力（kW）のメトリック名。ユースケースにより必須は異なる。",
        "enum": [
          "meter_export_ac",
          "meter_import_ac",
          "grid_to_load_ac",
          "load_demand_ac",
          "solar_net_generation_ac",
          "battery_charge_ac",
          "battery_discharge_ac",
          "solar_to_grid_ac",
          "solar_to_battery_ac",
          "solar_to_load_ac",
          "battery_to_grid_ac",
          "battery_to_load_ac",
          "grid_to_battery_ac",
          "solar_generation_dc",
          "battery_charge_dc",
          "battery_to_inverter_dc",
          "inverter_net_output_ac",
          "solar_to_battery_dc",
          "solar_to_inverter_dc",
          "inverter_to_battery_dc",
          "inverter_to_load_ac",
          "inverter_to_grid_ac",
          "grid_to_inverter_ac"
        ]
      },
      "energyMetric": {
        "description": "集計エネルギー（kWh）のメトリック名。ユースケースにより必須は異なる。",
        "enum": [
          "meter_export_ac",
          "meter_import_ac",
          "grid_to_load_ac",
          "load_demand_ac",
          "solar_net_generation_ac",
          "battery_charge_ac",
          "battery_discharge_ac",
          "solar_to_grid_ac",
          "solar_to_battery_ac",
          "solar_to_load_ac",
          "battery_to_grid_ac",
          "battery_to_load_ac",
          "grid_to_battery_ac",
          "solar_generation_dc",
          "battery_charge_dc",
          "battery_to_inverter_dc",
          "inverter_net_output_ac",
          "solar_to_battery_dc",
          "solar_to_inverter_dc",
          "inverter_to_battery_dc",
          "inverter_to_load_ac",
          "inverter_to_grid_ac",
          "grid_to_inverter_ac"
        ]
      },
      "lifetimeMetric": {
        "description": "累積エネルギー（kWh）のメトリック名。増加カウンター（リセットは処理可能）。",
        "enum": [
          "meter_export_ac",
          "meter_import_ac",
          "grid_to_load_ac",
          "load_demand_ac",
          "solar_net_generation_ac",
          "battery_charge_ac",
          "battery_discharge_ac",
          "solar_to_grid_ac",
          "solar_to_battery_ac",
          "solar_to_load_ac",
          "battery_to_grid_ac",
          "battery_to_load_ac",
          "grid_to_battery_ac",
          "solar_generation_dc",
          "battery_charge_dc",
          "battery_to_inverter_dc",
          "inverter_net_output_ac",
          "solar_to_battery_dc",
          "solar_to_inverter_dc",
          "inverter_to_battery_dc",
          "inverter_to_load_ac",
          "inverter_to_grid_ac",
          "grid_to_inverter_ac"
        ]
      },
      "window": {
        "description": "集計ウィンドウ長（ISO 8601期間）",
        "enum": ["PT1M", "PT5M", "PT10M", "PT15M", "PT30M", "PT1H"]
      },
      "batteryStateMetric": {
        "description": "蓄電池状態メトリック。少なくとも、バッテリー状態エネルギー（SoE）とエネルギー残量（定格温度での蓄電池容量の残存kWh、劣化効果を含む）が必要です。\n\n- battery_soe: 現在この瞬間に蓄電池に蓄積されているエネルギー（State of ChargeのkWh相当）。頻繁に更新されます。有効範囲：0 ≤ battery_soe ≤ battery_energy_remaining。\n- battery_energy_remaining: 劣化および故障セルを考慮した、定格温度（約25°C）における蓄電池の総利用可能容量。蓄電池が保持できる最大エネルギーを表します。更新頻度は低い（通常1日1回）。",
        "enum": ["battery_soe", "battery_energy_remaining"]
      }
    },
    "messages": {
      "EnergyLifetime": {
        "name": "EnergyLifetime",
        "title": "累積エネルギー読み取りテレメトリ",
        "summary": "kWh単位の累積エネルギー。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "description": "累積エネルギー（kWh）の測定値",
              "type": "object",
              "properties": {
                "value": {
                  "description": "運用開始以来の累積エネルギー。これは、電力メーターのように時間とともに増加するカウンターである必要があります。Tensor Cloudはカウンターのリセットを処理できます。",
                  "type": "number",
                  "minimum": 0
                },
                "unit": {
                  "description": "測定単位",
                  "type": "string",
                  "enum": ["kWh"]
                }
              },
              "required": ["value", "unit"],
              "additionalProperties": false
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        }
      },
      "EnergyWindowed": {
        "name": "EnergyWindowed",
        "title": "ウィンドウエネルギー読み取りテレメトリ",
        "summary": "時間ウィンドウ集計エネルギー。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "description": "ウィンドウ内のエネルギー測定。タイムスタンプは左側が含まれ、右側は含まれません。つまり、*end_ts* が 10:30 の場合、10:29:59.999... までは含まれますが、10:30 自体は含まれません。",
              "type": "object",
              "properties": {
                "start_ts": {
                  "description": "ISO-8601準拠のタイムスタンプ。ウィンドウの開始時刻（含む）",
                  "type": "string",
                  "format": "date-time",
                  "examples": ["2024-01-04T03:00:00.000+09:00"]
                },
                "end_ts": {
                  "description": "ISO-8601準拠のタイムスタンプ。ウィンドウの終了時刻（含まれない）",
                  "type": "string",
                  "format": "date-time",
                  "examples": ["2024-01-04T03:30:00.000+09:00"]
                },
                "value": {
                  "description": "ウィンドウ内の総エネルギー測定",
                  "type": "number",
                  "minimum": 0
                },
                "unit": {
                  "description": "測定単位",
                  "type": "string",
                  "enum": ["kWh"]
                }
              },
              "required": ["start_ts", "end_ts", "value", "unit"],
              "additionalProperties": false
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        }
      },
      "PowerInstant": {
        "name": "PowerInstant",
        "title": "瞬時電力読み取りテレメトリ",
        "summary": "瞬時電力（kW）。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "description": "瞬時電力値",
              "type": "object",
              "properties": {
                "value": {
                  "description": "瞬時電力値",
                  "type": "number",
                  "minimum": 0
                },
                "unit": {
                  "description": "測定単位",
                  "type": "string",
                  "enum": ["kW"]
                }
              },
              "required": ["value", "unit"],
              "additionalProperties": false
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        }
      },
      "Curtailment": {
        "name": "出力抑制",
        "title": "出力抑制スケジュールテレメトリ",
        "summary": "出力抑制スケジュールのテレメトリメッセージ。このメッセージは任意ですが、特に系統用蓄電池システムの場合、蓄電池最適化の改善のために送信することを推奨します。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "description": "出力抑制スケジュール",
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "start_ts": {
                    "description": "ISO-8601準拠のタイムスタンプ。出力抑制イベントの開始時刻を示します。左側は含まれます。`end_ts`より前である必要があります。",
                    "type": "string",
                    "format": "date-time",
                    "examples": ["2024-01-04T14:00:00.000+09:00"]
                  },
                  "end_ts": {
                    "description": "ISO-8601準拠のタイムスタンプ。出力抑制イベントの終了時刻を示します。右側は含まれません。`start_ts`より後である必要があります。",
                    "type": "string",
                    "format": "date-time",
                    "examples": ["2024-01-04T14:30:00.000+09:00"]
                  },
                  "limit_percent": {
                    "description": "TSOによって許可される最大サイト出力の割合。0は100%のエネルギーが抑制され、サイト出力が許可されないことを意味します。値は[0,100]の範囲内である必要があります。",
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100
                  }
                },
                "required": ["start_ts", "end_ts", "limit_percent"]
              }
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        }
      },
      "Irradiation": {
        "name": "Irradiation",
        "title": "日射量テレメトリ",
        "summary": "発電所に設置された日射量センサーの測定値（kW/m2）",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "description": "発電所に設置された日射量センサーの測定値",
              "type": "object",
              "properties": {
                "value": {
                  "description": "瞬時日射量",
                  "type": "number",
                  "minimum": 0
                },
                "unit": {
                  "description": "測定単位",
                  "type": "string",
                  "enum": ["kW/m2"]
                }
              },
              "required": ["value", "unit"],
              "additionalProperties": false
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        },
        "examples": [
          {
            "name": "日射量測定例",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "measurement_ts": "2024-01-04T12:30:00.000+09:00",
              "measurement_value": {
                "value": 0.845,
                "unit": "kW/m2"
              }
            }
          }
        ]
      },
      "BatteryStateValue": {
        "name": "BatteryStateValue",
        "title": "Battery state telemetry",
        "summary": "Single battery state measurement",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。EMSによってテレメトリが測定された時刻。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "type": "object",
              "properties": {
                "value": {
                  "type": "number",
                  "minimum": 0
                },
                "unit": {
                  "type": "string",
                  "enum": ["kWh"]
                }
              },
              "additionalProperties": false,
              "required": ["value", "unit"]
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"]
        }
      },
      "BatteryPowerCommand": {
        "name": "BatteryPowerCommand",
        "title": "蓄電池電力設定値コマンド",
        "summary": "任意間隔のスケジュールで充放電を指示。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "issue_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。Tensor Cloudがコマンドを発行した時刻を示します。EMSが優先順位ポリシーを実行するために使用します。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-05T00:00:00.000+09:00"]
            },
            "res_topic": {
              "description": "EMSがコマンド結果を送信するレスポンストピック。ack-cmd/{siteId}名前空間内である必要があります。res_topic がこの名前空間外の場合、MQTT ブローカーによって拒否されます。",
              "type": "string",
              "pattern": "^ack-cmd/si_[a-z0-9]{6}$",
              "examples": ["ack-cmd/si_qcf9gn"]
            },
            "control": {
              "description": "蓄電池電力設定値スケジュールのペイロード",
              "type": "object",
              "properties": {
                "priority": {
                  "description": "制御コマンドの優先度。値が大きいほど優先度が高くなります。例: 値が50の場合は10よりも高い優先度を持ちます。",
                  "type": "number",
                  "minimum": 0,
                  "maximum": 100
                },
                "schedule": {
                  "description": "充放電スケジュール",
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "type": "object",
                    "properties": {
                      "start_ts": {
                        "description": "ISO-8601準拠のタイムスタンプ。スケジュールされた充放電イベントの開始時刻を示します。左側は含まれます。",
                        "type": "string",
                        "format": "date-time",
                        "examples": ["2024-01-05T00:00:00.000+09:00"]
                      },
                      "end_ts": {
                        "description": "ISO-8601準拠のタイムスタンプ。スケジュールされた充放電イベントの終了時刻を示します。右側は含まれません。",
                        "type": "string",
                        "format": "date-time",
                        "examples": ["2024-01-05T00:30:00.000+09:00"]
                      },
                      "power_kw": {
                        "description": "充放電に使用するキロワット単位の電力の量。正の値は充電を示し、負の値は放電を示します。0の値は待機を示します。",
                        "type": "number",
                        "examples": [10.123, -5.5, 0]
                      }
                    },
                    "additionalProperties": false,
                    "required": ["start_ts", "end_ts", "power_kw"]
                  }
                }
              },
              "additionalProperties": false,
              "required": ["schedule", "priority"]
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "issue_ts", "res_topic", "control", "schema_version"]
        }
      },
      "BatteryFcrCommand": {
        "name": "BatteryFcrCommand",
        "title": "一次需給調整市場（オフライン）のスケジュール",
        "summary": "Tensor CloudからEMSへ送信される一次需給調整市場（オフライン）の落札スケジュールが含まれるメッセージ",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "issue_ts": {
              "description": "ISO-8601準拠のタイムスタンプ。Tensor Cloudがコマンドを発行した時刻を示します。EMSが優先順位ポリシーを実行するために使用します。",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-05T00:00:00.000+09:00"]
            },
            "res_topic": {
              "description": "EMSがコマンド結果を送信するレスポンストピック。ack-cmd/{siteId}名前空間内である必要があります。res_topic がこの名前空間外の場合、MQTT ブローカーによって拒否されます。",
              "type": "string",
              "pattern": "^ack-cmd/si_[a-z0-9]{6}$",
              "examples": ["ack-cmd/si_qcf9gn"]
            },
            "control": {
              "description": "一次需給調整市場（オフライン）スケジュールのペイロード",
              "type": "object",
              "properties": {
                "priority": {
                  "description": "制御コマンドの優先度。値が大きいほど優先度が高くなります。例: 値が50の場合は10よりも高い優先度を持ちます。",
                  "type": "number",
                  "minimum": 0,
                  "maximum": 100
                },
                "action": {
                  "description": "実行するアクション。'execute'（デフォルト）は一次需給調整市場（オフライン）の落札スケジュールを実行します。'cancel'は指定された時間範囲内に以前に送信されたコマンドをキャンセルし、優先度ルールを尊重します（同等または低い優先度のコマンドのみをキャンセルします）。",
                  "type": "string",
                  "enum": ["execute", "cancel"],
                  "default": "execute"
                },
                "schedule": {
                  "description": "一次需給調整市場（オフライン）の制御スケジュール。action='execute'の場合、実行する落札が含まれます。action='cancel'の場合、キャンセルする時間範囲を指定します（capacity_kwは不要）。",
                  "type": "array",
                  "minItems": 1,
                  "items": {
                    "type": "object",
                    "properties": {
                      "start_ts": {
                        "description": "ISO-8601準拠のタイムスタンプ。一次需給調整市場（オフライン）の落札開始時刻を示します。左側は含まれます。",
                        "type": "string",
                        "format": "date-time",
                        "examples": ["2024-01-05T00:00:00.000+09:00"]
                      },
                      "end_ts": {
                        "description": "ISO-8601準拠のタイムスタンプ。一次需給調整市場（オフライン）の落札終了時刻を示します。右側は含まれません。",
                        "type": "string",
                        "format": "date-time",
                        "examples": ["2024-01-05T00:30:00.000+09:00"]
                      },
                      "capacity_kw": {
                        "description": "落札量（kW）。action='execute'の場合は必須、action='cancel'の場合は省略されます。",
                        "type": "number",
                        "minimum": 0,
                        "examples": [10.5, 25.0, 50.0]
                      }
                    },
                    "additionalProperties": false,
                    "required": ["start_ts", "end_ts"]
                  }
                }
              },
              "additionalProperties": false,
              "required": ["schedule", "priority"],
              "if": {
                "properties": {
                  "action": {
                    "const": "cancel"
                  }
                },
                "required": ["action"]
              },
              "then": {
                "properties": {
                  "schedule": {
                    "items": {
                      "not": {
                        "required": ["capacity_kw"]
                      }
                    }
                  }
                }
              },
              "else": {
                "properties": {
                  "schedule": {
                    "items": {
                      "required": ["capacity_kw"]
                    }
                  }
                }
              }
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "issue_ts", "res_topic", "control", "schema_version"]
        },
        "examples": [
          {
            "name": "一次需給調整市場（オフライン）コマンド例",
            "summary": "複数の3時間枠の落札スケジュールを実行",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "issue_ts": "2024-01-04T23:55:00.000+09:00",
              "res_topic": "ack-cmd/si_qcf9gn",
              "control": {
                "priority": 50,
                "action": "execute",
                "schedule": [
                  {
                    "start_ts": "2024-01-05T06:00:00.000+09:00",
                    "end_ts": "2024-01-05T09:00:00.000+09:00",
                    "capacity_kw": 1200.0
                  },
                  {
                    "start_ts": "2024-01-05T09:00:00.000+09:00",
                    "end_ts": "2024-01-05T12:00:00.000+09:00",
                    "capacity_kw": 1500.0
                  }
                ]
              }
            }
          },
          {
            "name": "一次需給調整市場（オフライン）キャンセルコマンド例",
            "summary": "翌日のすべての落札をキャンセル",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_c4ce10c4-1234-1234-1234-123456789012",
              "issue_ts": "2024-01-05T12:00:00.000+09:00",
              "res_topic": "ack-cmd/si_qcf9gn",
              "control": {
                "priority": 100,
                "action": "cancel",
                "schedule": [
                  {
                    "start_ts": "2024-01-06T00:00:00.000+09:00",
                    "end_ts": "2024-01-07T00:00:00.000+09:00"
                  }
                ]
              }
            }
          },
          {
            "name": "一次需給調整市場（オフライン）部分キャンセル例",
            "summary": "特定の3時間枠の落札をキャンセル",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_aabbccdd-3456-7890-abcd-ef1234567890",
              "issue_ts": "2024-01-05T10:30:00.000+09:00",
              "res_topic": "ack-cmd/si_qcf9gn",
              "control": {
                "priority": 75,
                "action": "cancel",
                "schedule": [
                  {
                    "start_ts": "2024-01-05T12:00:00.000+09:00",
                    "end_ts": "2024-01-05T15:00:00.000+09:00"
                  },
                  {
                    "start_ts": "2024-01-05T15:00:00.000+09:00",
                    "end_ts": "2024-01-05T18:00:00.000+09:00"
                  }
                ]
              }
            }
          }
        ]
      },
      "CommandResponse": {
        "name": "CommandResponse",
        "title": "コマンドレスポンス",
        "summary": "コマンド実行結果。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "このレスポンスの一意識別子",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "status": {
              "description": "コマンド実行のステータス",
              "type": "string",
              "enum": ["ok", "error"]
            },
            "command_id": {
              "description": "応答対象のコマンドメッセージのmessage_id",
              "type": "string",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "errors": {
              "description": "エラーの配列（status = 'error' の場合に必ず存在し、1 件以上を含む必要があります。それ以外の場合は省略されます）。相関するメッセージで検出された各エラーについて、EMS は配列内に 1 件の項目を送信する必要があります。",
              "type": "array",
              "minItems": 1,
              "items": {
                "type": "object",
                "properties": {
                  "code": {
                    "$ref": "#/components/schemas/ErrorCode"
                  },
                  "detail": {
                    "description": "状況を説明する詳細なエラーメッセージ",
                    "type": "string",
                    "examples": [
                      "電力値がバッテリーの最大容量を超えています",
                      "バッテリーへの接続が失われました"
                    ]
                  },
                  "field_path": {
                    "description": "エラーを引き起こしたフィールドへのパス。すべてのエラーがコマンドスケジュールの内容に直接起因するわけではないため任意。",
                    "type": "string",
                    "examples": ["control.schedule[0].power_kw"]
                  }
                },
                "required": ["code", "detail"],
                "additionalProperties": false
              }
            }
          },
          "additionalProperties": true,
          "required": ["message_id", "command_id", "status", "schema_version"],
          "if": {
            "properties": {
              "status": {
                "const": "error"
              }
            }
          },
          "then": {
            "required": ["errors"]
          },
          "else": {
            "not": {
              "required": ["errors"]
            }
          }
        },
        "examples": [
          {
            "name": "コマンドレスポンス正常例",
            "summary": "EMSがコマンドを正常に受け入れました",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_a80dd191-47fa-44ca-3243-40d7b4d88277",
              "status": "ok",
              "command_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277"
            }
          },
          {
            "name": "コマンドレスポンスエラー例",
            "summary": "Tensor Cloudがバッテリーの最大出力容量を超える放電電力値を送信しました",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_a80dd191-47fa-44ca-3243-40d7b4d88277",
              "status": "error",
              "command_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "errors": [
                {
                  "code": "FIELD_OUT_OF_RANGE",
                  "detail": "Power value exceeds battery maximum capacity",
                  "field_path": "control.schedule[0].power_kw"
                }
              ]
            }
          },
          {
            "name": "コマンドレスポンス複数エラー例",
            "summary": "EMSがスケジュール内のいくつかの検証失敗によりコマンドを拒否しました",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_44444444-5555-6666-7777-888888888888",
              "status": "error",
              "command_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "errors": [
                {
                  "code": "FIELD_OUT_OF_RANGE",
                  "detail": "Power value exceeds battery maximum capacity",
                  "field_path": "control.schedule[0].power_kw"
                },
                {
                  "code": "TIME_WINDOW_INVALID",
                  "detail": "End timestamp must be after start timestamp",
                  "field_path": "control.schedule[1].end_ts"
                },
                {
                  "code": "MISSING_FIELD",
                  "detail": "Priority field is required",
                  "field_path": "control.priority"
                }
              ]
            }
          }
        ]
      },
      "AlertEvent": {
        "name": "AlertEvent",
        "title": "アラートイベント",
        "summary": "アラートの状態変更イベント。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "measurement_ts": {
              "description": "EMS がアラート状態の変化を測定した時点のISO-8601タイムスタンプ",
              "type": "string",
              "format": "date-time",
              "examples": ["2024-01-04T03:26:10.000+09:00"]
            },
            "measurement_value": {
              "type": "object",
              "properties": {
                "code": {
                  "$ref": "#/components/schemas/AlertCode",
                  "description": "アラートタイプの識別子。"
                },
                "status": {
                  "description": "アラートが進行中（active）か、解決済み（cleared）か。",
                  "type": "string",
                  "enum": ["active", "cleared"]
                }
              },
              "required": ["code", "status"],
              "additionalProperties": false
            }
          },
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"],
          "additionalProperties": true
        }
      },
      "AlertState": {
        "name": "AlertState",
        "title": "アラートスナップショット",
        "summary": "現在アクティブなアラートのスナップショット。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "schema_version": {
              "description": "安全な進化と後方互換性のためのスキーマのバージョン",
              "type": "string",
              "default": "2.2.0",
              "pattern": "^\\d+\\.\\d+\\.\\d+$",
              "examples": ["2.2.0"]
            },
            "message_id": {
              "description": "メッセージのID（プレフィックス付きUUID形式）",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_99999999-8888-7777-6666-555555555555"]
            },
            "measurement_ts": {
              "description": "EMS がスナップショットを取得した時点の ISO-8601 準拠タイムスタンプ",
              "type": "string",
              "format": "date-time",
              "examples": ["2025-09-10T11:20:00+09:00"]
            },
            "measurement_value": {
              "description": "アラートとその現在の状態のリスト",
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "code": {
                    "$ref": "#/components/schemas/AlertCode",
                    "description": "アラートタイプの識別子"
                  },
                  "first_seen_ts": {
                    "type": "string",
                    "format": "date-time",
                    "description": "このアラートが最初にアクティブとして確認された時点のISO-8601準拠タイムスタンプ。"
                  },
                  "last_seen_ts": {
                    "type": "string",
                    "format": "date-time",
                    "description": "このアラートが最後にアクティブとして確認された時点のISO-8601準拠タイムスタンプ。"
                  }
                },
                "required": ["code", "first_seen_ts", "last_seen_ts"],
                "additionalProperties": false
              },
              "minItems": 0
            }
          },
          "required": ["message_id", "measurement_ts", "measurement_value", "schema_version"],
          "additionalProperties": true
        },
        "examples": [
          {
            "name": "FirstActiveAlert",
            "summary": "EMSが初めて低SOCアラートを発生",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_11111111-2222-3333-4444-555555555555",
              "measurement_ts": "2025-09-15T10:00:00+09:00",
              "measurement_value": [
                {
                  "code": "BATT_SOC_LOW",
                  "first_seen_ts": "2025-09-15T10:00:00+09:00",
                  "last_seen_ts": "2025-09-15T10:00:00+09:00"
                }
              ]
            }
          },
          {
            "name": "OngoingActiveAlert",
            "summary": "アラートが継続中のスナップショット",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_22222222-3333-4444-5555-666666666666",
              "measurement_ts": "2025-09-15T10:05:00+09:00",
              "measurement_value": [
                {
                  "code": "BATT_SOC_LOW",
                  "first_seen_ts": "2025-09-15T10:00:00+09:00",
                  "last_seen_ts": "2025-09-15T10:05:00+09:00"
                }
              ]
            }
          },
          {
            "name": "MultipleAlerts",
            "summary": "2つのアラートが同時にアクティブなスナップショット",
            "payload": {
              "schema_version": "2.2.0",
              "message_id": "msg_44444444-5555-6666-7777-888888888888",
              "measurement_ts": "2025-09-15T10:15:00+09:00",
              "measurement_value": [
                {
                  "code": "BATT_SOC_LOW",
                  "first_seen_ts": "2025-09-15T10:00:00+09:00",
                  "last_seen_ts": "2025-09-15T10:15:00+09:00"
                },
                {
                  "code": "PV_COMM_FAIL",
                  "first_seen_ts": "2025-09-15T10:12:00+09:00",
                  "last_seen_ts": "2025-09-15T10:15:00+09:00"
                }
              ]
            }
          }
        ]
      },
      "TelemetryFeedback": {
        "name": "TelemetryFeedback",
        "title": "テレメトリフィードバック",
        "summary": "テレメッセージに対する開発者向けフィードバック。テスト環境のみで使用され、本番環境では無視されます。",
        "correlationId": {
          "description": "message_idに基づくトレース",
          "location": "$message.payload#/message_id"
        },
        "contentType": "application/json",
        "payload": {
          "$schema": "http://json-schema.org/draft-07/schema#",
          "type": "object",
          "properties": {
            "message_id": {
              "description": "このレスポンスメッセージの一意なメッセージ識別子",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "correlation_id": {
              "description": "このフィードバックをトリガーしたテレメッセージの`message_id`",
              "type": "string",
              "pattern": "^msg_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
              "examples": ["msg_a80dd197-47fa-44ca-8966-40d7b4d88277"]
            },
            "status": {
              "description": "検証ステータス",
              "type": "string",
              "enum": ["ok", "error"]
            },
            "code": {
              "description": "statusがerrorの場合のエラーコード",
              "$ref": "#/components/schemas/ErrorCode"
            },
            "field_path": {
              "description": "該当する場合、エラーを引き起こしたフィールドへのパス",
              "type": "string",
              "examples": ["measurement_value.value"]
            },
            "detail": {
              "description": "詳細なエラーメッセージ",
              "type": "string",
              "examples": ["soe_kwh must be positive"]
            }
          },
          "required": ["message_id", "correlation_id", "status", "schema_version"],
          "additionalProperties": true,
          "if": {
            "properties": {
              "status": {
                "const": "error"
              }
            }
          },
          "then": {
            "required": ["code", "detail"]
          },
          "else": {
            "not": {
              "anyOf": [
                {
                  "required": ["code"]
                },
                {
                  "required": ["detail"]
                }
              ]
            }
          }
        },
        "examples": [
          {
            "name": "テレメッセージが検証を通過",
            "payload": {
              "message_id": "msg_11111111-2222-3333-4444-555555555555",
              "correlation_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "status": "ok"
            }
          },
          {
            "name": "テレメッセージが検証を通過しなかった",
            "payload": {
              "message_id": "msg_22222222-3333-4444-5555-666666666666",
              "correlation_id": "msg_a80dd197-47fa-44ca-8966-40d7b4d88277",
              "status": "error",
              "code": "FIELD_OUT_OF_RANGE",
              "field_path": "measurement_value.value",
              "detail": "soe_kwh must be positive"
            }
          }
        ]
      }
    },
    "schemas": {
      "AlertCode": {
        "type": "string",
        "enum": [
          "BATT_SOC_LOW",
          "BATT_SOH_DEGRADED",
          "BATT_OVERTEMP",
          "BATT_COMM_FAIL",
          "BATT_OTHER",
          "PV_COMM_FAIL",
          "PV_OTHER",
          "CURT_COMM_FAIL",
          "UNKNOWN_FAULT"
        ]
      },
      "ErrorCode": {
        "$schema": "http://json-schema.org/draft-07/schema#",
        "title": "エラーコード",
        "description": "標準化されたエラーコード。詳細な意味についてはプロトコル仕様の「エラーコード」セクションを参照してください。",
        "type": "string",
        "enum": [
          "MESSAGE_MALFORMED",
          "MISSING_FIELD",
          "TYPE_MISMATCH",
          "FIELD_OUT_OF_RANGE",
          "TIME_WINDOW_INVALID",
          "DUPLICATE",
          "EXPIRED",
          "RESOURCE_UNAVAILABLE",
          "INTERNAL_ERROR"
        ]
      }
    },
    "securitySchemes": {
      "awsIotCore": {
        "type": "X509",
        "description": "AWS IoT CoreのX.509証明書認証。証明書はTensor Energyが発行。"
      }
    }
  }
}
