はつねの日記

Kinect, Windows 10 UWP, Windows Azure, IoT, 電子工作

第12話

「すべてのローカル物理サーバーを発注する前に消し去りたい。すべての自社サーバールーム、データセンタの全ての自社サーバーを、この手で」
「神様でも何でもいい」
「今日まで物理サーバーと戦ってきたみんなを、希望を信じたインフラエンジニアを、私は泣かせたくない。最後まで笑顔でいてほしい」
「それを邪魔するルールなんて、壊してみせる、変えてみせる」
「これが私の祈り、私の願い」
「さあ!叶えてよ、デプロイ王子!!」

Developers Summit 2015のセンサー&デバイス枠の中で登壇します。

2015/02/19(木)にDevelopers Summit 2015に登壇します。

----

【19-A-7】センサー&デバイス大集合
http://event.shoeisha.jp/devsumi/20150219/session/640

『センサー&クラウドを体験しよう』 初音 玲〔TMCN〕氏
各種センサーおよびデバイスからのデータをMicrosoft Azureで収集して可視化するための勘所を実演を中心にご紹介します。

----

私の他にも一緒に登壇する方が紹介する内容は面白い物ばかりなのでぜひ目黒雅叙園にきてください!

Microsoft Azure Mobile ServicesでFacebookに投稿する

Microsoft Azrue Mobile Servicesでは、Microsoftアカウント、FacebookGoogleTwitterなどを認証寄稿として利用できます。

Facebook認証を選択した場合、そこで取得したアクセストークンを使ってカスタムAPIからFacebookに自動投稿することができます。

AEDオープンデータプラットフォームにてbetaテスト中の更新機能もこの機能を使って位置情報を登録、更新したときにFacebookに自動投稿をして(あとは、SendGrid使ってメールも飛ばして)います。このように操作履歴をSNSに投稿することで、位置情報の収集に貢献している人の見える化、そして、いたずらの発見と戻しがスムーズに行えるように考慮されています。

つまり、Facebookの自動投稿をクライアント側ではなく、Mobile Services側に実装することで投稿を回避するような迂回ができなくなるわけです。

 

Facebookにアプリを登録

Facebookを認証機構として使う場合は次のようにします。

image

Facebookに開発者登録を行い、アプリ登録を行います。

Microsoft Azrue Mobile Services側でFacebook認証を行うのならば、ここでは「ウェブサイト」として登録してMobile Servicesに作成したサービスのURLを登録します。

FacebookアプリをMobile Servicesに登録

Facebookにアプリを登録するとアプリケーションIDとアプリのシークレットキーが生成されますので、これをMobile Servicesに登録します。

image

カスタムAPIにアクセス制限をかける

image

アクセス制限をかけたいカスタムAPIメソッドに対して「認証されたユーザーのみ」を設定します。

 

この設定によりFacebook認証を行わずにGETしようとすると次のようなエラーが発生します。

image

 

認証を通してアクセス制限がかかったカスタムAPIメソッドを実行する

Windows Azrue Mobile Services側でFacebook認証を行うためには、Mobile Services SDKを使ってクライアント側で次のコードを実行します。

await mobileService.LoginAsync(MobileServiceAuthenticationProvider.Facebook);

 

このコードを実行すると自動的にFacebookのログイン画面がSDKにより表示されます。

image

 

FacebookのIDとパスワードを入れて[ログイン]をクリックして成功すれば、アクセス制限のかかったカスタムAPIにアクセスできます。

カスタムAPI

それでは最後にFacebookに投稿するためのカスタムAPIについてみていきましょう。

exports.post = function(request, response) {
    PostFacebook(request,'UPDATE',response);
};

function PostFacebook(request,mode,response,results)
{
    var user = request.user;
    var LocationName = request.body.LocationName;
    var FacilityPlace = request.body.FacilityPlace;
    var VenueId = request.body.VenueId
    user.getIdentities({
        success: function(identities) {
            if (identities.facebook) {
                var req = require('request').defaults({strictSSL: true});
                var fbAccessToken = identities.facebook.accessToken;
                var providerId = user.userId.substring(user.userId.indexOf(':') + 1);;
                var userName = "";
                var userLink = "";
                /* get user info */
                { 
                    var uri = 'https://graph.facebook.com/' + providerId + '?access_token=' + fbAccessToken;
                    req(uri, {json: true},function(err,resp,body) {
                        if (err) {
                            console.error('Error sending data to FB Graph API: ', err);
                            response.send(statusCodes.INTERNAL_SERVER_ERROR);
                        } else {
                            if (resp.statusCode !== 200)
                            {
                                console.error(JSON.stringify(body));
                                response.send(statusCodes.INTERNAL_SERVER_ERROR);
                            } else {
                                userName = body.name;
                                userLink = body.link;
                                /* post feed for Facebook page */
                                if (userName.length > 0)
                                {
                                    var message = "posted:" + userName + " " + userLink + "\n"; 
                                    message = message + mode + ":" + LocationName;
                                    if (FacilityPlace) {
                                        message = message + " " + FacilityPlace + "\n";
                                    }
                                    message = message + "\n";
                                    if (VenueId) {
                                        message = message + " https://ja.foursquare.com/v/" + VenueId;  
                                    }  
                                    var uri = 'https://graph.facebook.com/614536118659766/feed';
                                    req.post(uri, {
                                        form: {
                                            message: message,
                                            access_token: fbAccessToken
                                        },
                                        json: true
                                    }, function(err,resp,body) {
                                        if (err) {
                                            console.error('Error sending data to FB Graph API: ', err);
                                            response.send(statusCodes.INTERNAL_SERVER_ERROR);
                                        } else {
                                            /*if (resp.statusCode !== 200 && resp.statusCode !== 506)
                                            {
                                                if (mode == "INSERT")
                                                {
                                                    InsertData(request,response);    
                                                } else {
                                                    UpdateData(request,response);    
                                                }
                                                console.error(JSON.stringify(body));
                                                response.send(statusCodes.INTERNAL_SERVER_ERROR);
                                            } else {
                                            }
                                            */
                                            if (mode == "INSERT")
                                            {
                                                InsertData(request,response);    
                                            } else {
                                                UpdateData(request,response);    
                                            }
                                        }
                                    });
                                } else {
                                    response.send(statusCodes.BAD_REQUEST);
                                }
                            }
                        }
                    });
                }
            }
        },
        error : function()
        {
            response.send(statusCodes.INTERNAL_SERVER_ERROR);
        }
    });
}

 

このカスタムAPIを呼び出せば、更新時には次のような投稿が自動的にFacebookページに送られます。image

以上

英語が不得意でもWOVN.ioを使って、たった5クリックでサイトを英語化しよう

日本語サイトを英語化するのは、静的なサイトだとしても難しいものです。

今回、WOVN.ioというサービスを教えて頂いたので試してみたところ思った以上によかったので紹介します。

 

https://wovn.io/

image

 

どのような感じで翻訳されるかは、このページの右下にある[日本語]を[英語]にしてみましょう。

image

 

中国語も対応できているので、台湾の人たちに伝えたいときもいい感じです。

image

 

それでは、AEDオープンデータのページを英語化してみましょう。

 

Click 1:サインアップまたはログイン

まずは、WOVN.ioに会員登録します。この登録自体は無料です。

image

Click2:該当ページを追加する

登録またはログインするとダッシュボードが表示されるので[+New Page]をクリックします。

image

Click3:ページを登録する

「Add a New Page!」ダイアログが表示されたら、URL「http://hatsunejournal.jp/w8/AEDOpendata/」を入力します。

image

URLを入れるとページタイトルやLanguageは自動的にhtmlの内容から取得されます。このあたりはちゃんとHTML定義しているかによります。

なので、URLをいれたら[Begin!]をクリックするだけで済みます。

 

で、余りにもよくできているのでさっととおりすぎてしまいますが、「Target Language」のところがドロップダウンになっています。

image

無料版では「English」から選択肢は帰らえませんが他の言語も実装されています。

Click4:翻訳方法を選ぶ

URLで指定されたページからテキスト部分を抽出して一覧が作成されます。文章のセンテンス数が多いとこの一覧を作るのに多少時間が必要ですので、[Machine Translate]ボタンが有効になるまで待ちます。

image

[Pro Translate]は有償版の機能で人による翻訳になり、[Machine Translate]ボタンは、無償版でも使えるBing Translateを使った機械翻訳になります。

なお翻訳結果は、日本語の右側の欄に表示される翻訳後のテキストを編集できます。このあたりは、Visual StudioのAddInにある多言語アプリツールキットと同じような感覚です。

Click5:Publish & Save

image

最後は[Publish & Save]をクリックします。

これでheadセクションに書くスクリプトが表示されるので、それを該当ページの定義の中にコピー&ペーストすれば完成です。

感想

とても簡単に英語化できます。今回は、いわゆるランディングページに適用してみましたが、とても相性が良いと感じました。

もしかしたら話し言葉中心であったり、一般的なブログだと翻訳後の手助けが必要でしょう。

しかし、このプロダクトのすごいところは翻訳後のテキストを元のサイトに1行だけ定義を加えるだけで簡単に表示できることです。

imageimage

そして、見た目も変わらず(このあたりはHTMLの定義にもよりますが)という素晴らしいものです。

みなさんもぜひ利用してみてください。

Mobile Serviceで自動的に列を追加させない設定

Microsoft Azure Mobile Servicesはコードファーストなのでデータ更新時にDB上にない列を指定すると自動的に列を追加してくれます。

これはこれで便利なのですが、コード側が間違えていて意図しない列が追加されてしまうという事も考えられるので、保存項目の変更がないときは自動的に列を追加しないように設定しておくのがよいでしょう。

 

設定は、Azureの管理ポータルに入って、設定したいMobile Serviceを選択してから構成メニューに移動すると「動的スキーマー」という項目があるので、これを「オフ」にすれば列が追加されません。

image

動的スキーマーのヒントにも「アプリケーションが稼働状態になったらオフにすることを検討してください。」とありますね。

 

これをオフにできることを知っているとインフラ屋さん的にもMobile Serviceを使う事にOKだしやすいですね。

AEDオープンデータプラットフォームのFoursquare連携機能を実証実験中

AEDオープンデータプラットフォームの先行機能であるFoursquare連携を会津若松市AEDに対して実証実験展開中です。
まだ全件登録し終わっていませんが、ぜひ、お近くのAEDの写真をとってチェックインして貰えたらと思います。

https://ja.foursquare.com/explore?mode=url&near=%E4%BC%9A%E6%B4%A5%E8%8B%A5%E6%9D%BE%E5%B8%82&q=AED

 

AEDの位置情報をオープンデータとして公開したいと考えている担当者の方へ

AEDの位置情報をオープンデータとして公開したいと考えている行政担当者の方は、是非ともAEDオープンデータプラットフォームへの掲載を検討していただければ幸いです。

 

AEDオープンデータプラットフォームであれば、いま、お手元にあるAED位置情報を初期投資を抑えて公開することができます。
そして、データとして出すところではなく活用するところにシステム化費用を投資してほしいと思います。

 

AEDオープンデータプラットフォームは、誰でも無償でAED情報の検索できるプラットフォームです。
また、AED情報の登録については、Facebook認証および変更が行われた場合にはFacebookの「https://www.facebook.com/AEDSearch」に自動投稿が行われるので変更追跡が可能です。なお、登録のAPIは現時点ではWindowsストアアプリである「AED検索」のみに限定して提供していますが、androidiOSへの移植も検討しております。
android版やiOS版への展開をお手伝い頂ける方も募集しております。

 

本ソリューションのマネタイズは、AEDオープンデータプラットフォームではなく、そのデータを使った関連アプリにて行いますので、AEDオープンデータプラットフォーム自体の利用は将来にわたっても無償ですし、その利用方法についても特に制限を設けることはありません。

 

AEDオープンデータプラットフォームは、パブリッククラウドを活用したWebサービスでHTTP-GETによりJSON形式で以下のデータを取得できます。

・指定した都道府県単位のAED情報一覧
・指定した市町村区単位のAED情報一覧
・指定した緯度経度の直近AED情報
・指定した緯度経度の指定範囲内のAED情報一覧
・指定したIDのAED情報

指定方法や返却されるJSONデータ形式は、 http://hatsunejournal.jp/w8/aedSearch/ を参照ください。


もし、お手元にAED情報がExcelなどでまとまっているのであれば、そのデータをぜひご提供ください。
施設名と住所があれば1週間、WGS84形式(google mapで表示できる形式)の緯度経度があれば、最速1晩でデータ投入可能です。
繰り返しになりますが、行政担当者の方はぜひご検討いただき、費用をかけずに住民サービスの向上を図っていただけたらと思います。

 

ご参考までに、AEDオープンデータプラットフォームを使って、第三者が作成したWEBサイトをご紹介します。

http://aedmap.catchball.co/

このサイトではAEDデータの管理を一切行わず、すべてAEDオープンデータプラットフォームから情報を取得しています。
処理速度なども含めて、行政公式ホームページからAEDオープンデータプラットフォームを利用したときの雰囲気を感じていただければ幸いです。


行政公式ホームページの中で「AEDオープンデータプラットフォームからデータを取得してGoogleマップに表示」することを想定したHTML+JavaScriptのサンプルをGitHubに登録しました。ご活用ください。
https://github.com/hatsunea/aedmap
http://aedmap.azurewebsites.net/