はじめに
今回、私が使用している オクトパスエナジー がGraphQL APIを提供しているので
それを用いて毎朝電気代が届くLine Botを開発します。
今回は、Railsと外部API連携、GraphQLの叩き方、 Line Messaging APIを利用していきます。
定期実行、デプロイ編について後編記事で書く予定です(まだ実装してない)
そもそもGraphQLって何?という方は下記の記事をご覧ください
使用技術
Rails(APIモード): 7.0.8
Ruby: 3.2.0
graphql 2.0.27
Line Messaging API
実装方針
1.Rails側からGraphQL叩いて電気代を取得出来るようにする
2.Line Messaging APIを利用して、取得した電気代情報をユーザーに送信する機能の実装
-- 今回はここまで --
3.開発環境で定期実行用のタスクを作成する
4.本番環境で定期実行を行えるようにする
Rails側からGraphQL叩いて電気代を取得出来るようにする
オクトパスエナジーで電気代を取得するには以下の2ステップになります。
1-1.emailとパスワードをクエリ変数として,認証トークンの取得(mutation)
1-2.認証トークンを使用して、電気代情報の取得(query)
MutationとQueryの使い分け
基本的には下記の図解の使い分けになります。
- RESTとは
Representational State Transfer
の略でwebサービスの設計モデルのこと - SQLとはデータベース用のクエリ言語のこと
- GraphQLとはAPIのクエリ言語のこと
Rest | SQL | GraphQL | |
---|---|---|---|
データ取得 | GET | Select | Query |
データ追加 | POST | Create | Mutation |
データ更新 | PATCH | Update | Mutation |
データ削除 | DELETE | Delete | Mutation |
データの取得はQueryでそれ以外はMutationと考えると覚えやすいかも知れません(因みにイベント監視はSubscription)
。
事前準備
とその前に RailsアプリでGraphqlが使えるように以下のgemを追加してbundle install
を行います。
gem 'graphql'
gem 'graphql-client'
gem 'dotenv-rails'
graphql-client
とは
GraphQLのクエリを宣言、作成、実行を行うRubyライブラリことです。
詳しくは以下を参照してください。
dotenv-rails
とは
環境変数を管理するRubyライブラリのことです。
自信が作成した、アプリケーションの直下に.env
ファイルを作成することでシークレットキーやパスワードなど
ネットに公開させたくない情報を扱い、自動で読み込むことが可能です。
OCTOPUS_EMAIL = "XXX@example.com"
OCTOPUS_PASSWORD = "passwordhogefuga"
のような形式で定義することができます。
呼び出す際は ENV["OCTOPUS_EMAIL"]
のような形式で呼び出すことができます!
隠したいファイルですので .gitignoreを設定 することは忘れないようにしましょう。
詳しくは以下を参照してください。
1-1.emailとパスワードをクエリ変数として,認証トークンの取得
上記インストールを行った後に、トークンの取得のために以下のファイルを作成します。
今回、graphql-client
について補足説明が少なかったのでコメントアウトで
説明しておきます。
require "graphql/client"
require "graphql/client/http"
class OctopusAuthenticationToken
# http アダプターを設定
HTTP = GraphQL::Client::HTTP.new("https://api.oejp-kraken.energy/v1/graphql/")
# 上記を使用して、API サーバーから GraphQL Schema を取得
Schema = GraphQL::Client.load_schema(HTTP)
# 上記を使ってクライアント作成
Client = GraphQL::Client.new(schema: Schema, execute: HTTP)
# ログイントークンを作成する,mutationを定義
LOGIN_QUERY = self::Client.parse <<~GRAPHQL
mutation($input: ObtainJSONWebTokenInput!) {
obtainKrakenToken(input: $input) {
token
refreshToken
}
}
GRAPHQL
def generate_token
# mutationを実行してその実行結果をresultに格納する
result = Client.query(LOGIN_QUERY, variables: {
input: {
email: ENV["OCTOPUS_EMAIL"],
password: ENV["OCTOPUS_PASSWORD"],
},
})
result.original_hash.dig("data", "obtainKrakenToken", "token")
end
end
上記で、ログイントークンを取得するためのGraphQLクライアントの設定とクエリの定義と、
トークン作成用のメソッドを定義しております。
1-2.認証トークンを使用して、電気代情報の取得
さて、認証トークンを作成したと思うのでそのトークンを元に
電気代取得のためのHTTPクライアントを作成します。
require "graphql/client"
require "graphql/client/http"
module OctopusClient
HTTP = GraphQL::Client::HTTP.new("https://api.oejp-kraken.energy/v1/graphql/") do
def headers(context)
{ "Authorization" => "#{OctopusAuthenticationToken.new.generate_token}" }
end
end
Schema = GraphQL::Client.load_schema(HTTP)
Client = GraphQL::Client.new(schema: Schema, execute: HTTP)
end
上記では,lib/octopus_authentication_token.rb
で作成した
OctopusAuthenticationToken
クラスのインスタンスメソッドを読んで
tokenを取得しヘッダーにセットし、Client作成を行っています。
そして,octopus_energy_bill/index
にアクセスをしたらAPIを叩くよう実装を行います。
class OctopusEnergyBillController < ApplicationController
GetBillQUERY = OctopusClient::Client.parse <<~'GRAPHQL'
query(
$accountNumber: String!
$fromDatetime: DateTime
$toDatetime: DateTime
) {
account(accountNumber: $accountNumber) {
properties {
electricitySupplyPoints {
agreements {
validFrom
}
halfHourlyReadings(
fromDatetime: $fromDatetime
toDatetime: $toDatetime
) {
startAt
endAt
value
costEstimate
consumptionStep
consumptionRateBand
}
}
}
}
}
GRAPHQL
def index
result = OctopusClient::Client.query(GetBillQUERY, variables: {
accountNumber: ENV['OCTOPUS_ACCOUNT_NUMBER'],
fromDatetime: Date.yesterday.beginning_of_day.iso8601,
toDatetime: Date.yesterday.end_of_day.iso8601
})
properties = result.original_hash.dig("data", "account", "properties")
electricity_supply_points = properties.first["electricitySupplyPoints"]
half_hourly_readings = electricity_supply_points.first["halfHourlyReadings"]
@kwh = half_hourly_readings.pluck("value").map(&:to_f).sum
@cost = half_hourly_readings.pluck("costEstimate").map(&:to_f).sum
puts "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
end
end
+ resources :octopus_energy_bill, only: %i[index]
また、今回の実装にあたりissue
を作成して実装したので参考にしたい方はどうぞ。
Line Messaging APIを利用して、取得した電気代情報をユーザーに送信する機能の実装
下記のgemを前の章同様にinstallしていきます。
gem 'line-bot-api'
Messaging API チャンネルを作成していきます。
上記の記事で詳しく説明されているので、当記事では省略します。
上記のような形で、今回はオクトパスエナジーの非公式botを作成しました。
また、今回作成された チャネルシークレト
をLINE_CHANNEL_SECRET
に、チャンネルアクセストークン
をLINE_CHANNEL_TOKEN
に.env
ファイルで定義します。
さて、チャネルシークレット
とチャネルアクセストークン
を使用してクライアントを作成します。
class LineBotClient
def client
Line::Bot::Client.new { |config|
config.channel_secret = ENV["LINE_CHANNEL_SECRET"]
config.channel_token = ENV["LINE_CHANNEL_TOKEN"]
}
end
end
この記述によってLineBotClient.new.client
、Line::Bot::Client
のインスタンスを作成出来るようになります。
さて、上記を使ってLINEを送ってみましょう!!
class OctopusEnergyBillController < ApplicationController
GetBillQUERY = OctopusClient::Client.parse <<~'GRAPHQL'
query(
$accountNumber: String!
$fromDatetime: DateTime
$toDatetime: DateTime
) {
account(accountNumber: $accountNumber) {
properties {
electricitySupplyPoints {
agreements {
validFrom
}
halfHourlyReadings(
fromDatetime: $fromDatetime
toDatetime: $toDatetime
) {
startAt
endAt
value
costEstimate
consumptionStep
consumptionRateBand
}
}
}
}
}
GRAPHQL
def index
result = OctopusClient::Client.query(GetBillQUERY, variables: {
accountNumber: ENV['OCTOPUS_ACCOUNT_NUMBER'],
fromDatetime: Date.yesterday.beginning_of_day.iso8601,
toDatetime: Date.yesterday.end_of_day.iso8601
})
properties = result.original_hash.dig("data", "account", "properties")
electricity_supply_points = properties.first["electricitySupplyPoints"]
half_hourly_readings = electricity_supply_points.first["halfHourlyReadings"]
@kwh = half_hourly_readings.pluck("value").map(&:to_f).sum
@cost = half_hourly_readings.pluck("costEstimate").map(&:to_f).sum
- puts "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
+ text = "#{Date.yesterday.strftime('%Y年%m月%d日')}は#{@kwh.round(2)}kWh消費して#{@cost}円かかったよ"
+ message = {
+ type: 'text',
+ text: text
+ }
+ LineBotClient.new.client.broadcast(message)
end
end
そして、/octopus_energy_bill
エンドポイントにアクセスすると、以下のようにLINEが送ることができます。
以上で今回の目標物は完成です!!
最後に
いかがでしたでしょうか。
今回は、GraphQLとRails(APIモード)を使用して、電気代Line botを開発していきました。
次回はデプロイと定期実行を行なっていこうと思います🔥
最後まで読んで頂きありがとうございました!
後編記事
参考文献