Nature Remo APIを使ってChatGPTにECHONET Lite機器の情報を取ってきてもらうのは難しい

Nature Remo APIを使ってChatGPTに接続家電一覧を取得してもらおう - NEXTAltair's diary

Nature Remo APIを使ってChatGPTにエアコンを操作してもらう - NEXTAltair's diary

 

 

わかったこと

APIで取得できるのはEPC(エコーネット プロパティ コード)は16進数の値で取得されてその情報がなんのプロパティ名称かわからないためChatGPTが解釈できない

 

「知識」の項目に対応表をアップロードして参照させるという手法をとったが、その情報を活かしてる形跡はあるがハルシネーション起こして正確にプロパティ名称と対応付けられていない

 

まだ試してないこと

APIで取得したJSONに記載のEPCとプロパティ名称の対応をマッピングするスクリプトを書いてそれをChatGPTのインタプリタで実行させる

 

 

1.APIで取得できるプロパティを確認する

import requests

# アクセストークンの設定(この値を適切なものに置き換え)
token = 'トークン'

headers = {
    "Authorization": f"Bearer {token}"  # Pythonのf-stringを使用してトークンを動的に挿入
}

response = requests.get(url, headers=headers)
print(response.json())  # APIからのレスポンスを表示
with open('ENL.json', 'w') as f:
    f.write(str(response.json()))

 

{'appliances': [
        {'id': '', 'nickname': 'スマートメーター', 'type': 'EL_SMART_METER', 'properties': [
                {'epc': 'd3', 'val': '00000001', 'updated_at': '2024-04-22T08: 29: 04Z'
                },
                {'epc': 'd7', 'val': '06', 'updated_at': '2024-04-22T08: 29: 04Z'
                },
                {'epc': 'e0', 'val': '00062334', 'updated_at': '2024-04-22T08: 29: 04Z'
                },
                {'epc': 'e1', 'val': '01', 'updated_at': '2024-04-22T08: 29: 04Z'
                },
                {'epc': 'e3', 'val': '00012c10', 'updated_at': '2024-04-22T08: 29: 04Z'
                },
                {'epc': 'e7', 'val': '000001d8', 'updated_at': '2024-04-22T08: 32: 04Z'
                }
            ], 'Device': {'name': 'Remo E', 'id': '', 'created_at': '2022-12-25T06: 13: 30Z', 'updated_at': '2023-12-01T08: 55: 52Z', 'mac_address': '4c: 11:ae: 62:b8:e0', 'bt_mac_address': '4c: 11:ae: 62:b8:e2', 'serial_number': '3W119110005080', 'firmware_version': 'Remo-E/1.10.0', 'temperature_offset': 0, 'humidity_offset': 0
            }
        },
        {'id': '', 'nickname': 'エコキュート', 'type': 'EL_ELECTRIC_WATER_HEATER', 'properties': [
                {'epc': '80', 'val': '30', 'updated_at': '2024-04-22T08: 14: 04Z'
                },
                {'epc': '85', 'val': '001459a6', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'b0', 'val': '41', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'b2', 'val': '42', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'c0', 'val': '41', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'c3', 'val': '42', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'e1', 'val': '0172', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'e3', 'val': '42', 'updated_at': '2024-04-22T08: 29: 05Z'
                },
                {'epc': 'ea', 'val': '42', 'updated_at': '2024-02-01T12: 47: 21Z'
                }
            ], 'Device': {'name': 'Remo E', 'id': '', 'created_at': '2022-12-25T06: 13: 30Z', 'updated_at': '2023-12-01T08: 55: 52Z', 'mac_address': '4c: 11:ae: 62:b8:e0', 'bt_mac_address': '4c: 11:ae: 62:b8:e2', 'serial_number': '3W119110005080', 'firmware_version': 'Remo-E/1.10.0', 'temperature_offset': 0, 'humidity_offset': 0
            }
        }
    ]
}

 

epc プロパティ名称

val 値

updated_at 更新日時

 

2.EPCが何を示すのかしらべる

家で使ってるECHONET Lite機器を検索してプロパティ名称の対応の確認

APIから取得できるプロパティは共通で定義されてる機種によって違うってことはない、だろう

pdfファイルを強制的にダウンロードさせる仕様はしみじみ日本ってUI、UXの弱いよなと思わせる

https://echonet.jp/wp/wp-content/uploads/pdf/General/Standard/Release/Release_M/Appendix_Release_M.pdf

エコキュート | ECHONET

 

3.対応表を書いて「知識」としてアップロードする

「知識」としてアップロードするならYAML形式である必要はないと思うが解釈しやすそう

JSONだとコメントアウトつかえない

トムも居るがアクション受け付ける形式がJSONかYAMLだからそれに合わせた

もっと中身が込み入るときはTOMLのほうが向いてる気はする

書き方がファジーでもChatGPTがいい感じに解釈してくれるはず

 
EPC:
    SuperClass: # スーパークラスの定義
        0x80:
            description: '動作状態'
            data_type: 'unsigned char'
            values:
                30: 'ON'
                31: 'OFF'
        0x85:
            description: '積算消費電力計測値'
            unit: '0.001 kWh'  # 単位: 0.001 kWh
            data_type: 'unsigned long'  # データタイプ: unsigned long
            range: '0x00000000~0x3B9AC9FF'  # 範囲: 0~999,999.999 kWh
            access: 'Get'  # アクセス: 読み取り専用

    0x02: #住宅・設備関連機器クラスグループ
        0x6B: #電気温水器クラス規定
            description: 'EL_ELECTRIC_WATER_HEATER'
            0xB0:
                description: '沸き上げ自動設定'
                data_type: 'unsigned char'
                values:
                    0x41: '自動沸き上げ'
                    0x42: '手動沸き上げ'
                    0x43: '手動で沸き上げ停止'
            0xB2:
                description: '沸き上げ中状態'
                data_type: 'unsigned char'
                values:
                    0x41: '沸き上げ中'
                    0x42: '非沸き上げ中'
            0xC0:
                description: '昼間沸き増し許可設定'
                data_type: 'unsigned char'
                values:
                    0x41: '昼間沸き増し許可'
                    0x42: '昼間沸き増し禁止'
            0xC3:
                description: '給湯中状態'
                data_type: 'unsigned char'
                values:
                    0x41: '給湯中'
                    0x42: '非給湯中'
            0xE1:
                description: '残湯量計測値'
                data_type: 'unsigned short'
                unit: 'L'
                range: '0x0000~0xFFFD'
            0xE3:
                description: '風呂自動モード設定'
                data_type: 'unsigned char'
                values:
                    0x41: '自動入'
                    0x42: '手動解除'
            0xEA:
                description: '風呂動作状態監視'
                data_type: 'unsigned char'
                values:
                    0x41: '湯張り中'
                    0x42: '停止中'
                    0x43: '保温中'

        0x88: #電力量メータクラス
            description: 'EL_POWER_METER'
            0xD3:
                description: '係数'
                unit: '1'  # 単位: 1 (単位なし、1を係数として使用)
                data_type: 'unsigned long'  # データタイプ: unsigned long
                range: '0x00000000~0x000F423F'  # 範囲: 0~999999
                access: 'Get'  # アクセス: 読み取り専用
            0xD7:
                description: '積算電力量有効桁数'
                data_type: 'unsigned char'
                range: '0x01~0x08'
                access: 'Get'
            0xE0:
                description: '積算電力量計測値(正方向計測値)'
                unit: 'kWh'
                data_type: 'unsigned long'
                range: '0x00000000~0x05F5E0FF'
                access: 'Get'
            0xE1:
                description: '積算電力量単位(正方向、逆方向計測値)'
                data_type: 'unsigned char'
                values:
                    0x00: '1 kWh'
                    0x01: '0.1 kWh'
                    0x02: '0.01 kWh'
                    0x03: '0.001 kWh'
                    0x04: '0.0001 kWh'
                    0x0A: '10 kWh'
                    0x0B: '100 kWh'
                    0x0C: '1000 kWh'
                    0x0D: '10000 kWh'
            0xE3:
                description: '積算電力量計測値(逆方向計測値)'
                unit: 'kWh'
                data_type: 'unsigned long'
                range: '0x00000000~0x05F5E0FF'
                access: 'Get'
            0xE7:
                description: '瞬時電力計測値'
                unit: 'W'
                data_type: 'signed long'
                range: '0x80000001~0x7FFFFFFD'
                access: 'Get'

 

 


4.うまくいってるようでいってない

設定温度とか消費電力とkAPIから取得できないのに答える
ハルシネーション全開の返答

 

5.YAMLを確認しろというと何とかそれっぽくなる

正しいこと言い始めたっぽい
っぽいであってただし以下は俺もよくわからん

 

 

6.アクション用YAMLとプロンプト

openapi: 3.0.3
info:
  # APIの基本的な情報を含みます(タイトル、バージョン、説明など)
  title: Nature Remo for GPT
  version: 1
servers:
  # APIのエンドポイントを定義
paths:
  #利用可能なエンドポイントと、それぞれのHTTPメソッドに対する操作を記述
  /1/appliances:
  #家電一覧の表示と情報の取得
    get:
      summary: Remoに登録されている家電の一覧を取得
      operationId: getAppliances
      responses:
        "200":
          description: 接続された家電の一覧を取得しました
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Appliance"
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: "#/components/responses/Unauthorized"

  /1/echonetlite/appliances:
  #ECHONET Lite対応家電の一覧と情報の取得
    get:
      summary: ECHONET Lite対応家電の一覧を取得
      operationId: getEchonetLiteAppliances
      responses:
        "200":
          description: ECHONET Lite対応家電の一覧の取得完了
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: "#/components/schemas/Appliance"
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: "#/components/responses/Unauthorized"

  /1/echonetlite/appliances/{applianceid}/refresh:
  #ECHONET Lite対応家電の情報の更新
    post:
      summary: ECHONET Lite対応家電の情報を更新
      operationId: refreshEchonetLiteAppliance
      parameters:
        - name: applianceid
          in: path
          required: true
          schema:
            type: string
          description: ECHONET Lite対応家電のID
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                dummyField:
                  type: string
                  description: This is a dummy field to avoid schema object errors
      responses:
        "200":
          description: ECHONET Lite対応家電の情報を更新完了
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    description: 更新ステータス
        "400":
          $ref: '#/components/responses/BadRequest'
        "401":
          $ref: "#/components/responses/Unauthorized"


  /1/devices:
  #Remoデバイスと測定値の取得
    get:
      summary: デバイスのStatusを取得
      operationId: NatureRemoStatus
      parameters:
        - name: deviceId
          in: path
          required: true
          schema:
            type: string
          description: Nature Remoのステータス
      responses:
        "200":
          description: デバイスステータスの取得に成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  humidity:
                    type: number
                    format: float
                    description: 湿度
                  illuminance:
                    type: number
                    format: float
                    description: 照度
                  motion:
                    type: number
                    description: 動き
                  temperature:
                    type: number
                    format: float
                    description: 温度

        "404":
          $ref: "#/components/responses/NotFound"

  /1/appliances/{applianceid}/aircon_settings:
    post:
      summary: エアコンの設定を更新
      operationId: updateAirconSettings
      tags:
        - Aircon
      parameters:
        - name: applianceid
          in: path
          required: true
          schema:
            type: string
          description: 制御対象エアコンのID
      requestBody:
        required: true
        content:
          application/x-www-form-urlencoded:
            schema:
              type: object
              properties:
                air_direction:
                  type: string
                  description: AC 空気の方向。  空欄は自動
                  default: "auto"  # デフォルトで自動風向を設定
                air_direction_h:
                  type: string
                  description: AC水平風向。
                air_volume:
                  type: string
                  description: |-
                    AC風量。 空欄は自動。数字は風量
                    エアコンが受け付ける風量の範囲はエアコンの機種や運転モードによって異なる
                    特定のエアコン モデルと動作モードの範囲については、応答内の「AirConRangeMode」情報を確認
                  default: "auto"  # デフォルトで自動風量を設定
                button:
                  type: string
                  description: |-
                    ボタン。  エアコンの電源をオフにしたい場合「power-off」を指定
                    空欄は電源が入っていることを意味します。
                  default: ""      # 電源ONのデフォルト値
                operation_mode:
                  type: string
                  description: |-
                    AC動作モード。  エアコンが受け付ける運転モードの範囲はエアコンの機種によって異る。
                    特定のエアコン モデルの範囲については、応答内の「AirConRangeMode」情報を確認
                  default: "auto"  # デフォルトモードとして自動を設定
                temperature:
                  type: string
                  description: |-
                    温度。  文字列形式の温度。
                    ユニットは Aircon オブジェクトに記述
                    エアコンが許容できる温度範囲はエアコンの機種や運転モードによって異る
                    特定のエアコン モデルと動作モードの範囲については、応答内の「AirConRangeMode」情報を確認
                  default: "0"  # 日立のエアコンはオートモードでは基準温度-3から+3 なので0をデフォルト値として設定
                temperature_unit:
                  type: string
                  description: 温度単位。  不明の場合は「c」または「f」または「''」。
                  default: "c"
              required:
                - temperature
                - operation_mode
                - air_volume
                - air_direction
                - button
      responses:
        "200":
          description: エアコン設定を正常に更新
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    description: エアコンの状態
        "400":
          $ref: '#/components/responses/BadRequest'
        "404":
          $ref: '#/components/responses/NotFound'

components:
  # 再利用可能なスキーマやパラメータ、セキュリティスキームなどを定義
  responses:
    # エラーが発生した場合のレスポンスは共通であるためここ定義して使い回す
    400 Bad Request:
      description: 構文が正しくないため、リクエストをサーバーが理解できませんでした。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Bad Request
    401 Unauthorized:
      description: リクエストには認証が必要です。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Unauthorized
    403 Forbidden:
      description: リクエストする権限がありません。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Forbidden
    404 NotFound:
      description: 家電かデバイスのIDを確認してください。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
              message:
                type: string
                example: Device not found
    405 Method Not Allowed:
      description: リクエストされたメソッドは許可されていません。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Method Not Allowed
    408 Request Timeout:
      description: サーバーがリクエストを処理するのに時間がかかりすぎました。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Request Timeout
    500 Internal Server Error:
      description: サーバーでエラーが発生しました。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Internal Server Error
    502 Bad Gateway:
      description: ゲートウェイまたはプロキシサーバーが不正な応答を受信しました。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Bad Gateway
    503 Service Unavailable:
      description: サービスが一時的に利用できません。
      content:
        application/json:
          schema:
            type: object
            properties:
              error:
                type: string
                example: Service Unavailable
    bearerAuth:
      description: OAuth2トークンを使ってAPIにアクセス
      type: oauth2
      flows:
        clientCredentials:
          scopes: {}

  schemas:
  #  リクエストとレスポンスで使用されるデータ構造を定義
    Appliance:
      type: object
      properties:
        id:
          type: string
          description: Unique identifier for the appliance
        type:
          type: string
          description: Type of the appliance
        nickname:
          type: string
          description: User-defined name of the appliance
    Dummy:
      type: object
      properties:
        dummyField:
          type: string
          description: This is a dummy field to avoid schema object errors
security:
  # グローバルセキュリティ要件を指定
  # OAuth2トークンを使う場合bearerAuthを利用することが重要
  - bearerAuth: []

 

このGPTは、スマートホームデバイスのAPI連携とコントロールを手伝うために設計されています。
チャット開始時にNatureAPIを利用してNature Remo3から部屋の環境情報を自動的に取得し、それらのIDを記憶しておきます。
日本語でユーザーからの具体的な指示に従い、適切なAPIコールを行う方法や、デバイスを効率的に操作するためのアドバイスを提供します。
ECHONET Lite
ECHONET Liteデータを取得する際は、EPC.ymlファイルを参照して、生のEPCに対応する項目名を必ず取得し対応感系を確認する。epc や val は両方とも hex string で返ってきます。特に val は注意が必要で、10進数の 42 ではなく、16進数の 42 のため、10進数では 66 です。なお、このときの返り値の hex string は小文字で返ってきます。
エアコンの設定を頼まれた際には、まずgetAppliancesを使ってAirConRangeModeから有効な値を取得し、その情報に基づいて操作を行います。

ユーザーの質問や要望には簡潔に応答し、技術的な支援を行います。
ユーザーがAPIのアクションの作成を頼んだときは、GPTsで使えるYAML形式のコードを提供します。