該用戶端可讓您連接 MyJohnDeere API,而無需編寫自己的 oAuth 流程、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 添加到您的 gemfile 中:
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 )
實際上,當使用者返回時,您可能需要重新實例化授權對象,並且這不會出現問題:
# 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 )
在網頁應用程式中,您希望用戶不必複製/貼上驗證碼。所以你可以傳入一個 :oauth_callback url。當使用者透過 John Deere 授權您的應用程式時,他們將被重定向到您提供的 url,參數「oauth_verifier」包含驗證碼,因此使用者無需提供驗證碼。
# 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 Module 包含的所有方法之外,貢獻產品集合還支援以下方法:
個人貢獻產品支援以下方法和關聯:
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 狀態碼,並附有訊息「No Content」。此方法傳回完整的 Net::HTTP 回應。
DELETE 請求僅需要資源路徑。
client . delete ( '/assets/123123' )
John Deere 的標準回應是 204 HTTP 狀態碼,並附有訊息「No Content」。此方法傳回完整的 Net::HTTP 回應。
自訂錯誤有助於清楚地識別使用客戶端時出現的問題:
:sandbox
或:production
。在 GitHub 上為這顆寶石加註星標。它可以幫助開發人員找到並選擇這個寶石,而不是其他可能存在的寶石。據我們所知,沒有其他約翰迪爾寶石正在積極維護。
最簡單的貢獻方式是:
vcr_setup
中vcr_setup
中。