mitolab's diary

東南アジアで頑張って生きてる人のブログ

Hugo、github Pages、wovn.io、ムームードメインを使って楽に短時間でプロフィールページを作る!

最近、初対面の方にお会いすることが多くなってきたので、先日webサービスとアプリを使ってオシャレな名刺を作ってみました*1

で、この際プロフィールページフリーランス時代のものだったので、現状に即した内容にアップデートをしてみました。

できたもの

f:id:mitolab:20160812131646p:plain mitolab

  • 1枚だけのプロフィールページ
  • PC/スマフォ両対応
  • google analyticsでトラッキング可能
  • メールフォーム利用可能
  • ブログへの拡張性もある
  • 日本語/英語両対応

短時間でこれだけのものが、ドメイン代だけでまかなえます。

プロフィールページ作成に使うもの

  1. Hugo... 静的サイト生成ツール
  2. Github Pages... 静的サイトを公開できるgithubのサービス
  3. ドメイン... ムームードメインで取得
  4. wovn.io... htmlに一行挿入するだけ簡単ローカライズサービス

作成手順

基本的な手順は、

Hugo + GitHub Pagesでブログを作る

の記事を参照しつつ、ドメイン設定に関しては、

GitHub Pagesで静的なサイトを公開し、独自ドメインを設定する

こちらの記事を参照しながら進めました。

最後に、wovn.ioを使って英語と日本語を切り替えられるようにしました。

Hugoテンプレート適用

Hugoのいいところは、多数のフリーテンプレートを用意していること。しかも結構シンプルでオシャレなものが多い印象です。

f:id:mitolab:20160812133009p:plain http://themes.gohugo.io/

多分、テンプレを探すのに一番時間を費やしました...。最終的に決めたものがこちら。

f:id:mitolab:20160812133119p:plain Hugo Theme: Strata

1枚で完結して、且つスマフォ/PC両対応だったのでこれにしました。あとこれは別に選定基準ではなかったんですが、google analyticsのトラッキングコードを設定出来るようになっていたり、メールフォームもすぐ使えるようにしていたりで、かゆいところに手が届くテンプレで素晴らしいです。背景画像くらいは変えたほうがいいかもしれないけどそのまんま使ってます...。

あと、左下のアイコンを出す出さないとか、右カラムの画像類を出す出さないとかは全てconfig.tomlで設定できて便利です。

注意点として、今回は1枚だけのページを作りたかったので、上記参照した手順記事記事の枠を作ってみるから記事を書いてみるまでは飛ばして、テンプレに付属のexampleSiteに入っている、config.tomlhugo new site <site-name>した際のトップディレクトリに配置(デフォのやつを上書き)して、その中身をいじってあげればOKです。

あと、テンプレに付属のメールフォームは、formspree.ioというプロキシサービスを使っていて、使う場合はサイトをgithubにpushして、ドメインも適用してから、実際にフォームから自分宛にメールを送信して、来たメールでconfirmするだけでフォームが利用可能になります。月に1000通までは無料らしいので余裕で足りると思います。

Github Pages

基本的には、

  • githubリポジトリを作る
  • gh-pagesというブランチを作る
  • 上記ブランチにpushする

という作業だけで、http://[ユーザ名].github.io/[リポジトリ名]というurlにページを公開できます。それか、[ユーザ名].github.ioというリポジトリを作ることでも同様のことが出来るようで、2通りのやり方があるみたいです。今回は前者のやり方でやってみました。

ドメイン設定

ムームードメインでの作業と、Github Pagesでの作業にわかれます。

ムームードメインでは既にドメインを取得済だったので、DNSのAレコードを変更/追加してあげました。加えて、tumblrでCNAMEレコードを使っていたんですが不要なので消しました。

GithubPagesでは、リポジトリのSettingsからCustom Domainを設定してあげると、自動的にリポジトリにCNAMEファイルができます。それで、qiita記事のこちらの手順と同等の手順となります。

f:id:mitolab:20160812134456p:plain

ローカライズ

wovn.ioを使うと簡単にローカライズできました。画面もシンプルなのでいじってみれば使い方は理解できると思います。手順も公式で用意されています。

ただ1つわかりにくかったのが、htmlに挿入する1文が見つけにくいこと。上記手順では、ダッシュボードがブランクの際のページに1文が書いてあるのですが、一度ページを登録してしまうと、その1文がどこかに消えていなくなってしまい、色々ボタンを探してみないとわからないという状態になってしまいました。

最終的には、右上のドロップダウンにフォーカスして、アカウント > コードスニペット を選択すると1文が表示されます。

<script src="//j.wovn.io/1" data-wovnio="key=xxxxx" async></script>

こういうやつです。

まとめ

以上です。簡単に多機能なページが作れてしまうのでオススメです。今回は静的ページ生成サービス探しやテンプレ探しに時間がかかりましたが、既にテンプレも決まっていてドメインも取れている状態であれば、1時間では終わりそうなボリュームかと思います。

では、何かの参考になれば幸いです。

aws serverlessでfacebook messenger botを試してみた

前回のポストから時間がだいぶ空いてしまった...反省。やったことと言えば件名にあることくらいです。まだ中途半端ですが忘れてしまうのでとりあえずメモします。

作ろうと思っているもの

今学んでいるBLOF理論や植物生理、微生物、土の性質、etc...農作物の生産に関するQ&A botができれば便利かなぁと思って着手し始めました。

想定する使い方はいたってシンプルで、

  1. 質問をメッセンジャーに音声で質問する(農作業中テキストを打つとかめんどくさくてしないので)
  2. botがその答えを返してくれる

というもの。


ゆくゆくは個別の圃場情報を予めinputしておいて、例えば「A圃場に必要な肥料は?」とか聞くと、「はい、次の施肥をしてください:① バーク堆肥を250kg、アミノ酸肥料を10kg、鉄肥料を2kg、マンガン肥料を1kg を混ぜて施肥してください ② 酵母菌を30g、砂糖を400g、水を5Lを混ぜて施肥してください、③ 1,2完了後、透明マルチを被せて3日間養生してください」とかそういう答えが返ってくるようなものができれば便利だなぁと思ったりします。つまりは圃場メンテナンスにかけるルーチンプロセスを少しでも省略化することができれば便利だなぁと。


利用サービス

作り方

qiita.com

developers.facebook.com

http://docs.serverless.com/v0.5.0/docsdocs.serverless.com

※ wit.aiについては一端スルー(理由は以下)

現状

頭悪くてwit.aiの使い方/メリットがいまいち理解できず...モチベーションが下がり気味です。"音声認識"がついていること以外、単純にスプレッドシートにキーワードとそのキーワードが含まれていた場合の回答を用意しておくのと何が違うのかイマイチ理解出来ていません...。あと自分がバカなんだとおもいますがwit.ai上の単語の意図するところやインタフェースがわかりにくくてイマイチ手が進まないという。

なので、現状はmessengerでテキストを入力するとオウム返しするbotといういたっておもしろみのないサンプルで止まっています。

f:id:mitolab:20160710154847p:plain

作る上での方針

今回利用するツールはどれも新しい技術らしく、公式ドキュメント、qiita記事などの第三者情報、どちらか一方にしか無い情報があるということがネットサーフィンでわかりました。ので、「ベースの手順は公式ドキュメントを優先し、詰まったところを第三者情報に頼る」という至ってまっとうな形で進めました。

作る上でのメモ

以下は、今後同様のことをするときのために、わかりにくかった点をメモしておきます。

iamロールの設定が必要ですよ

serverlessを導入するにあたって、公式ドキュメントにあるように、"Configuring AWS"から設定しておきましょう。serverlessのプロジェクトを作る前に設定しておかないと、_meta/variables/s-variables-dev-{region名}.jsoniamRoleArnLambdaに適切なキーがアサインされず、handler.jsの実行時にエラーになりますので要注意です。

aws console iamでこんな感じになっていればOK

f:id:mitolab:20160710152220p:plain

iamロールについては、以下が分かりやすかったです。

dev.classmethod.jp

Serverless Optimizer Pluginを入れないと無理

lambdaにUPするコード(ここではhandler.js)にrequireがある場合は、browserifyしてrequire先のコードも1つのファイルにまとめるプラグインが無いと無理でした。

github.com

※ これは前述のqiita記事を読まないとわからなかったです。

API Gatewayからserverlessへのパラメータの受け渡しはどうする?

本来は、s-templates.jsonなるものを作って、任意のendpointに適用していく形のようですが、まどろっこしかったので、qiitaのサンプルのやり方を踏襲してs-function.json内で書けば動いたのでそれでいきました。

{
  "name": "facebook",
  "runtime": "nodejs4.3",
  "description": "Serverless Lambda function for project: FBBot",
  "customName": false,
  "customRole": false,
  "handler": "handler.handler",
  "timeout": 6,
  "memorySize": 1024,
  "authorizer": {},
  "custom": {
    "excludePatterns": [],
    "optimize": {
      "exclude": ["aws-sdk"],
      "transforms": [
        {
          "name": "babelify",
          "opts": {
            "presets": ["es2015"]
          }
        }
      ]
    } 
  },
  "endpoints": [
    {
      "path": "facebook",
      "method": "GET",
      "type": "AWS",
      "authorizationType": "none",
      "authorizerFunction": false,
      "apiKeyRequired": false,
      "requestParameters": {
        "integration.request.querystring.hub.verify_token": "method.request.querystring.hub.verify_token",
    "integration.request.querystring.hub.challenge": "method.request.querystring.hub.challenge",
    "integration.request.querystring.hub.mode": "method.request.querystring.hub.mode"
      },
      "requestTemplates": {
        "application/json": {
          "verify_token": "$input.params('hub.verify_token')",
          "challenge": "$input.params('hub.challenge')",
      "mode": "$input.params('hub.mode')",
          "method": "$context.httpMethod"
        }
      },
      "responses": {
        "400": {
          "statusCode": "400"
        },
        "default": {
          "statusCode": "200",
          "responseParameters": {},
          "responseModels": {
            "application/json;charset=UTF-8": "Empty"
          },
          "responseTemplates": {
        "text/plain": "$input.path('$')"    
          }
        }
      }
    },
    {
      "path": "facebook",
      "method": "POST",
      "type": "AWS",
      "authorizationType": "none",
      "authorizerFunction": false,
      "apiKeyRequired": false,
      "requestParameters": {},
      "requestTemplates": {
        "application/json": {
          "entry": "$input.json('entry')",
          "method": "$context.httpMethod"
        }
      },
      "responses": {
        "400": {
          "statusCode": "400"
        },
        "default": {
          "statusCode": "200",
          "responseParameters": {},
          "responseModels": {
            "application/json;charset=UTF-8": "Empty"
          },
          "responseTemplates": {
            "text/plain": "$input.path('$')"
          }
        }
      }
    }
  ],
  "events": [],
  "environment": {
    "SERVERLESS_PROJECT": "${project}",
    "SERVERLESS_STAGE": "${stage}",
    "SERVERLESS_REGION": "${region}"
  },
  "vpc": {
    "securityGroupIds": [],
    "subnetIds": []
  }
}

参考:

http://docs.serverless.com/docs/templates-variablesdocs.serverless.com

docs.aws.amazon.com

handler.jsはこんな感じ

'use strict';

const request = require('request');

const FB_MESSANGER_TOKEN = 'xxxxxx';

module.exports.handler = function(event, context, cb) {
  switch (event.method.toUpperCase()) {
    case 'GET': {
      if (event.mode === 'subscribe' && event.verify_token === FB_MESSANGER_TOKEN) {
        const validRequest = event.verify_token;
        return cb(null, validRequest ? event.challenge : 'Error, wrong validation token');
      }
    }
    case 'POST': {
      event.entry.forEach(function(pageEntry) {
        pageEntry.messaging.forEach(function(messagingEvent) {
      if (messagingEvent.message) {
        receivedMessage(messagingEvent);
      }
        });
      });
      return cb(null, 'OK');
    }
    default: return cb('Error, Invalid Method');
  } 
};

function receivedMessage(event) {
  var senderID = event.sender.id;
  var recipientID = event.recipient.id;
  var timeOfMessage = event.timestamp;
  var message = event.message; 

  console.log("Received message for user %d and page %d at %d with message:",senderID, recipientID, timeOfMessage);
  console.log(JSON.stringify(message));
  
  var messageId = message.mid;
  
  // You may get a text or attachment but not both
  var messageText = message.text;
  var messageAttachments = message.attachments;

  if (messageText) {
    sendTextMessage(senderID, messageText); 
  } else if (messageAttachments) {
    sendTextMessage(senderID, "Message with attachment received");
  }
}

function sendTextMessage(recipientId, messageText) {
  var messageData = {
    recipient: {
      id: recipientId
    },
    message: {
      text: messageText
    }
  };

  callSendAPI(messageData);
}

function callSendAPI(messageData) {
  request({
    uri: 'https://graph.facebook.com/v2.6/me/messages',
    qs: { access_token: FB_MESSANGER_TOKEN },
    method: 'POST',
    json: messageData

  }, function (error, response, body) {
    if (!error && response.statusCode == 200) {
      var recipientId = body.recipient_id;
      var messageId = body.message_id;

      console.log("Successfully sent generic message with id %s to recipient %s", messageId, recipientId);
    } else {
      console.error("Unable to send message.");
      console.error(response);
      console.error(error);
    }
  });  
}

誰でもbotにアクセスできるわけではない

ここまでの手順で、botサービスを一般公開できるわけではありません。一般公開するには、facebookの審査に通る必要があります。

じゃあどうやって審査に出せばいいの?というと恐らく以下のようになるかと思います。ただし実際に試したわけではないのであくまで推測になります。

  1. facebook developerの当該アプリのダッシュボードにて、左側のサイドバーからmessengerを選択し、スクショの1,2のボタンを押して申請します。

f:id:mitolab:20160710152840p:plain

  1. 左側のサイドバーからアプリレビューを選択し、page_messagingの項目でノートを編集ボタンを押します。

f:id:mitolab:20160710153411p:plain

  1. さらにその先で、プラットフォームポリシーに準拠しているかどうかの確認と、使い方のスクリーンキャストの提出を求められるので、それらを入力します。

f:id:mitolab:20160710153741p:plain

  1. 承認されれば、晴れて一般公開となると思われます。

botを誰かに試して欲しい場合はテスターとして追加する

f:id:mitolab:20160710152447p:plain

画像のように、テスターとして役割に追加してあげれば、botを試してもらうことができます。

感想

今回はとりあえず、serverlessを使ってmessengerでテキストを入力するとオウム返しするbotを作りました。感想としては、おもったよりレスポンスが遅いなー(0.5秒くらいな感覚)と思いました。handler.jsの中身の処理がかさむと恐らくもっと重くなると思われます。

wit.aiは音声認識が付いているので使いたいですが、概念を理解するのに人より多く時間を割かないといけなさそうでだるいなーというところです。

ということで、引き続き触っていきます。

ラズベリーパイ3で土壌湿度センサーを試してみました

今日はこちらの記事を参考に土壌湿度センサーを試してみました。

dev.classmethod.jp

今後はnodeで色々やりたかったので、本記事はドンピシャでした。

実験の目的

最終的には、葉物(特にコマツナ)を作るにあたっての最適な潅水タイミングを見極めたい、ので、とりあえずデータをとってみたい。

結果

結果からいうと記事の通りやったらこんなかんじで何の問題もなくデータがとれました*1

f:id:mitolab:20160529163745j:plain

f:id:mitolab:20160529163800j:plain

基本、参照元の記事の手順まんまでいけるのですが、多少僕の環境との相違点とか、補足があるのでそこだけ書いておきます。

参照記事との相違点

  • ラズベリーパイsudo raspi-configコマンドからAdvanced OptionsにてSPIの機能を有効化しました
  • 前回、nodebrewで最新のnodeを入れたので、"Node.js のインストール"は割愛しました
  • "npm モジュールのインストール"の前にサンプル用ディレクトリを作成ました
  • npm の引数 -S は--saveと同意で、package.jsonのdependenciesに追加されるので、別途package.jsonを作っておく必要があります(作り方はこちらの記事に)
  • nodeコマンドがsudoで実行できなかったので、nodebrewがインストールした場所(which nodeで特定)からシンボリックリンクを貼って対応しました(参考)

参照記事の補足

ピン名対応表

記事中Fritzingで書かれた図面を見れば、配線はできますが、ADコンバータとラズパイ上のピンの対応関係が把握しずらかったのでここで少し補足します。

土壌湿度センサー 結線 MCP3208-CI/P 結線 ラズベリーパイ3
青:
湿度出力(アナログ電圧出力: 0~4.2v(@5v))
- Pin1:
CH0
赤:
電源入力(DC3.3~5v)
- - Pin2:
5v Power
黒:
GND
- Pin14:
AGND*2
- Pin6:
Ground
Pin16:
ADO*3
- Pin1:
3.3v Power
Pin13:
CLK
- Pin23:
SPI0 SCLK
Pin12:
Dout
- Pin21:
SPI0 MISO
Pin11:
Din
- Pin19:
SPI0 MOSI
Pin10:
CS/SHDN
- Pin24:
SPI0 CE0

※ 結線に"-"(ハイフン)が入っているものは結線します。MCP3208-CI/Pを飛ばして結線しているものもあります。

※ MCP3208-CI/PのPin10は、LOWにするとADCがONの状態になります。ADCを使わない場合はHIGHにしてて待機状態にする必要があります。

出力される数値の対応

土壌湿度センサーの開発元wikiページ)をみると、

0 ~300 : dry soil
300~700 : humid soil
700~950

とありました。これはArduinoに繋いだ場合の値で、見たところ上限が10bit(0~1023)ぽいです。今回のADCは12bit仕様なので、分解能は0~4095になります。これを直線的に変換するとすれば、

出力値 状態
0~1292 乾いている
1292~3017 湿っている
3017~4095 湿りすぎ

というふうになるかとおもいます。

通信方式について参考

今回使ったSPI通信、前回のI2C通信に関してはこちらが参考になるかと思います: I2CとSPI

感想

センサー自体が"プリント基板を切り出しました" みたいな作りだったことや、ウルトラ簡単な回路ということもあったりで実用性はどうなんだろう...というところです。色々他も調べてみたほうがいいかもしれません。

また、pFメーター(テンシオメーター)とはちがって、植物の根と土壌間の水分浸透圧を加味することはできないので、その辺の相関関係を調べないと、根が水分を吸収するのに最適な潅水時期を検出することはできないかなぁと思いました。その辺は、東大の難しめな資料が参考になるかもしれません。

あと、良く硝酸態チッソの量を推測するのに使われるEC(電気伝導率)とは仕組みとしてはどう違うのだろうと疑問に思いました。

ということで、かなり簡易的なデバイスですがデータは取るだけとってみて考えようと思います。

*1:ハウツーを参照させていただいたクラスメソッドさんありがとうございます

*2:Pin9:DGND と直結

*3:Pin13:AREF と直結

ラズベリーパイ3にnodejsをインストール

前回のセンサの動作確認pythonでやったんですが、今後はpythonじゃなくてnodejsで色々やりたいので、とりあえず環境を整えます。

既存のnodejsをアンインストール

# apt-getでインストール済のパッケージを確認
dpkg -l | grep node

# nodejs, nodejs(legacy), nodered が入ってたのでそれぞれアンインストール [参照](http://kawatama.net/web/296)
sudo apt-get --purge remove nodejs
sudo apt-get --purge remove nodered

# 一応ちゃんと削除されたか確認
dpkg -l | grep node
sudo find / -name node

# proc/xx/node ってファイルが大量にあったけど問題なさそうなので続行

nodebrewをインストール

# nodebrew(nodeのバージョン管理)をインストール
curl -L git.io/nodebrew | perl - setup

# nodebrewのパスを通す
vim ~/.bashrc
export PATH=$HOME/.nodebrew/current/bin:$PATH
source ~/.bashrc

# nodebrewが有効になったか確認
nodebrew -v

# nodebrewでnodejsのバイナリ安定版をインストール(もし無ければbinaryを外してみる。ちなみにバイナリじゃない場合はソース落としてコンパイルするのでクソ時間かかります要注意)
nodebrew install-binary stable

# lsして出てきたものをuse
nodebrew ls
nodebrew use v6.2.0

# 上記versionが出てきたら成功
node -v

とりあえずここまで。

Raspberry Pi3でTSL2561照度センサの動作確認

こちらの記事を見ながらやってみたらあっけなく動きました。。

qiita.com

boyaki_machineさんありがとうございます。

唯一相違点としては、snd-bcm2835の記入は特に必要なかったです。オーディオのモジュールのようですが、これはデフォでうごいているようでした。lsmod | grep snd_bcm2835 すれば分かります。

f:id:mitolab:20160523215706p:plain

今後としては

  • pythonで動いているんですがnodejsで統一したい
  • High Gainにした時、ある程度の照度(5月日中の窓際くらい)があると異常な値に固定される らしいのでその点を確認してみる

という感じでしょうか。とりあえず動作確認ということで。

Rasberry Pi3にRaspbianをインストールしてSSHでつなぐとこまで

やろうとしていること

f:id:mitolab:20160523185459p:plain

今後各種センサを繋いで開発を行う*1ので、まずは開発しやすい環境を、ということで自宅などで自分のメインマシン(macPC)からSSH接続できるようにしたいと思います。

尚、自宅にHDMIモニタや外付けUSBキーボードが無いので、macPCでSDカードにOSイメージ(raspbian)を焼いて、それをラズパイ3に読ませるという手法をとりました。

必要なもの

  • macPC
  • Rasberry Pi3(以下ラズパイ3)
  • MicroSDカード(コレを使いました)
  • SDカード変換アダプタ(macPCのスロットがSDカード用なので)
  • 電源(5V, 1.2A以上)
  • LANケーブル
  • 無線LANルーター

HDMIモニタ、キーボードは使いません

手順

公式サイトでOSイメージをDL

公式サイトDLページ

f:id:mitolab:20160523185527p:plain

左がDesktop版、右がミニマル。大は小を兼ねるということで左を選択。サイズは約1.4GBでした。

1. DLしたOSイメージが正常か確認する(チェックサムのdiffを取る)

  1. 上記DLサイトにSHA1キーが記載されています。そちらをコピーしてCS_site.txtとかいう名前で保存します
  2. DLしたzipファイルのチェックサムを別ファイルに保存します: shasum 2016-05-10-raspbian-jessie.zip > CS_DL.txt
  3. 1と2で作成したファイルの差分をとります: diff CS_site.txt CS_DL.txt

特に差分がでなければOK、差分がでたらダウンロードしたデータに異変があるので、再度ダウンロードするなりします。

2. OSイメージをmicroSDカードに焼く

  1. macのSDカードスロットにmicroSDカード装着済のSDカードアダプタを挿入
  2. terminalを開いて以下の要領でマウント
## SDカードのエンドポイントを探す。僕の場合は `/dev/disk2` でした
diskutil list

## 一度アンマウントします(マウントされた状態だとOSイメージを焼くddコマンドが使えないので)
sudo diskutil unmountDisk /dev/disk2

## OSイメージのzipを解凍します(普通にFinderからダブルクリックで解凍でもOK)
cd ~/Downloads
unzip 2016-05-10-raspbian-jessie.zip

## OSイメージをmicroSDカードに転送します
sudo dd bs=1m if=2016-05-10-raspbian-jessie.img of=/dev/rdisk2

## 転送中、様子を見たいときはctrl+tで進捗状況を確認できます

3. ラズパイ3にsshで接続する

前準備

  1. 上の手順でOSイメージを入れたmicroSDカードをラズパイ3のmicroSDスロットに挿します
  2. ラズパイ3に電源をいれます。5V 1.2A必要らしいですが、僕はこのモバイルバッテリーを使いました。

ラズパイ3のIPアドレスを取得

  1. macPCのterminal上からarp -a > before_ips.txtを実行してラズパイ接続前のIP一覧を取得します
  2. 無線LANルーターにラズパイ3をLAN接続して30秒くらい待ちます
  3. macPCのterminal上からarp -a > after_ips.txtを実行してラズパイ接続後のIP一覧を取得します
  4. diff before_ips.txt after_ips.txtとして出てきたIPアドレスが恐らくラズパイ3のIPです

上記ででなければ、新しいIPが大抵新しく追加されたIPなので総当りしてみます。

ssh接続

ラズパイはデフォルトでsshが有効になっているとのことで、上記4の手順で取得したIPを用いて以下のようにssh接続します。

## パスワードはデフォルトだと raspberry でxの部分は上記で取得したIP
ssh pi@x.x.x.x

無事接続できると以下のようになります。

f:id:mitolab:20160523202637p:plain

参考

Raspberry Pi 2 Model BのOSインストールと初期設定 https://www.generation.ne.jp/topics/raspberry01/

Mac OS X で Raspberry PiのOSイメージを焼く http://ledsun.hatenablog.com/entry/2014/10/26/174712

DDコマンド http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230741/

バンガロールの投資家や起業家が集まるINVEST KARNATAKA 2016でアグリビジネスセミナーに参加してきた

INVEST KARNATAKA 2016って?

インドのバンガロールでオーガニック日本食ブランドを立ち上げ中の鴛渕さん(前回記事参照)にこんなのがあるよと教えてもらったのが、INVEST KARNATAKA 2016というイベント。

f:id:mitolab:20160211144242p:plain http://investkarnataka.co.in/

こちらのイベントは、2/1~2/3に渡って、バンガロールの属するカルナータカ州が主催する州の産業の各セクター見本市及びカンファレンス、セミナー、BtoBmeetingの場を提供することで同州への企業進出や投資を促すもの。インドのシリコンバレーと言われるバンガロールはインドの中でも重要な稼ぎ頭なのかもしれません。私が参加したセミナーだけでものすごい量の資料でした。

f:id:mitolab:20160211150305p:plain

設備も警備体制もかなりのもので力入っていました。

f:id:mitolab:20160211151850j:plainf:id:mitolab:20160211151852j:plainf:id:mitolab:20160211151856p:plain

ちなみに、本家シリコンバレーのこういうカンファレンス系イベントは10~20万円の法外なお金を取られるようです(ex:World Agri-Tech Investment Summit)が、こちらは政府主導ということもあってかvisitorであればだれでも参加できて無料です。しかも大抵のところは見て回れるので最高です。なので若い人もかなり多かった印象です。

こちら(↓)のイベントカレンダーをみると大体どんな内容が繰り広げられているのか分かります。

Event Schedule

私は農業のことに興味があったので、イベント初日の、Agri-Business & Food Processing セミナーに参加してきました。

Agri-Business & Food Processing セミナーについて

まずつっこみどころとして、開始が30分くらい遅れて、終了も40分押しとなっていました(笑)。インド文化なのでしょうか? また、スピーカーが14名ほどいらっしゃってその内キレイな英語を喋られていたのは2,3名の方くらいでした。残りの方はインド英語だったので正直かなりの部分は聞き取れなかったです。インドで生きてくには、別で"インド英語"を勉強する必要がありそうです...。

上記の理由もあり、セミナー自体から汲みとった内容は少ないですが、とにかく「州によるかなり強いバックアップ体制があるので心配ないぞ!どんどん投資しろ!」というメッセージは汲み取ることができました。

以降は、資料が非常に充実していたので、そちらを参照しながら内容をかいつまんでみます。

カルナータカ州のアグリビジネスの強み

  • 食料加工セクターの2009-2013年までの年成長率は20%、国の平均成長率16%を上回る数値
  • 2014-2015年のUSD20億ドルの輸出額で、年率成長率は22% -カルナータカ州は10個の気候エリア、6つの土壌性質をもつエリアに分けられるため様々な種類の農作物を育てることができる

また、以下の作物はインドの中でも有数の生産高を誇るそう。

f:id:mitolab:20160211155639p:plain

このランクにある作物を見るだけでもかなり幅広い作物が取れていることが伺えますね。

余談ですが、ランク1にあるコーヒーは確かに街中でもコーヒースタンドがたくさんあって立ち飲みしてる人が多かったように思います。あでもコーヒーじゃなくてチャイ飲んでたのかな...?ただCafe Coffee Dayというコーヒーフランチャイズショップは最近やたら多かったです。スタバの超廉価版って感じ。かのセコイヤキャピタルインド支部も投資をしてIPOによりリターンを得ていたようです。

Sequoia to get 18% return on Cafe Coffee Day exit | Business Standard News

カルナータカ州のアグリビジネスエコシステム

優れたインフラと人材

  • 6つのフードパーク(水や電気、洪水時の排水システムなどアグリビジネスに適したエリア)を有し、4つは稼働中、2つは建設中。それともう1つメガフードパークっていうのもある
  • 2百万トン収容可能な工場、30万トンの貯蔵庫が稼働中
  • 農業や園芸農業に関する国の研究機関が5つもあり、同分野のHUBとなっている
  • 農業、園芸農業、獣医学のトレーニングをうけた4000人もの学位を持った人間が毎年輩出される

優れたマーケットと貿易拠点

  • 同州はインドで初めて花卉国際オークションセンターが設置され花卉輸出の中心地となっている
  • カルナータカはgherkin(キュウリ)、rose onion(赤玉ねぎ)、切り花の国内でも有数の輸出州

豊富な貸付可能地

  • 6つのフードパーク内に380エーカーもの貸付可能地がある
  • KIADBというところでは今すぐにでも利用可能な貸付可能地が6000エーカー以上ある

カルナータカ州政府のサポート

  • MSME(Micro, Small & Medium Enterprises)に対して固定資産35%の補助金を提供(上限650万ルピー)
  • 税金の75%が5年間免除される(固定資産に関しては、MSMEは100%免除を上限、カテゴリABCの企業はそれぞれ60~80%が上限)
  • 毎年(最高7年間)利益の6%を補助
  • 国立研究所の開発した技術を適用すると、導入コストの50%(最大100万ルピー)を補助する
  • その他印紙税(Stamp duty)の免除、入境税(Entry tax)、電気税(Electricity tax)、農地転用費を最大100%免除など

※ 日本円はルピーの大体1.6倍です(2016年2月11日現在)

オーガニック農業に関して

どの発表者もそれほど言及はしていませんでしたが(多分)、インドでAmazonを凌ぐといわれるECサイト BigBasketのCEO(もしくはその代理の方)が「オーガニックの需要は高まっいて、消費者は"本物の"認証のついたオーガニックを求めている」おっしゃっていたのが印象的でした。

インドではオーガニック商品は一般の商品の15~20%の高さで取引されているそうですが、その事を逆手にとって"本物"ではないものも横行しているとか。だからこそ消費者は本物を求めるのでしょうね。

また、資料を見てみると、オーガニック農業について多少言及されていましたが、ほんとかよっていうレベルのものでした。一部抜粋すると、

政府がオーガニック農家の組合を設立し、オーガニック作物のマーケティングを先導する

とありましたが、現時点でどこまで進んでいるか、有効性があるのかわからないですね。また、

"Savayava Bhagya Yojane" というオーガニック農業のプログラムを実施し、63677haが認証オーガニック耕作地になった。これによって5.4万人の農家がオーガニック農家に

みたいな記述もあったのですが、いかんせん継続性がなければすぐに慣行農業に戻るでしょうし、耕作地の広さだけでいっても生産性が上がらなければ利益はそこまで上げられないと思います。実際のところはどうなんでしょうか。

参考: Savayava Bhagya Yojane | Green Foundation

"貧しい農家"を減らしたいという想い

農業・食品加工セクターの州政府名誉大臣であるSri. Krishna Byregowdaさんが

  • 既存農家のインカムを上げることが命題
  • 農家とユーザを直接結びつけて中間卸をなくす

とゆっくり力強く語っていた姿が印象的でした。観客もみなこの方の言葉の節々で拍手をしたり声を上げたりしていました。よほど共感したんだと思います。

特にインドでは、所得の少ない農家の貧困による自殺や、農薬被害、中間業者による悪質な中抜などがあるそうです。また、カルナータカでも州の人口の60%が農民ということで、州としても州民としても命題であることは確かなのだろうなと思いました。

参考:

農民の自殺、インドで増加-綿花価格下落で地方の貧困深刻化 - Bloomberg

Amulモデルがインドの農業を変える!? | AGRI IN ASIA

全体の感想

かなり言葉の壁があって、恥ずかしながら資料で知る情報の方が多かったです...。ただ州として支援する姿勢は今後も変わらなさそうですし、ここ5年くらいで確実に発展はしていくだろうなと感じました。オーガニック農業に関しては州として優先度は低そうですが、農家の教育を促してはいますし、支援制度を使うこともできると思うので、何かしら食品関連や農業関連でビジネスをしたい場合は期待はできそうだなと感じました。