このクライアントを使用すると、独自の oAuth プロセス、API リクエスト、ページネーションをコーディングすることなく、MyJohnDeere API に接続できます。
get
、 create
、 put
、およびdelete
メソッドを提供して、認証された直接 API 呼び出しを簡単に実行できます。each
、 map
などの呼び出しは、必要に応じてデータの新しいページをフェッチします。 RDoc ドキュメントを提供していますが、開始するための役立つガイドは次のとおりです。 gem 名が長いため、すべての例では次のショートカットを想定しています。
JD = MyJohnDeereApi
したがって、次のように表示された場合:
JD :: Authorize
それは実際には次のことを意味します:
MyJohnDeereApi :: Authorize
このライブラリは gem として入手できます。これを使用するには、gem をインストールするだけです。
gem install my_john_deere_api
Bundler を使用している場合 (そして、なぜ使用しないのでしょうか?)、gem ファイルに gem を追加します。
gem 'my_john_deere_api'
そして実行します:
bundle install
これは承認への最も簡単なパスですが、ユーザーは確認コードを提供するという追加のフープを飛び越える必要があります。
# Create an authorize object, using your app's API key and secret. You can
# pass an environment (`:live` or `:sandbox`), which default to `:live`.
authorize = JD :: Authorize . new ( API_KEY , API_SECRET , environment : :sandbox )
# Retrieve a valid authorization url from John Deere, where you can send
# your user for authorizing your app to the JD platform.
url = authorize . authorize_url
# Verify the code given to the user during the authorization process, and
# turn this into access credentials for your user.
authorize . verify ( code )
実際には、ユーザーが戻ったときに Authorize オブジェクトを再インスタンス化する必要がある可能性がありますが、これは問題なく機能します。
# Create an authorize object, using your app's API key and secret.
authorize = JD :: Authorize . new ( API_KEY , API_SECRET , environment : :sandbox )
# Retrieve a valid authorization url from John Deere.
url = authorize . authorize_url
# Queue elevator music while your app serves other users...
# Re-create the authorize instance in a different process
authorize = JD :: Authorize . new ( API_KEY , API_SECRET , environment : :sandbox )
# Proceed as normal
authorize . verify ( code )
Web アプリでは、ユーザーが確認コードをコピー/ペーストする必要がないことが望まれます。したがって、:oauth_callback URL を渡すことができます。ユーザーが John Deere でアプリを承認すると、検証コードを含むパラメーター「oauth_verifier」を使用して指定した URL にリダイレクトされるため、ユーザーは検証コードを指定する必要がありません。
# Create an authorize object, using your app's API key and secret.
authorize = JD :: Authorize . new (
API_KEY ,
API_SECRET ,
environment : :sandbox ,
oauth_callback : 'https://example.com'
)
# Retrieve a valid authorization url from John Deere.
# This will contain the callback url encoded into the
# query string for you.
url = authorize . authorize_url
# Queue elevator music while your app serves other users...
# Re-create the authorize instance in a different process.
# It's not necessary to re-initialize with the callback url.
authorize = JD :: Authorize . new ( API_KEY , API_SECRET , environment : :sandbox )
# Inside a Rails controller, you might do this:
authorize . verify ( params [ :oauth_verifier ] )
認可が完了すると、 Client
オブジェクトはこのライブラリのインターフェイスの大部分を提供します。一部の API 呼び出しは、ユーザーではなくアプリケーションと John Deere の関係に固有であるため、クライアントはユーザー資格情報の有無にかかわらず使用できます。しかし、ほとんどのやり取りにはユーザーデータが関係します。クライアントをインスタンス化する方法は次のとおりです。
client = JD :: Client . new (
# the application's API key
API_KEY ,
# the application's API secret
API_SECRET ,
# the chosen environment (:sandbox or :live)
environment : :sandbox ,
# optional contribution_definition_id. This is needed for some requests,
# but the client can be created without it, in order to find it.
contribution_definition_id : CONTRIBUTION_DEFINITION_ID ,
# the user's access credentials
access : [ ACCESS_TOKEN , ACCESS_SECRET ]
)
接続すると、クライアントは ActiveRecord の簡易版のように動作します。 API からの JSON ハッシュは、操作しやすいようにオブジェクトに変換されます。組織などのコレクションがページネーションを処理します。 each
、 map
などを使用して反復するだけで、必要に応じて新しいページがフェッチされます。
このクライアントは進行中です。現在、API 呼び出しに頼らずに次のことを実行できます。
client
├── contribution_products
| ├── count
| ├── all
| ├── first
| └── find(contribution_product_id)
| └── contribution_definitions
| ├── count
| ├── all
| ├── first
| └── find(contribution_definition_id)
└── organizations
├── count
├── all
├── first
└── find(organization_id)
├── assets(attributes)
| ├── create(attributes)
| ├── count
| ├── all
| ├── first
| └── find(asset_id)
| ├── save
| ├── update(attributes)
| └── locations
| ├── create(attributes)
| ├── count
| ├── all
| └── first
└── fields
├── count
├── all
├── first
└── find(field_id)
└── flags
├── count
├── all
└── first
貢献 製品コレクションはリストのように機能します。 Ruby の Enumerable モジュールを介して含まれるすべてのメソッドに加えて、コントリビューション製品コレクションは次のメソッドをサポートします。
個々のコントリビューション製品は、次のメソッドと関連付けをサポートしています。
client . contribution_products
# => collection of contribution products under this client
client . contribution_products . count
# => 1
client . contribution_products . first
# => an individual contribution product
contribution_product = client . contribution_products . find ( 1234 )
# => an individual contribution product, fetched by ID
contribution_product . market_place_name
# => 'Market Place Name'
contribution_product . contribution_definitions
# => collection of contribution definitions belonging to this contribution product
コントリビューション製品のコントリビューション定義を処理します。コントリビューション定義コレクションは、次のメソッドをサポートしています。
個々の貢献定義は、次のメソッドと関連付けをサポートしています。
contribution_product . contribution_definitions
# => collection of contribution definitions under this contribution product
client . contribution_definitions . count
# => 1
client . contribution_definitions . first
# => an individual contribution definition
contribution_definition = contribution_product . contribution_definitions . find ( 1234 )
# => an individual contribution definition, fetched by ID
contribution_definition . name
# => 'Contribution Definition Name'
アカウントの組織を処理します。組織コレクションは次のメソッドをサポートしています。
個々の組織は、次の方法と関連付けをサポートしています。
count
メソッドでは、結果の最初のページを読み込むだけでよいため、比較的低コストの呼び出しです。一方、 all
指定すると、強制的にコレクション全体が John Deere の API からロードされるため、使用には注意が必要です。 API を介して組織を作成することはできないため、このコレクションにはcreate
メソッドがありません。
client . organizations
# => collection of organizations under this client
client . organizations . count
# => 15
client . organizations . first
# => an individual organization object
organization = client . organizations . find ( 1234 )
# => an individual organization object, fetched by ID
organization . name
# => 'Smith Farms'
organization . type
# => 'customer'
organization . member?
# => true
organization . links
# => {
# 'self' => 'https://sandboxapi.deere.com/platform/organizations/1234',
# 'machines' => 'https://sandboxapi.deere.com/platform/organizations/1234/machines',
# 'wdtCapableMachines' => 'https://sandboxapi.deere.com/platform/organizations/1234/machines?capability=wdt'
# }
organization . assets
# => collection of assets belonging to this organization
organization . fields
# => collection of fields belonging to this organization
組織の資産を扱います。アセット コレクションは次のメソッドをサポートしています。
個々のアセットは、次のメソッドと関連付けをサポートします。
organization = client . organizations . first
# => the first organization returned by the client
organization . assets
# => collection of assets belonging to this organization
asset = organization . assets . find ( 123 )
# => an individual asset object, fetched by ID
asset . title
# => 'AgThing Water Device'
asset . category
# => 'DEVICE'
asset . type
# => 'SENSOR'
asset . sub_type
# => 'OTHER'
asset . links
# => a hash of API urls related to this asset
create
メソッドは、John Deere プラットフォームにアセットを作成し、新しく作成されたレコードを返します。
asset = organization . assets . create (
title : 'Asset Title' ,
asset_category : 'DEVICE' ,
asset_type : 'SENSOR' ,
asset_sub_type : 'ENVIRONMENTAL'
)
asset . title
# => 'Asset Title'
update
メソッドはローカル オブジェクトを更新し、John Deere プラットフォーム上のアセットも更新します。アセットのタイトルのみを更新できます。
asset . update ( title : 'New Title' )
asset . title
# => 'New Title', also John Deere record is updated
save
メソッドは、ローカルで行われた変更を反映して John Deere を更新します。
asset . title = 'New Title'
asset . save
# => Successful Net::HTTPNoContent object
アセットの場所を処理します。アセット ロケーション コレクションは次のメソッドをサポートしています。
個々の場所では次の方法がサポートされています。
asset = organizations . assets . first
# => the first asset returned by the organization
asset . locations
# => collection of locations belonging to this asset
location = asset . locations . first
# => the first location returned by the asset. Note that locations do not have their own id's
# in the JD platform, and therefore cannot be requested individually via a "find" method.
location . timestamp
# => "2019-11-11T23:00:00.000Z"
# John Deere includes 3 decimal places in the format, but does not actually
# store fractions of a second, so it will always end in ".000". This is
# important, because timestamps must be unique.
location . geometry
# => a GeoJSON formatted hash, for example:
# {
# "type"=>"Feature",
# "geometry"=>{
# "geometries"=>[
# {
# "coordinates"=>[-95.123456, 40.123456],
# "type"=>"Point"
# }
# ],
# "type"=>"GeometryCollection"
# }
# }
location . measurement_data
# => the status details of this location, for example:
# [
# {
# "@type"=>"BasicMeasurement",
# "name"=>"[Soil Temperature](http://example.com/current_temperature)",
# "value"=>"21.0",
# "unit"=>"°C"
# }
# ]
create
メソッドは、John Deere プラットフォームに場所を作成し、新しく作成されたオブジェクトを John Deere から返します。ただし、固有の ID は生成されないため、新しい情報はありません。送信されたタイムスタンプ (デフォルトは「現在」) は、最も近い秒に丸められます。
locaton = asset . locatons . create (
# You can pass fractional seconds, but they will be truncated by JD.
timestamp : "2019-11-11T23:00:00.123Z" ,
# JD requires more complicated JSON geometry, but this client will convert a simple
# set of lat/long coordinates into the larger format automatically.
geometry : [ - 95.123456 , 40.123456 ] ,
# This is a list of "measurements"
measurement_data : [
{
name : 'Temperature' ,
value : '68.0' ,
unit : 'F'
}
]
)
location . timestamp
# => "2019-11-11T23:00:00.000Z"
# Note that the timestamp's fractional second is truncated by John Deere, though they
# still return the record with three digits of precision.
location . geometry
# => a GeoJSON formatted hash in its larger format
# {
# "type"=>"Feature",
# "geometry"=>{
# "geometries"=>[
# {
# "coordinates"=>[-95.123456, 40.123456],
# "type"=>"Point"
# }
# ],
# "type"=>"GeometryCollection"
# }
# }
location . measurement_data
# [
# {
# "@type"=>"BasicMeasurement",
# "name"=>"Temperature",
# "value"=>"68.0",
# "unit"=>"F"
# }
# ]
場所の更新や削除はありません。最新の位置レコードは常に特定の資産のステータスとして機能し、マップ ビューに表示されます。
John Deere では場所は「資産の場所」と呼ばれますが、簡潔にするために、 asset.locations
のように関連付けを「場所」と呼ぶことに注意してください。
組織のフィールドを処理します。フィールド コレクションは次のメソッドをサポートします。
個々のフィールドは、次のメソッドと関連付けをサポートしています。
count
メソッドでは、結果の最初のページを読み込むだけでよいため、比較的低コストの呼び出しです。一方、 all
指定すると、強制的にコレクション全体が John Deere の API からロードされるため、使用には注意が必要です。フィールドは API 経由で作成できますが、このコレクションにはまだcreate
メソッドがありません。
organization . fields
# => collection of fields under this organization
organization . fields . count
# => 15
organization . fields . first
# => an individual field object
field = organization . fields . find ( 1234 )
# => an individual field object, fetched by ID
field . name
# => 'Smith Field'
field . archived?
# => false
field . links
# => a hash of API urls related to this field
field . flags
# => collection of flags belonging to this field
フィールドのフラグを処理します。フラグ コレクションは次のメソッドをサポートします。 John Deere は、ID によって特定のフラグを取得するエンドポイントを提供していないことに注意してください。
個々のフラグは、次のメソッドと関連付けをサポートします。
count
メソッドでは、結果の最初のページを読み込むだけでよいため、比較的低コストの呼び出しです。一方、 all
指定すると、強制的にコレクション全体が John Deere の API からロードされるため、使用には注意が必要です。フラグは API 経由で作成できますが、このコレクションにはまだcreate
メソッドがありません。
field . flags
# => collection of flags under this field
field . flags . count
# => 15
flag = field . flags . first
# => an individual flag object
flag . notes
# => 'A big rock on the left after entering the field'
flag . geometry
# => a GeoJSON formatted hash, for example:
# {
# "type"=>"Feature",
# "geometry"=>{
# "geometries"=>[
# {
# "coordinates"=>[-95.123456, 40.123456],
# "type"=>"Point"
# }
# ],
# "type"=>"GeometryCollection"
# }
# }
field . archived?
# => false
field . proximity_alert_enabled?
# => true
field . links
# => a hash of API urls related to this flag
クライアントの目標は、John Deere API の呼び出しを実行/解釈する必要をなくすことですが、クライアントによってまだ完全にはサポートされていない呼び出しを実行できることが重要です。場合によっては、トラブルシューティングが必要になる場合もあります。
GET リクエストにはリソース パスのみが必要です。
client . get ( '/organizations' )
応答サンプルの簡略化:
{
"links" : [ " ... " ],
"total" : 1 ,
"values" : [
{
"@type" : " Organization " ,
"name" : " ABC Farms " ,
"type" : " customer " ,
"member" : true ,
"id" : " 123123 " ,
"links" : [ " ... " ]
}
]
}
これにより、ページネーションや検証などのクライアント機能は提供されませんが、返された JSON は解析されます。
POST リクエストには、リソース パスとリクエスト本文のハッシュが必要です。クライアントはキーをラクダ化して JSON に変換します。
client . post (
'/organizations/123123/assets' ,
{
"title" => "i like turtles" ,
"assetCategory" => "DEVICE" ,
"assetType" => "SENSOR" ,
"assetSubType" => "ENVIRONMENTAL" ,
"links" => [
{
"@type" => "Link" ,
"rel" => "contributionDefinition" ,
"uri" => "https://sandboxapi.deere.com/platform/contributionDefinitions/CONTRIBUTION_DEFINITION_ID"
}
]
}
)
John Deere の標準応答は、「作成されました」というメッセージを含む 201 HTTP ステータス コードです。このメソッドは、完全な Net::HTTP 応答を返します。
PUT リクエストには、リソース パスとリクエスト本文のハッシュが必要です。クライアントはキーをラクダ化して JSON に変換します。
client . put (
'/assets/123123' ,
{
"title" => "i REALLY like turtles" ,
"assetCategory" => "DEVICE" ,
"assetType" => "SENSOR" ,
"assetSubType" => "ENVIRONMENTAL" ,
"links" => [
{
"@type" => "Link" ,
"rel" => "contributionDefinition" ,
"uri" => "https://sandboxapi.deere.com/platform/contributionDefinitions/CONTRIBUTION_DEFINITION_ID"
}
]
}
)
John Deere の標準応答は、「コンテンツがありません」というメッセージを含む 204 HTTP ステータス コードです。このメソッドは、完全な Net::HTTP 応答を返します。
DELETE リクエストにはリソース パスのみが必要です。
client . delete ( '/assets/123123' )
John Deere の標準応答は、「コンテンツがありません」というメッセージを含む 204 HTTP ステータス コードです。このメソッドは、完全な Net::HTTP 応答を返します。
カスタム エラーは、クライアント使用時の問題を明確に特定するのに役立ちます。
:sandbox
または:production
です。GitHub でこの宝石にスターを付けてください。これは、開発者が他の Gem よりもこの Gem を見つけて選択するのに役立ちます。私たちの知る限り、他に積極的にメンテナンスされている John Deere gem はありません。
貢献する最も簡単な方法は次のとおりです。
vcr_setup
で事前に記録されている必要がありますvcr_setup
でも削除する必要があります。