Pada tulisan ini akan membahas posting file dari perangkat IOT berbasis ESP8266 ke google drive. Untuk menjalankan script pada pembahasan ini, anda perlu melakukan kustomisasi firmware nodemcu dengan memasukan beberapa module yang diperlukan sebagai berikut:
NodeMCU custom build by frightanic.com
branch: master
commit: 81ec3665cb5fe68eb8596612485cc206b65659c9
SSL: true
modules: cjson,crypto,dht,file,gpio,http,net,node,rtctime,sntp,tmr,uart,websocket,wifi
build built on: 2016-12-10 10:19
powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)
Langkah-langkah:
1. Aktifkan ke
Google API console
2. Klik pada Project, dan pilih Create Project
Gambar 1. Pembuatan Project Baru
3. Tambahkan Library Drive API
Gambar 2. Tambahkan Drive API
4. Aktifkan Drive API dengan klik pada Enable
Gambar 3. Google Drive API setelah di Enable
5. Tambahkan Credentials pada Project
Gambar 4. Setting Credentials
Pastikan bahwa Authorized redirect URLS adalah: https://developers.google.com/oauthplayground
6. Setting OAuth 2.0 consent screen
Gambar 5. OAuth 2.0 Consent Screen
7. Aktifkan ke
Google OAauth Playground
Gambar 6. OAuth 2.0 configuration
Check Use your own OAuth credentials, isikan OAuth Client ID, dan OAuth Client secret yang dapat diperoleh pada langkah sebelumnya (pada bagian Credentials pada Google Console API).
8. Tentukan authorize API scope, dalam hal ini adalah https://www.googleapis.com/auth/drive
Gambar 7. Tentukan Scope otorisasi yang diinginkan
9. Berikan otorisasi dengan klik pada Allow
Gambar 8. Memperbolehkan View dan Manage file pada Google Drive
10. Buat Refresh Token dan Access Token
Gambar 9. Membuat Refresh Token dan Access Token
11. Catat Authorization code, Client_Id, Client_Secret, Refresh Token
12. Lakukan koding berikut ini:
-- by Hendra Soewarno (0119067305) based on documentation
-- https://developers.google.com/identity/protocols/OAuth2WebServer
-- https://developers.google.com/drive/v2/reference/
authorization_code = "your authorization code"
client_id = "your client id"
client_secret = "your client secret"
refresh_token = "your refresh token"
access_token = nil
id = nil
title = "init.lua"
function encode_parameter(str)
return str:gsub('[^-%._~a-zA-Z0-9]', function(c)
return string.format("%%%02x", c:byte()):upper()
end)
end
function changeTitle()
local url = "https://www.googleapis.com/drive/v2/files/" .. id
local header = "Content-type: application/json\r\n" ..
"Authorization: Bearer " .. access_token .. "\r\n"
local payload = "{\"title\" : \"" .. title .. "\"}"
http.request(url,
"PATCH",
header,
payload,
function(code, data)
if (code ~= 200) then
print("Failed : HTTP error code : " .. code, data)
else
print("Succeed : " .. code, data)
end
end)
end
function uploadFile(callback)
local url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=media&convert=true"
local header = "Content-type: application/text\r\n" ..
"Authorization: Bearer " .. access_token .. "\r\n"
if file.open("init.lua", "r") then
payload = file.read(512)
print(payload)
file.close()
http.post(url,
header,
payload,
function(code, data)
if (code ~= 200) then
print("Failed : HTTP error code : " .. code, data)
else
print("Succeed : " .. code, data)
local t = cjson.decode(data)
id = t["id"]
node.task.post(changeTitle)
end
end)
end
end
function getAccessToken()
local url = "https://www.googleapis.com/oauth2/v4/token"
local payload =
"code=" .. encode_parameter(authorization_code) ..
"&redirect_uri=" .. encode_parameter("https://developers.google.com/oauthplayground") ..
"&client_id=" .. encode_parameter(client_id) ..
"&client_secret=" .. encode_parameter(client_secret) ..
"&scope=" ..
"&grant_type=authorization_code"
local header = "Content-type: application/x-www-form-urlencoded\r\n"
--"Content-length: " .. string.len(payload) .. "\r\n"
http.post(url,
header,
payload,
function(code, data)
if (code ~= 200) then
print("Failed : HTTP error code : " .. code, data)
else
print("Succeed : " .. code, data)
end
end)
end
function refreshAccessToken(callback)
local url = "https://www.googleapis.com/oauth2/v4/token"
local payload =
"client_secret=" .. encode_parameter(client_secret) ..
"&grant_type=refresh_token" ..
"&client_id=" .. encode_parameter(client_id) ..
"&refresh_token=" .. encode_parameter(refresh_token)
local header = "Content-type: application/x-www-form-urlencoded\r\n"
--"Content-length: " .. string.len(payload) .. "\r\n"
http.post(url,
header,
payload,
function(code, data)
if (code ~= 200) then
print("Failed : HTTP error code : " .. code, data)
else
print("Succeed : " .. code, data)
local t = cjson.decode(data)
access_token = t["access_token"]
node.task.post(uploadFile)
end
end)
end
--getAccessToken()
--refreshAccessToken()
refreshAccessToken()
Hasil Run:
Succeed : 200 {
"kind": "drive#file",
"id": "0B9b1RNrwu14WNmsyeV9vU1RHVEE",
"etag": "\"m64ksZC09nG4-fB1IRhNTNcF3vg/MTQ4MTk3ODM2OTYzMw\"",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE",
"webContentLink": "https://drive.google.com/uc?id=0B9b1RNrwu14WNmsyeV9vU1RHVEE&export=download",
"alternateLink": "https://drive.google.com/file/d/0B9b1RNrwu14WNmsyeV9vU1RHVEE/view?usp=drivesdk",
"embedLink": "https://drive.google.com/file/d/0B9b1RNrwu14WNmsyeV9vU1RHVEE/preview?usp=drivesdk",
"iconLink": "https://ssl.gstatic.com/docs/doclist/images/generic_app_icon_16.png",
"title": "Untitled",
"mimeType": "application/text",
"labels": {
"starred": false,
"hidden": false,
"trashed": false,
"restricted": false,
"viewed": true
},
"createdDate": "2016-12-17T12:39:29.633Z",
"modifiedDate": "2016-12-17T12:39:29.633Z",
"modifiedByMeDate": "2016-12-17T12:39:29.633Z",
"lastViewedByMeDate": "2016-12-17T12:39:29.633Z",
"markedViewedByMeDate": "1970-01-01T00:00:00.000Z",
"version": "95279",
"parents": [
{
"kind": "drive#parentReference",
"id": "0ANb1RNrwu14WUk9PVA",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE/parents/0ANb1RNrwu14WUk9PVA",
"parentLink": "https://www.googleapis.com/drive/v2/files/0ANb1RNrwu14WUk9PVA",
"isRoot": true
}
],
"downloadUrl": "https://doc-0s-0g-docs.googleusercontent.com/docs/securesc/6ef3a2thq1io4lguiv000fc3n8j157mi/hkbk6sp6ejiicbcbnmof5oobimi08o6e/1481976000000/14467718844153000671/14467718844153000671/0B9b1RNrwu14WNmsyeV9vU1RHVEE?e=download&gd=true",
"userPermission": {
"kind": "drive#permission",
"etag": "\"m64ksZC09nG4-fB1IRhNTNcF3vg/oL4ijP0n8GxZ7JDTDMVZhQFn1h0\"",
"id": "me",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE/permissions/me",
"role": "owner",
"type": "user"
},
"originalFilename": "Untitled",
"fileExtension": "",
"md5Checksum": "74339827856ad32167b81a9b69c6a369",
"fileSize": "512",
"quotaBytesUsed": "512",
"ownerNames": [
"Hendra Soewarno"
],
"owners": [
{
"kind": "drive#user",
"displayName": "Hendra Soewarno",
"picture": {
"url": "https://lh3.googleusercontent.com/-zT-K5R2Kl7c/AAAAAAAAAAI/AAAAAAAAAM0/rk_CEnm7hMA/s64/photo.jpg"
},
"isAuthenticatedUser": true,
"permissionId": "14467718844153000671",
"emailAddress": "hendra.soewarno@gmail.com"
}
],
"lastModifyingUserName": "Hendra Soewarno",
"lastModifyingUser": {
"kind": "drive#user",
"displayName": "Hendra Soewarno",
"picture": {
"url": "https://lh3.googleusercontent.com/-zT-K5R2Kl7c/AAAAAAAAAAI/AAAAAAAAAM0/rk_CEnm7hMA/s64/photo.jpg"
},
"isAuthenticatedUser": true,
"permissionId": "14467718844153000671",
"emailAddress": "hendra.soewarno@gmail.com"
},
"editable": true,
"copyable": true,
"writersCanShare": true,
"shared": false,
"explicitlyTrashed": false,
"appDataContents": false,
"headRevisionId": "0B9b1RNrwu14WK01kUUtOQTdTVlljNTlhMjN5Zml5MVFsMjNRPQ",
"spaces": [
"drive"
]
}
Succeed : 200 {
"kind": "drive#file",
"id": "0B9b1RNrwu14WNmsyeV9vU1RHVEE",
"etag": "\"m64ksZC09nG4-fB1IRhNTNcF3vg/MTQ4MTk3ODM3MTYwNA\"",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE",
"webContentLink": "https://drive.google.com/uc?id=0B9b1RNrwu14WNmsyeV9vU1RHVEE&export=download",
"alternateLink": "https://drive.google.com/file/d/0B9b1RNrwu14WNmsyeV9vU1RHVEE/view?usp=drivesdk",
"embedLink": "https://drive.google.com/file/d/0B9b1RNrwu14WNmsyeV9vU1RHVEE/preview?usp=drivesdk",
"iconLink": "https://ssl.gstatic.com/docs/doclist/images/generic_app_icon_16.png",
"title": "init.lua",
"mimeType": "application/text",
"labels": {
"starred": false,
"hidden": false,
"trashed": false,
"restricted": false,
"viewed": true
},
"createdDate": "2016-12-17T12:39:29.633Z",
"modifiedDate": "2016-12-17T12:39:31.604Z",
"modifiedByMeDate": "2016-12-17T12:39:31.604Z",
"lastViewedByMeDate": "2016-12-17T12:39:31.604Z",
"markedViewedByMeDate": "1970-01-01T00:00:00.000Z",
"version": "95281",
"parents": [
{
"kind": "drive#parentReference",
"id": "0ANb1RNrwu14WUk9PVA",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE/parents/0ANb1RNrwu14WUk9PVA",
"parentLink": "https://www.googleapis.com/drive/v2/files/0ANb1RNrwu14WUk9PVA",
"isRoot": true
}
],
"downloadUrl": "https://doc-0s-0g-docs.googleusercontent.com/docs/securesc/6ef3a2thq1io4lguiv000fc3n8j157mi/hkbk6sp6ejiicbcbnmof5oobimi08o6e/1481976000000/14467718844153000671/14467718844153000671/0B9b1RNrwu14WNmsyeV9vU1RHVEE?e=download&gd=true",
"userPermission": {
"kind": "drive#permission",
"etag": "\"m64ksZC09nG4-fB1IRhNTNcF3vg/oL4ijP0n8GxZ7JDTDMVZhQFn1h0\"",
"id": "me",
"selfLink": "https://www.googleapis.com/drive/v2/files/0B9b1RNrwu14WNmsyeV9vU1RHVEE/permissions/me",
"role": "owner",
"type": "user"
},
"originalFilename": "Untitled",
"fileExtension": "lua",
"md5Checksum": "74339827856ad32167b81a9b69c6a369",
"fileSize": "512",
"quotaBytesUsed": "512",
"ownerNames": [
"Hendra Soewarno"
],
"owners": [
{
"kind": "drive#user",
"displayName": "Hendra Soewarno",
"picture": {
"url": "https://lh3.googleusercontent.com/-zT-K5R2Kl7c/AAAAAAAAAAI/AAAAAAAAAM0/rk_CEnm7hMA/s64/photo.jpg"
},
"isAuthenticatedUser": true,
"permissionId": "14467718844153000671",
"emailAddress": "hendra.soewarno@gmail.com"
}
],
"lastModifyingUserName": "Hendra Soewarno",
"lastModifyingUser": {
"kind": "drive#user",
"displayName": "Hendra Soewarno",
"picture": {
"url": "https://lh3.googleusercontent.com/-zT-K5R2Kl7c/AAAAAAAAAAI/AAAAAAAAAM0/rk_CEnm7hMA/s64/photo.jpg"
},
"isAuthenticatedUser": true,
"permissionId": "14467718844153000671",
"emailAddress": "hendra.soewarno@gmail.com"
},
"editable": true,
"copyable": true,
"writersCanShare": true,
"shared": false,
"explicitlyTrashed": false,
"appDataContents": false,
"headRevisionId": "0B9b1RNrwu14WK01kUUtOQTdTVlljNTlhMjN5Zml5MVFsMjNRPQ",
"spaces": [
"drive"
]
}
Trouble Shooting:
> Failed : HTTP error code : 401 {
"error": "invalid_client",
"error_description": "The OAuth client was not found."
Pastikan client_id telah benar
> Failed : HTTP error code : 401 {
"error": "invalid_client",
"error_description": "Unauthorized"
}
Pastikan client_secret telah benar
> Failed : HTTP error code : 400 {
"error": "invalid_grant",
"error_description": "Bad Request"
}
Pastikan refresh_token telah benar