blog.kur.jp

バイオリンと山、自転車をこよなく愛するkurのチラシの裏。たまには技術的なことを書いたりするかも知れません。

Azure App ServiceでLaravelを動かす

Githubに置いてあるプロジェクトをAzure App Serviceで動かそうとしたのだけど、思ったより苦労してしまったのでメモ。とりあえず作業のみ。ちなみにLaravel のバージョン5.6.23でした。 

1. GithubにLaravelプロジェクトをプッシュする

まず、新しくLaravelプロジェクトを作ります。

Laravel new laravelapp

そしてこれをとりあえずGithubに突っ込んでおきましょう。

2. Azure App Serviceで新しいアプリを作成する

無料プランで使おうと思った場合、Windowsを選択する必要がああります。

3. アプリケーションの設定を行う

設定項目は下記の通り。

全般設定

phpのバージョン 7.1

アプリケーション設定 

APP_KEY base64:AwYPHtuaOUQIUjAGVCwNg8/jEboqexg1q
APP_DEBUG true
SCM_REPOSITORY_PATH ..\repository
SCM_TARGET_PATH .. 

なお、ここでAPP_KEYは下記のようにして生成します。

php artisan key:generate --show

仮想アプリケーションとディレクトリ

/ site\public

デプロイオプションとして、Githubの上記プロジェクトを指定

4. MySQL in App

せっかくなのでMySQL in Appを使用しますオンにします。

5. MySQL接続情報の取得

「開発ツール」の「コンソール」を開き、下記のようなコマンドで、接続情報を取得できます。

> cd d:\home\data\mysql
d:\home\data\mysql
> cat MYSQLCONNSTR_localdb.txt
Database=localdb;Data Source=127.0.0.1:<ポート>;User Id=azure;Password=<パスワード>

6.ソースコードの修正

上記接続情報をソースに反映させます。

.envとdatabase.phpに反映させれば多分大丈夫。

web.configの生成

IISでは.htaccessが使えないので、web.configを下記のように設定します。

<configuration>
  <system.webServer>
        <handlers accessPolicy="Read, Execute, Script">
        </handlers>
        <rewrite>
            <rules>
                <rule name="Rules for laravel" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />                     
                    </conditions>
                    <action type="Rewrite" url="index.php/{R:1}" />
                </rule>
            </rules>
        </rewrite>
    </system.webServer>
</configuration>

7. Githubにコミット

上記修正したファイルをコミットします

migrate

Azureのコンソールから

php artisan migrate

以上で、動くはず。

参考にしたサイト

medium.com

 

docs.microsoft.com

 

medium.com

uzulla.hateblo.jp

 

Laravel5.1.xをIIS8.5で使う

 

Check! Azure Web Apps + MySQL In App で WordPress を構築する

RN4020をArduinoで使う

とあるプロジェクトでBluetooth Low Energyを使う事になり、そのプロトタイピングというか特性を把握する事を兼ねて諸々触ってみたのでメモ。

国内で流通している(つまり技適の問題がクリアされている)BLEモジュールはいくつかあるのだけれど秋月電子等で入手容易なもののひとつがmicrochip社製のRN4020を実装した物である。

akizukidenshi.com

他の候補だとNordic SemiconductorのRF51822などに代表されるnRF5Xシリーズもあるが、とりあえず今回はRN4020を使ってみることに。

RN4020はシリアル通信で各種コマンド(セットアップや、データの送信など)を実行できるし、RN4020 Arduinoで検索すると、やってみたブログが多く出てくるので、それらを参考にすれば良いだろうと思っていたのだけれど、何故かうまくいかない。

とりあえず、Mac -> Arduino -> RN4020と接続して、Arduinoからシリアルコマンドを自動的に発行させてRN4020を制御するのは一旦諦めて、Macから直接シリアルで RN4020を制御する事にする。

シリアル接続で直接制御する

とは言え、手元にUSBシリアル変換器のような便利なものは無いので、Arduinoに空のスケッチ(つまりsetupとloopのみ)を書き込み、0ピンと1ピンをRN4020に接続する。とりあえずはMacでターミナルを立ち上げて下記コマンドでRN4020に接続。

sudo cu -l /dev/tty.usbmodem1451 -s 115200

このまま接続しても良いのだけれどEchoがあったほうがわかりやすいので、+を入力してエンターすることでEchoを有効にできる。

+

その後、とりあえず工場出荷時の状態にリセットをかけておく。SF,1を送信するとAOKが返ってくる。

SF,1 // 初期化

これで準備がOK。BLEは仕様として、バッテリ情報や心拍数、体温計、サイクリングケイデンス等、いくつかの典型的なサービスが定義されているのだけれど今回は独自サービスを定義したいので、下記のようなコマンドで独自サービスかつ子機(ペリフェラル)として動作するように設定する。

SS,00000001       // 独自サービスを選択
SR,36000000 // 再起動、起動時、切断時に自動的にアドバイス実施
// かつNo Direct Advertisement
PZ // 独自サービスに紐づく独自キャラクタリスティックの初期化
PS,<UUID 1> // 独自サービスのUUIDを設定する
PC,<UUID 2>,1A,0A // 読み書き可能な10 byteのキャラクタリスティックを定義
R,1 // 再起動

なお、上記で設定した内容は下記コマンドで確認出来る。

LS

ここで設定した内容通りに設定が出来ているかはスマホやPCからBLEで接続してみるのが早い。私はとりあえずAndroidのB-BLEを使用したが、iPhone用でもAndroidでもアプリストアを見るといくつかの種類のアプリがあるので適当なものを使用すると良いと思う。

ちなみに上記設定したキャラクタリスティックに値を書き込むには下記のようにしてやる。

SHW,<書込み対象のハンドル>,<任意のデータ>

書込み対象のハンドルはLSで取得出来る。非常に簡単である。ここまで確認出来たのでArduinoから同様にRN4020でコマンドを発行してやれば良い。

とここまで書いて気がついたのだけれど、多くのネット上のサンプルではArduinoでSoftware Serialを使用しているのだけれど、このボーレートが高すぎたのがうまくいかない原因では?ということ。ArduinoにはUno以外にも多くの種類があり、そもそもハードウェアシリアルが複数ついているボードもあるし、ソフトウェアシリアルでも115200bpsが余裕で出る機種もあるのだろうけれど、少なくとも私の経験上Arduino Unoは9600bpsぐらいが無難です。

と言うことで、RN4020を初期化及びボーレートを9600bpsに落とす部分などは上記のように直接シリアル接続で行い、その後、ArduinoのSoftwareSerialで制御する事にした。

そうすると、Arduino側のコードは大変シンプルになる。参考までに極限までシンプルにしたサンプルコードはこんな感じ。通信自体はこれで出来るので、エラー処理をどうするかとか、そもそもアプリケーション的なコードは追加しなければならないのだけれど。 

#include <SoftwareSerial.h>
SoftwareSerial mySerial(3, 2);

void setup() {
  mySerial.begin(9600);
}

void loop() {
  mySerial.println("SHW,000B,ABCD");
  delay(1000);
}

参考にさせて頂いたページ

RN4020 Bluetooth® Low Energy モジュール ユーザガイド

http://akizukidenshi.com/download/ds/microchip/70005191A_JP.pdf

RN-4020搭載mikroBUS Clickボード

http://www.microtechnica.tv/support/manual/clickble_man.pdf

 

Hello 2018

あけましておめでとうございます。2017年末に、本年の振り返りでも書こうかと思っていたものの、気がついたら2018年になり、3日が経過していました。
昨年は趣味も仕事も非常に充実していたと感じています。プライベート面では音楽活動に、スクーバダイビング、登山など、相当に充実した一年でした。もちろんそれらアクティビティだけでなく、それらを通してできた友人知人と過ごす日常もかけがえのないものでした。
仕事面でも、新卒から8年間勤めたげたキヤノン株式会社を飛び出し、いわゆるスタートアップの世界に飛び込んでしまいました。そんな中、最近主に関わっているのはポケットチェンジというプロダクトです。
ポケットチェンジについて簡単に説明すると、海外旅行などで余った外貨をAmazonギフトカードや、Waonや楽天Edyなどの電子マネーにチャージできるサービスです。羽田空港や関西国際空港などの国内国際空港や、新宿や大手町、大阪市内などに設置された専用のキオスク端末を用いてサービス提供をしています。
私はポケットチェンジでは、キオスク端末の画面ユーザインタフェースに携わっています。一般のお客さんが目にする部分もそうですし、端末管理者(我々もそうですし、キオスク端末設置施設のメンテナなど)が触る、いわゆる管理画面にも携わっています。
その他、水面下で進めているようなプロジェクトや、残念ながら日の目を見ることなく忘れ去られてしまいそうなプロジェクトもあるにはあるのですが、一緒に働く仲間にも恵まれ毎日を楽しく送る事が出来ております。
さて、2018年。
前述したように仕事もプライベートも概ね充実してはいるもののCIIDをはじめこれまでで学んだ事を活かせているシーンがどれだけあるのか?というのはひとつのポイントなのかなと思っています。もちろんポケットチェンジのビジネスであったり、それに伴うデザインやエンジニアリングを通して学んだことはたくさんあるのですが、過去の経験をそこまで活かせていない気がする点が、個人的になんとかしたいなという思うところです。
そのため、今年は仕事の重心をもう少しデザインよりにシフトできればと思っています。具体的なアプローチとして個人でデザイン仕事を受けるための会社を作ろうかと。現在のところ、仕事を受注できる見込みもまったく無いのですが、とりあえず箱を作って色々動いて見るのが面白いのではないかなと。基本的にはCIIDが得意とするアプローチでもある、価値検証としてのイテレーティブなプロトタイピングを軸に新規事業創出をサポートできればと考えています。このあたり、私の目指す方向性の詳細については改めてブログなどで書いていければ良いなと思っています。
また、上記と並行して新しいサービスの立ち上げにも尽力して行ければと思っています。アイディアとしてはいくつかあるものの、どれが良いか?についてはまだ考えているところです。また個人的には他の人と一緒にプロジェクトを進めていくのが好き一緒に何かやろうぜと言う方がいらっしゃれば是非気軽に声をかけてください。

ファイナルファンタジータクティクス、オーケストラ演奏会のお知らせ

今週末にせまっておりますが9月24日の日曜日にファイナルファンタジータクティクス(以下、FFT)の音楽のオーケストラ演奏会が行われますので今日はそのお知らせです。演奏曲目、日時、チケットなどに関して詳細は下記のサイトを見て頂くのが良いかと思います。

hoshi-templar.tumblr.com

ところで、このファイナルファンタジータクティクスと言うゲーム、私に取っては結構思い出深いゲームです。子供の頃に結構やりこんだゲームのひとつだというのもありますし、そもそもゲーム音楽をオーケストラで演奏すると言う活動に初めて関わらせて頂いたのもFFTだということもあります。

私が就職して東京に出てきた当初、どこかオーケストラに入って活動したいと思った時に友人から誘ってもらったのが、管弦楽団「星の調べ」でした。普通に団員で入るつもりだったのですが、第二回の演奏会本番まで日が迫っていたためかエキストラ扱いだったのが不思議ですが、非常に楽しかった事をよく覚えています。

その後、しばらくして第三回の演奏会企画が動き出して、今度はちゃんと団員で乗ることに。しかしながら2011年3月11日の大震災の影響によって演奏会は中止になり、その後「星の調べ」は活動休止状態に。

このままもうFFTを演奏する機会は無いのかなぁと思っていたのですが、テンプルナイツ交響楽団が星の調べからFFTをの楽譜を借り受け、FFT演奏会が実現すると言う運びになったのが今回の演奏会なわけで、今回の演奏会は私自身非常に楽しみにしていますので興味のある方は是非お越し頂ければと思います。

なお、チケットに関してですが下記のCNプレイガイドから発券していただくのが確実のようです。チケット自体は無料ですが発券手数料が数百円かかります。また、当日券も多少はあるようです。

www.cnplayguide.com

以上、よろしくお願いいたします。

格安WIFIモジュールESP8266をArduino Unoで使う

Arduinoで何かを作ろうとする時にデータをインターネットから取得したりだとか、またはインターネットに対して送信したりだとか、そういうことがしたくなる時がある。

こういった時に選択肢はいくつかある。

  1. Arduino用のWiFIシールドを用意する
  2. Arduino YUN等の、WiFI標準搭載のArduinoを使用する
  3. シリアル接続のWiFIモジュールを使用する。

1に関しては、下記のページにあるように純正品が存在するのだけれど、Amazonやスイッチサイエンスでも2016年6月10日現在は取り扱っていないようだし、少なくとも日本国内では入手困難にであるように思われます。

Arduino WiFi Shield

Arduion YUNは日本でも容易に入手可能ではあるものの1万円程度と、結構な値段がしてしまう。

Arduino YÚN

Arduino YÚN

  • メディア:


そこで、有力な選択肢となるのが、ESP8266である。Amazonだと一個500円程度かな。

もし急がないようであれば、Aliexpressで送料込で1個2ドル弱からある。

http://www.aliexpress.com/wholesale?SearchText=ESP-01www.aliexpress.com

この値段でArduinoをWiFi対応に出来るのであるから、非常にコストパフォーマンスが高いと言えるのだが、実際に使えるようになるまで色々と詰まってしまったので、備忘録代わりにここに手順を書き残して置く。

1. ライブラリのダウンロードとインストールし、コードの修正

github.com

上記からArduinoからESP8266を使用するためのライブラリを取得し、ライブラリフォルダに展開する。

なお、注意点として、Arduino UNOの場合はソフトウェアシリアルを使用する事になるので、27行目にある下記の1行をアンコメントしておくこと。

#define ESP8266_USE_SOFTWARE_SERIAL

2. ESP8266を Arduinoに接続する(RX、TXをピン0、1に)

接続する必要があるのは合計5本。Arduino UNOは5V駆動、EPS8266は3.3V駆動なので、RX/TXに分圧抵抗等を入れている例もネットにはある。本当は入れたほうがいいのだけれど、私は入れていない。心配な方はどうぞ。

www.mauroalfieri.it

2. ESP8266のbaud rateを9600bpsに設定する

Arduinoにはシリアル端子が付いているのだけれど、この端子はデバッグ時に使用したいので無線モジュールとはソフトウェア的にシリアル通信をさせたい。しかしながら、ESP8266のデフォルトボーレートは115200bpsで、Arduino UNOのソフトウェアシリアルは115200bpsに対応出来ない。厳密には設定自体は出来るのだけれど、ビットエラーが多く使いものにならない。そこで、ボーレートを9600bpsまで落として使用する事にする。

Arduinoにからのスケッチをアップロードして、シリアルコンソールを出し、下記のコマンドを打てば良い。

AT+UART_DEF=9600,8,1,0,0

3. ArduinoとESP8266の接続を変更する

RX、TXをピン12、11などに接続を変更する。これはソフトウェアシリアルを使用するためであるけれど、特にどこのピンでも問題無いように思われる。

4. Arduinoでコードを書く

ほぼライブラリのexampleからのコピペなのだけれど、下記のようなコードを書く。SSIDとパスワードは環境に合わせて。
github.com

#include "ESP8266.h"
#define SSID "XXXX"
#define PASSWORD "XXXX"

SoftwareSerial mySerial(12, 11); /* RX:D12, TX:D11 */
ESP8266 wifi(mySerial);
void setup(void)
{
Serial.begin(9600);
Serial.print("setup begin\r\n");

Serial.print("FW Version: ");
Serial.println(wifi.getVersion().c_str());


if (wifi.setOprToStation()) {
Serial.print("to station ok\r\n");
} else {
Serial.print("to station err\r\n");
}

if (wifi.joinAP(SSID, PASSWORD)) {
Serial.print("Join AP success\r\n");
Serial.print("IP: ");
Serial.println(wifi.getLocalIP().c_str());
} else {
Serial.print("Join AP failure\r\n");
}

Serial.print("setup end\r\n");
}

void loop(void)
{
}

これでArduinoあらWiFIが使用出来るようになる。書いて見ると簡単なのだけれど、ボーレート設定の所に気が付かず、半日以上かかってしまった。どうやら以前出荷されたESP8266はデフォルトボーレートが9600bpsになっていたようで、繋げばすぐに使える状態だったようです。最近のもの、と言ってもいつごろからかはわからないのだけれど、デフォルトが115200bpsになっているようで、Arduino UNOからは使用しにくくなってしまったという事らしい。

Ubuntu 16.04 Xenial XerusをVagrantで試す

Ubuntuは半年に一度と比較的頻繁にリリースされており、常に最新の環境を使いたいと言うコアなユーザーには良いのだけれど、各リリースのサポート期間が9ヶ月と非常に短いため、安定した環境を長く使いたいと言うユーザには向いて居ない。そのため、通常のリリースとは別に約二年間に一度、LTS(Long Term Support)版がリリースされている。先日、その最新のLTS版であるUbuntu 16.04 Xenial Xerusがリリースされたので、この機会に早速試して見ることにした。

thinkit.co.jp

とは言え、新しいPCを用意してインストールする程の体力はなかったのでVagrant上に、である。

最初に用意した環境は下記の通り。

Mac OS El Capitan 10.11.4
Vagrant 1.8.1
VirtualBox 5.0.18

下記のようなコマンドでインストールと起動を行う。

mkdir xenial64
cd
vagrant init ubuntu/xenial64; vagrant up --provider virtualbox

しかし、下記のようなメッセージが出て起動しない。

vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: bridged
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: ubuntu
    default: SSH auth method: password
The guest machine entered an invalid state while waiting for it
to boot. Valid states are 'starting, running'. The machine is in the
'gurumeditation' state. Please verify everything is configured
properly and try again.

If the provider you're using has a GUI that comes with it,
it is often helpful to open that and watch the machine, since the
GUI often has more helpful error messages than Vagrant can retrieve.
For example, if you're using VirtualBox, run `vagrant up` while the
VirtualBox GUI is open.

The primary issue for this error is that the provider you're using
is not properly configured. This is very rarely a Vagrant issue.

しかも2回目以降はこうなる。

vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: Clearing any previously set forwarded ports...
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["modifyvm", "43be4d09-5cca-4db0-82e7-6b57265af2f3", "--natpf1", "delete", "ssh"]

Stderr: VBoxManage: error: The machine 'ubuntu-xenial-16.04-cloudimg' is already locked for a session (or being unlocked)
VBoxManage: error: Details: code VBOX_E_INVALID_OBJECT_STATE (0x80bb0007), component MachineWrap, interface IMachine, callee nsISupports
VBoxManage: error: Context: "LockMachine(a->session, LockType_Write)" at line 493 of file VBoxManageModifyVM.cpp

なんだこれはと思って、VirtualBox Managerで確認して見たところ、Guru Meditationと表示されている。
f:id:mikio-k:20160426020406p:plain
よくわからないがとりあえず、起動していない事は間違いない。VirtualBox Managerから仮想マシンを殺す事も出来なかったのでvagrant haltコマンドで終了させる。海外の掲示板などで見てみると、解決方法としてはVirtualboxを5.0.16にダウングレードすれば良いとのこと。

Ubuntu 16.04 (Xenial Xerus) | Hacker News

とりあえずietualBoxを5.0.16にダウングレードしてみることにした。そしてvagrant upした結果がこちら。

vagrant up

Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'ubuntu/xenial64' is up to date...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: bridged
==> default: Forwarding ports...
    default: 22 (guest) => 2222 (host) (adapter 1)
==> default: Running 'pre-boot' VM customizations...
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: ubuntu
    default: SSH auth method: password
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
    default: Warning: Remote connection disconnect. Retrying...
==> default: Machine booted and ready!
==> default: Checking for guest additions in VM...
==> default: Configuring and enabling network interfaces...
The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

/sbin/ifdown eth1 2> /dev/null

Stdout from the command:



Stderr from the command:

sudo: unable to resolve host ubuntu-xenial
mesg: ttyname failed: Inappropriate ioctl for device

下記の部分で非常に時間がかかっていることと、

default: SSH auth method: password
default: Warning: Remote connection disconnect. Retrying...
default: Warning: Remote connection disconnect. Retrying...
default: Warning: Remote connection disconnect. Retrying...

下記のメッセージが気になると言えば気になるのだけれど、vagrant sshコマンドで無事にsshログインする事が出来るようになった。

The following SSH command responded with a non-zero exit status.
Vagrant assumes that this means the command failed!

/sbin/ifdown eth1 2> /dev/null

Stdout from the command:



Stderr from the command:

sudo: unable to resolve host ubuntu-xenial
mesg: ttyname failed: Inappropriate ioctl for device

Webブラウザからインターネット越しにArduinoのシリアル入出力を叩く

ネットワーク越しにArduinoを操作したいなと思ったので、ちゃちゃっと作って見ました。需要はあんまりない気がするので、最低限の記述だけれおd,ほぼリアルタイムの通信が出来ているので、備忘録代わりに。

仕組みとしては下記のような感じ。
f:id:mikio-k:20160310070354p:plain
Arduinoのシリアル出力をMacで動くNode.jsが受信してSocket.ioでAzureに投げつける。WebブラウザとAzureも同様にSocket.ioで通信をしている。コードを見てもらったほうが早いと思うので下記に示す。まず、下記がMac上のNode.jsのコード。

var serialPort = require("serialport")
var io = require('socket.io-client')

// send server
socket = io.connect('http://ほげほげ.azurewebsites.net/');
socket.on('connect', function () {
	  console.log("socket connected");
});
  
socket.on('s2c_message', function (data) {
	  console.log("data receive:" + data.value);
	  sp.write(data.value);
});
  var flag = 0;
  var sp = new serialPort.SerialPort("/dev/tty.usbmodem1421", {
  baudrate: 9600,
  dataBits:8,
  parity:'none',
  flowControl:false,
  parser:serialPort.parsers.readline('\n')
});

sp.on('data', function(data) {
	console.log('data received: ' + data);
    socket.emit("c2s_message", { value : data });
});

sp.on("open", function () {
  console.log('open');
});

そしてこれがAzure WebApps上のコード

var http = require('http');
var socketio = require( 'socket.io' ); // Socket.IOモジュール読み込み
var fs = require( 'fs' ); // ファイル入出力モジュール読み込み
//Lets define a port we want to listen to
var port = process.env.PORT || 1337;
var ip = "0.0.0.0";

// 3000番ポートでHTTPサーバーを立てる
var server = http.createServer( function( req, res ) {
    res.writeHead(200, { 'Content-Type' : 'text/html' }); // ヘッダ出力
    res.end( fs.readFileSync('./index.html', 'utf-8') );  // index.htmlの内容を出力
}).listen(port);

// サーバーをソケットに紐付ける
var io = socketio.listen( server );

// 接続確立後の通信処理部分を定義
io.sockets.on( 'connection', function( socket ) {

    // クライアントからサーバーへ メッセージ送信ハンドラ(自分を含む全員宛に送る)
    socket.on( 'c2s_message', function( data ) {
        // サーバーからクライアントへ メッセージを送り返し
        io.sockets.emit( 's2c_message', { value : data.value } );
    });
});

最後にブラウザのUI

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <style>
    #messageForm {
        margin-top: 15px;
    }
    </style>

    <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script type="text/javascript" src="socket.io.js"></script>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <form name="form">
                    <div class="form-group">
                        <input  name="field" type="text" class="form-control" id="messageForm" style="width:100px;">    
                    </div>
                    <div class="form-group">
                        <button type="button" class="btn btn-primary" id="sendMessageBtn">send message</button>
                    </div>
                </form>
                <div id="messageView"></div>
            </div>
        </div>
    </div>

    <script type="text/javascript">
	document.form.field.focus();
    var ioSocket = io.connect( "http://arduinosocket.azurewebsites.net/" ); // チャットサーバーに接続
    // サーバーからのデータ受け取り処理
    ioSocket.on( "connect", function() {} ); // 接続
    ioSocket.on( "disconnect", function() {} ); // 切断

	$("#messageForm").keydown(function(e) {
            if ((e.which && e.which === 13) || (e.keyCode && e.keyCode === 13)) {
				        var message = $("#messageForm").val();
    				    $("#messageForm").val("");

				        // クライアントからサーバーへ送信
        				ioSocket.emit( "c2s_message", { value : message } );

                return false;
            } else {
                return true;
            }
			});
    // サーバーからクライアントへの送り返し
    ioSocket.on( "s2c_message", function( data ) { appendMessage( data.value ) });

    // 画面にメッセージを追記
    function appendMessage( text ) {
        $("#messageView").prepend( "<div>" + text + "</div>" );
    }

    // 自分を含む全員宛にメッセージを送信
    $("#sendMessageBtn").click( function() {
        // メッセージの内容を取得し、その後フォームをクリア
        var message = $("#messageForm").val();
        $("#messageForm").val("");
        // クライアントからサーバーへ送信
        ioSocket.emit( "c2s_message", { value : message } );
    });

    </script>
</body>
</html>