2017年1月24日火曜日

バケットの一覧 +VB.net

現在のバケットの一覧を取得

バケットの一覧を取得するにはDataManagementAPIのGET Bucketを使います。前回のプロジェクトを利用して、WebFormでバケットの一覧を取得してみます。

WebFormの追加

WebFormを追加して、下の図のようにサーバーコントロールを配置します。
サンプルのWebForm

サンプルコード


以下はバケットの一覧を取得するサンプルコードです。ポイントは「apiの戻り値のJSONの配列を処理する部分です。レスポンスをNewtonsoft.Json.Linq.JArray型に変換して情報を取り出します。

Public Class WebForm3
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        '**********************************
        '     アクセストークンを取得
        '**********************************
    'この部分は前回の記事を参照してください。

        Dim acToken As String = mdlUtils.GetToken("bucket:read")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを取得
        '**********************************

        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.GET

            'ヘッダー
            .AddHeader("Authorization", "Bearer " + acToken)

        End With

        '送信
        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '200OKの場合

            Dim responseString As String = result.Content
            'Newtonsont.JsonのJSON解読メソッドを使うと便利
            'まず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            '"items"を取得しjArrayオブジェクトとする
            Dim itemArray As Newtonsoft.Json.Linq.JArray = jsonObj("items")
            '配列を走査する
            For Each item As Newtonsoft.Json.Linq.JObject In itemArray
                'バケットキー
                Dim strBucketKey As String = item("bucketKey")
                '作成した日付(ミリセカンド)
                Dim strCreatedDate As String = item("createdDate")
                'ポリシーキー
                Dim strPolicyKey As String = item("policyKey")

                'タイムスタンプから日付へ変換
                Dim intTimeStamp As Int64 = Int64.Parse(strCreatedDate)
                Dim dtCreateDate As DateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(intTimeStamp)

                'リストボックスのアイテムを追加する
                lbxBuckets.Items.Add(New ListItem(strBucketKey + " / 作成日時 : " + dtCreateDate.ToLocalTime.ToString + " / ポリシーキー : " + strPolicyKey, strBucketKey))

            Next
            lblStatus.Text = itemArray.Count.ToString + "個のバケットが見つかりました。"
        Else
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            lblStatus.Text = "取得に失敗しました。" + vbTab + jsonObj("reason")


        End If
    End Sub
End Class

実行する

実行すると以下のようになります。
現在のバケットの一覧

2017年1月19日木曜日

バケット作成 + VB.net

バケットを作成する

バケットを作成するにはまずbucket:createスコープでアクセストークンを取得し、ポリシーキー(データの保持期間)とバケット名(bucketId)を決めてPOSTで取得するという手順でした。これをvb.netで実装してみます。

アクセストークン取得モジュール

アクセストークンは様々な場面で必要なので、モジュールで関数にしておきます。

プロジェクトにモジュールを追加して「mdlUtils.vb」とします。以下はコードサンプルです。

Imports System.Net


Module mdlUtils

    Public Const CLIENTID As String = "自分のクライアントID"
    Public Const CLIENTSECRET As String = "自分のクライアントシークレット"
    Private ENDPOINT As String = "https://developer.api.autodesk.com"-

    ''' <summary>
    ''' 目的に応じたアクセストークンを取得する
    ''' </summary>
    ''' <param name="scopeString">スコープ</param>
    ''' <returns></returns>
    Public Function GetToken(ByVal scopeString As String) As String

        'RestSharpでクライアントを作成
        Dim _client As New RestSharp.RestClient(ENDPOINT)
        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "authentication/v1/authenticate"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/x-www-form-urlencoded")

            'ボディ
            .AddParameter("client_id", CLIENTID)
            .AddParameter("client_secret", CLIENTSECRET)
            .AddParameter("grant_type", "client_credentials")

            'スコープ
            .AddParameter("scope", scopeString)
        End With

        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            'このjsonは以下の形式となる
            '{
            '  "token_type": "Bearer",
            '  "expires_in": 1799,
            '  "access_token": "Ff387cyQXw1elOT3nldiFIKBqDOs"
            '}
            Dim responseString As String = result.Content
            'ここからaccess_tokenの値だけを取り出す

            '文字列を操作しても可能だが、Newtonsont.JsonのJSON解読メソッドを使うと便利です。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)

            'アクセストークンをオブジェクトに引数を与えて取得します
            Dim acToken As String = jsonObj("access_token")

            'Label1の表示を変更
            Return acToken

        Else
            '失敗した場合
            Return ""
        End If
    End Function
End Module

WebFormの追加


WebFormを一つ追加して、下の図のようにリストボックスとテキストボックス、ラベルを追加します。
WebFormにコントロールを追加

ボタンアクションを追加

btnCreateBucketをダブルクリックして、コードを追加すします。RestSharpで送信するデータは今回はJSONです。

Public Class WebForm2
    Inherits System.Web.UI.Page

    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles btnCreateBucket.Click

        '**********************************
        '     アクセストークンを取得
        '**********************************

        Dim acToken As String = mdlUtils.GetToken("bucket:create")
        If acToken = "" Then
            Exit Sub
        End If

        '**********************************
        '     バケットを作成
        '**********************************


        'RestSharpでクライアントを作成
        Dim url As String = "https://developer.api.autodesk.com"
        Dim _client As New RestSharp.RestClient(url)

        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "oss/v2/buckets"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/json")
            .AddHeader("Authorization", "Bearer " + acToken)

            'ボディ(JSON形式で送る場合には匿名型を使用します。)
            '{
            '     "bucketKey":"mybucket",
            '     "policyKey":"transient"
            '}
            .AddJsonBody(New With {
                         Key .bucketKey = tbxBucketKey.Text,
                         Key .policyKey = lbxPolicy.SelectedValue
                         })
        End With

        'POSTする
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = Net.HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            '{
            '  "bucketKey":"apptestbucket",
            '  "bucketOwner":"RlKfGlAbb7N8VJwLllOvpfonB1Ex52qG",
            '  "createdDate":1463785698600,
            '  "permissions":[
            '    {
            '      "authId":"RlKffonB1Ex52GlAbb7N8VJwLllOvpqG",
            '      "access":"full"
            '    }
            '  ],
            '  "policyKey":"transient"
            '}
            Dim responseString As String = result.Content
            '文字列を操作しても可能だが、Newtonsont.JsonのJSON解読メソッドを使うと便利。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            'バケットキーを取り出す
            Dim bucketKeyString As String = jsonObj("bucketKey")
            'ステータスに出力
            lblStatus.Text = bucketKeyString + "の作成に成功しました。"

        Else
            'エラーの場合は理由を示すJSONが返ってくる
            '            {
            '  "reason":"Valid field 'bucketKey' must be of the form  [-_.a-z0-9]{3,128}"
            '}
            Dim responseString As String = result.Content
            Dim jsonObj As Object = Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)
            Dim reasonString As String = jsonObj("reason")
            lblStatus.Text = "バケットの作成に失敗しました。理由:" + reasonString

        End If
    End Sub
End Class

RestSharpでJSONを送る

RestSharpでBODYにJSON形式のデータをセットする場合は、赤字で示した部分のように.AddJsonBodyの引数に匿名型のオブジェクトをセットします。

実行してみる


ビルドして実行してみます。
ブラウザで実行
データ保存期間とバケットキーを指定して「バケット作成」を押すと
バケットが作成された
もう一度押すとすでに同じ名前のバケットがあることがわかります。
同じ名前のバケットは作成できない
バケットの名前に大文字のアルファベットを使うと、同じくエラーになります。
文字の制約のエラー


2017年1月15日日曜日

アクセストークン + VB.net

サーバーサイドでアクセストークンを取得する

ここまでで基本的な知識は手に入りました。ここからはASP.NET WebFormを使って、FORGEに取り組んでみます。ビューアのチュートリアルでは、JavaScriptに直接

  • オブジェクトID
  • アクセストークン

を書き込んでいました。また、アクセストークンを取得するには
  • クライアントID
  • クライアントシークレット
が必要です。しかし、クライアントサイドのJavaScriptはブラウザーの開発者ツールを使えば「もろばれ」状態なので、大事な情報をクライアントサイドに置くわけにはいきません。

今回はWebFormを使って、アクセストークンを取得してみます。Webフォームのアクションはサーバーサイドで実行されるので、大事な情報をクライアントサイドに置かなくて済みます。

まずはVisual Studioで新しいWebFormプロジェクトを作成します。

RestSharpを導入する

アクセストークンを取得するにはRESTを使って、交信を行う必要があることがわかりました。VBでこれを実装するのはなかなか骨が折れそうですが、RestSharpを使うことでこの難関を切り抜けることができます。プロジェクトにRestSharpを組み込みます。

(1) [ツール]-[NuGetパッケージマネージャ]-[パッケージマネージャコンソール]
(2) パッケージマネージャコンソールで
  PM> Install-Package RestSharp

WebFormを追加


(1) [プロジェクト]-[新しい項目の追加]
(2) [Webフォーム]を選択して[追加]
(3) 画面左下の[並べて表示]をクリック
(4) ボタンとラベルを追加

ボタンのアクションを追加

(1) 追加したボタンをダブルクリックして、コードを表示する
(2) コードは以下のようになります。

Imports System.Net

Public Class WebForm1
    Inherits System.Web.UI.Page


    Protected Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click

        'ラベルをクリア
        Label1.Text = ""

        'クライアントIDとクライアントシークレット
        Dim client_id As String = "自分のクライアントIDで置き換え"
        Dim client_secret As String = "自分のクラインとシークレットで置き換え"

        'URL
        Dim strClient As String = "https://developer.api.autodesk.com"

        'RestSharpでクライアントを作成
        Dim _client As New RestSharp.RestClient(strClient)
        'RestSharpでリクエストを作成
        Dim authReq As New RestSharp.RestRequest()
        With authReq
            .Resource = "authentication/v1/authenticate"

            'メソッド
            .Method = RestSharp.Method.POST

            'ヘッダー
            .AddHeader("Content-Type", "application/x-www-form-urlencoded")

            'ボディ
            .AddParameter("client_id", client_id)
            .AddParameter("client_secret", client_secret)
            .AddParameter("grant_type", "client_credentials")

            'スコープはとりあえずdata:read
            .AddParameter("scope", "data:read")
        End With

        'リクエストを送信
        Dim result As RestSharp.IRestResponse = _client.Execute(authReq)

        If result.StatusCode = HttpStatusCode.OK Then

            '結果(json形式の結果が文字列で返ってくる)
            'このjsonは以下の形式となる
            '{
            '  "token_type": "Bearer",
            '  "expires_in": 1799,
            '  "access_token": "Ff387cyQXw1elOT3nldiFIKBqDOs"
            '}
            Dim responseString As String = result.Content
            'ここからaccess_tokenの値だけを取り出す

            '文字列を操作しても可能だが、Newtonsont.Jsonの解読メソッドを使うと便利です。
            '使い方はまず以下の構文でオブジェクトを作成します。
            Dim jsonObj As Object =  Newtonsoft.Json.JsonConvert.DeserializeObject(responseString)

            'アクセストークンをオブジェクトに引数を与えて取得します
            Dim acToken As String = jsonObj("access_token")

            'Label1の表示を変更
            Label1.Text = acToken

        Else
            '失敗した場合
            Label1.Text = "アクセストークンを取得できませんでした。"

        End If

    End Sub
End Class

ポイントはRestSharpのリクエストの作り方と、戻り値のJSONからaccess_tokenの値と取り出す部分です。Newtonsoft.Jsonは規定でASP.netに組み込まれているので、特に参照を操作する必要はありません。

実行してみる


ビルドして実行してみます。最初の画面はこうです。
ボタンを押してみましょう
ボタンを押すと
アクセストークンが取得できた!
アクセストークンが取得できました。
結構少ないコードで、安全にアクセストークンを取得できることがわかりました。

2017年1月6日金曜日

ビューアで表示する(2)~表示ビューの変更

3Dビューが表示されたのは偶然だった?

前回無事ビューアで表示できたので、今回はチュートリアルのStep3を解明してみます。考えてみれば、Revitのデータをアップロードして、2dと3dのビューを表示用に変換するように、命令をしたわけですから、前回のビューアで表示するように指定したビューには複数のビューがあったはずです。にもかかわらず、3Dビューが表示されたのは「単なる偶然」だったのですね。
運よく?表示された3Dビュー
Step3では画面上部に「Nextボタン」を表示して、クリックするごとに表示可能ビューを入れ変えるようにしてみます。

Step3 をフォローする

ボタンをつくる

まずビューアの上にボタンを作成します。これはHTMLファイルの<div>で区切られたビューアの
<div id="MyViewerDiv"></div>
の行の直後に
<button id="MyNextButton" onClick="loadNextModel()">Next!</button>
とボタンタグを加えます。
ボタンのIDはMyNextButtonで、onClickイベントにloadNextModel()関数を指定しています。
次にボタンのスタイルを指定するために、<head>~</head>内の<style>~</style>タグのなかに
#MyNextButton {
        position: absolute;
        top: 5px;
        left: 5px;
        z-index: 1;
        font-size: 40px;
        cursor: pointer;
    }
と付け加えます。従いまして、Visual Studioとしては下の図のようになります。
ボタンのスタイルとタグを追加

onClickイベント関数の追加

ボタンをクリックしたときに処理される関数を記述します。とりあえず
function loadNextModel() {
    console.log('TODO: Load Next Model');
}
を追加するのですが、問題はどこに追加するのか?ということです。HTMLファイルにJavaScriptを記述する場合、<script>~</script>タグの間に記述するので、とりあえず、下のほうの</script>の直上に入れておきます。
</script>の直上にいれる

グローバル変数の追加

すでに<script>タグの直後に var viewer; というグローバル変数が宣言されていますが、これにあと三つのグローバル変数を追加します。

        var lmvDoc;
        var viewables;
        var indexViewable;

したがって、以下の図の位置に入ります。
グローバル変数を追加

ロード成功時の関数(onDocumentLoadSuccess)の変更

既存のonDocumentLoadSuccess()を以下の内容で書き換えます。
function onDocumentLoadSuccess(doc) {

    // docにある2Dおよび3Dの表示可能なビューの配列をグローバル変数viewablesに格納
    viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), {'type':'geometry'}, true);
  // 表示可能なビューがなければ終了
    if (viewables.length === 0) {
        console.error('Document contains no viewables.');
        return;
    }

    // ビューアを<div id=MyViewerDiv>に作成しグローバル変数viewerに格納
    var viewerDiv = document.getElementById('MyViewerDiv');
    viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
    var errorCode = viewer.start();

    // ビューアの初期化時のエラーを確認する
    if (errorCode) {
        console.error('viewer.start() error - errorCode:' + errorCode);
        return;
    }

    // グローバル変数indexViewableを0に初期化し、グローバル偏すlmvDocにdocを格納.
    indexViewable = 0;
    lmvDoc = doc;

    // loadModel関数を呼び出して、ビューアにモデルをロードする
    loadModel();
}


働きはコメントをつけておきましたが、そもそもなぜonDocumentLoadSuccessに引数(doc)があるのかがわかりませんね。この関数自体は、Document.Load関数の第二引数の「onSuccessCallback」なのですが、これが引数をとるなどという記述は、HELPにはどこにもないですから。

これらの謎は後日調べて報告します。

さて、この関数の最後にあるloadModel()を、onDocumentLoadSuccess関数の後に記入します。
function loadModel() {
    var initialViewable = viewables[indexViewable];
    var svfUrl = lmvDoc.getViewablePath(initialViewable);
    var modelOptions = {
        sharedPropertyDbPath: lmvDoc.getPropertyDbPath()
    };
    viewer.loadModel(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
}

そして最後に、onClickイベント関数 loadModel を次の関数で置き換えます。
function loadNextModel() {

    viewer.tearDown();
    viewer.setUp(viewer.config);

    // インデックスを+1して次のビューをロード。最後まで行ったら0に戻る
    indexViewable = (indexViewable + 1) % viewables.length;
    loadModel();
}

これで実行してみると、まず下の図のように3Dビューが表示されます。
左上のNEXTボタンを押す
が、左上に表示された[Next!]ボタンをクリックすると
2D図面が表示される
2D図面が表示されます。押し続けると次々と図面が表示されて、また最初の3Dビューに戻ります。

さて、関数とAPI Referenceと見比べてみますと、onDocumentLoadSuccess関数のviewerのインスタンスを作成する「Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);」は、リファレンスには見当たりません。代わりに

というnew関数がありますので、この部分を

viewer = new Autodesk.Viewing.Viewer3D(viewerDiv);

と書き換えて実行してみます。実行後は[F5]などで、キャッシュを除去してください。これでも問題なく動くはずです。


What's next?


おお!無事に表示されたぞ。と喜んでいると一番下のWhat's next?の段落に

ここに紹介されているコードの多くは、物事を稼働させるために必要な定型文です。 ViewingApplicationオブジェクトを使用すると、その一部を簡略化できます。

とあります。ここにあるのはbioplate(定型文・決まり文句)なので、次のチュートリアルをやってみましょう、と言っております。

さてさて、「ViewingApplication」とはどのようなものなのでしょうか?

でも、ここらでチュートリアルで習ったことを使って、自分でWebアプリケーションを作ってみようではないですか!