0. メモ
2019年9月後期授業用に少し改変
1. Node.jsによる簡易httpサーバ
1.1 node.jsをインストール
ここからダウンロードする。
https://nodejs.org/en/download/
インストールは右クリックでインストール(とりあえず一般ユーザでやってみる)
node-v10.15.3-x64msiは、環境変数の設定は勝手にやってくれる(C:\Program Files\nodejs\;をパスに入れる等)ので、ありがたいが、勉強にはならないようにも思う。トラブル要因が一つ減るのでまぁいいが。
環境変数は、こんな形でできていると良い。
(他の環境変数の設定が間違っていたりすると、手動で直す必要がある事例あり)
起動チェックはコマンドプロンプトから以下のコマンドを使う。バージョン番号(10.15.3)が帰ってくれば成功。node -v
1.2 簡単サーバの立上げ実験
例えばc:\jstest等のフォルダを作り、
以下のプログラムを打ち込んで、UTF-8で保存する。
varhttp=require('http');// event handler HTTPhttp.createServer(function(req,res){res.writeHead(200,{'Content-Type':'text/plain'});res.end('Hello World!\n');}).listen(8181,'127.0.0.1');
スタートメニューにNode.js command promptというのができているので、それをクリック
コマンドプロンプトが立ち上がる。以下でプログラムで実行。node testsrv.js
コマンドプロンプトには何も表示されない(それで大丈夫)
通信ポートを使うので最初にセキュリティの許可を求めてくる可能性がある。許可すること
ブラウザから以下にアクセスするhttp://127.0.0.1:8181/
「Hello Word!」が表示されたら正常終了
終了は、コマンドプロンプトでCtrl+C。
1.3 コンテンツも返す簡易サーバ
以下のコマンドラインでプログラムで実行。node httpServ.js
今度は、以下のように3通りのアクセスをしてみる。
varhttp=require("http");varfs=require('fs');functiongetType(_url){vartypes={".html":"text/html",".png":"image/png",".gif":"image/gif"}for(varkeyintypes){if(_url.endsWith(key)){returntypes[key];}}return"text/plain";}varserver=http.createServer(function(req,res){varurl=req.url;url=url.replace(/^\//,"");console.log(url);if(fs.existsSync(url)){fs.readFile(url,(err,data)=>{if(!err){res.writeHead(200,{"Content-Type":getType(url)});res.end(data);}else{res.statusCode=500;res.end();}});}else{res.statusCode=404;res.end();}});server.listen(8181,'127.0.0.1');
2. サーバ側のプログラム実行
CGIによるプログラム実行をする簡易サーバのサンプル
varhttp=require('http');varurl=require('url');varpath=require('path');varserver=http.createServer();server.on('request',doRequest);server.listen(8181);functiondoRequest(req,res){varurl=req.url;console.log(url);constexecSync=require('child_process').execSync;varresult=execSync("test2").toString();res.writeHead(200,{'Content-Type':'text/html'});res.write(result);res.end();}
C言語で作るtest2.exeのためのソースコード
#include <stdio.h>
#include <stdlib.h>
intmain(void){printf("<!DOCTYPE html>\n");printf("<html lang = \"ja\">\n");printf("<head>\n");printf("This is CGI test\n");printf("My name is XXXXXXXX<BR>\n");printf("</html>\n");return0;}
※※実験科目はこの先も続く(授業科目はここまでで終わり)
3. フォームアプリを使ったシリアル通信の状態表示
目標:c#のフォームアプリでHTTPアクセス
画像を見ることになるので、C#のフォームアプリで作成する。
フォームアプリは(いや、教材以外の多くのアプリケーションは)、複数のソースから構成される。編集の際にどのファイルを扱っているのか気を付けることがとっても重要。でも、慣れないと中々難しいので、初めて挑戦する人は、失敗を繰り返す上での、練習の第一歩のつもりで。
3つのボタンで表示できるようにButton1_Click, Button2_Click, Button3_Clickの3つのボタンを作る。
とりあえずForm1というWindowに3つのボタンと、イメージ表示用のpictureBox1という、画像表示用のボックスを作ってみた。
こんな感じ
フォーム画面からソースを表示させるには、ソリューションエクスぷローラーでForm1.csを選択し、右クリック。そこからソースを表示を選ぶ。
ソースコードは、Com2HttpReqプロジェクトのFrom1.csの先頭部分だけ。
ソースコードの中にもButton1_Click, Button2_Click, Button3_Clickの3つのボタンクリックに対応した関数がある。
ボタンアクセスは、何も工夫なく愚直なやり方でwebアクセスをする。C#になると、Webアクセス用の構造は次のようになっており、非常に簡単。
namespaceCom2HttpReq{publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}privatevoidStartSerial(objectsender,EventArgse){SerialPort1.PortName=comboBox1.SelectedItem.ToString();// 選択されたCOMをポート名に設定SerialPort1.Open();SerialPort1.Write("s");}privatevoidStopSerial(objectsender,EventArgse){SerialPort1.Close();}privatevoidButton1_Click(objectsender,EventArgse){WebClientwc=newWebClient();Streamstream=wc.OpenRead("http://127.0.0.1:8181/gu.png");Bitmapbitmap=newBitmap(stream);stream.Close();pictureBox1.Image=bitmap;textBox1.Text="gu";}privatevoidButton2_Click(objectsender,EventArgse){WebClientwc=newWebClient();Streamstream=wc.OpenRead("http://127.0.0.1:8181/choki.png");Bitmapbitmap=newBitmap(stream);stream.Close();pictureBox1.Image=bitmap;textBox1.Text="choki";}privatevoidButton3_Click(objectsender,EventArgse){WebClientwc=newWebClient();Streamstream=wc.OpenRead("http://127.0.0.1:8181/pa.png");Bitmapbitmap=newBitmap(stream);stream.Close();pictureBox1.Image=bitmap;textBox1.Text="pa";}
4. 加速度計測結果表示アプリケーション
1) シリアル通信の結果をHTTP送受信をした上で画面表示
目標:目標:IIからIIIまでの内容をまとめて、加速度センサの状態を検知して、画面表示(およびLED表示)するアプリケーションを作成する。
C#のフォームアプリとArduinoのシリアル通信のプログラムは以下の渥美先生のページが非常に参考になる。
https://www.atsumitakeshi.com/index.html
でも時間がないので、
とりあえず(こちらで)III-2にボタンを増したものを作っておきました。
ヘッダ部分を更新
usingSystem;usingSystem.Drawing;usingSystem.Net;usingSystem.Windows.Forms;usingSystem.IO;usingSystem.Threading;
通信開始/終了用の関数を用意する。
送信開始時はII-3)で行った文字を一文字だけ送るという処理をしている。
privatevoidStartSerial(objectsender,EventArgse){SerialPort1.PortName=comboBox1.SelectedItem.ToString();// 選択されたCOMをポート名に設定SerialPort1.Open();SerialPort1.Write("s");}privatevoidStopSerial(objectsender,EventArgse){SerialPort1.Close();}
データ受信部分を追加
ここに、マイコンのシリアル回線から受信された1行を、処理するルーチンを作る。
文字列解析はこだわり始めると大変なので、 if(data.StartWith("A"))
という形で先頭文字だけで判断する仕様にする。
//受信用データ処理privatevoidSerialPort1_DataReceived(objectsender,System.IO.Ports.SerialDataReceivedEventArgse){try{//string data = SerialPort1.ReadExisting();stringdata=SerialPort1.ReadLine();if(!string.IsNullOrEmpty(data)){//受信データに関する処理if(data.StartsWith("A")){WebClientwc=newWebClient();Streamstream=wc.OpenRead("http://127.0.0.1:8181/gu.png");Bitmapbitmap=newBitmap(stream);stream.Close();//サブスレッドの受信データを、別スレッドのFrom1にInvoke((MethodInvoker)(()=>// 受信用スレッドから切り替えてデータを書き込む{pictureBox1.Image=bitmap;textBox1.Text=data;// ラベルを受信した文字列へ変更Thread.Sleep(1);//実行待ちのスレッドに処理を渡す}));}elseif(data.StartsWith("B")){//******* 注意、ここは略 *******}else{//サブスレッドの受信データを、別スレッドのFrom1にInvoke((MethodInvoker)(()=>// 受信用スレッドから切り替えてデータを書き込む{textBox1.Text=data;// ラベルを受信した文字列へ変更Thread.Sleep(1);//実行待ちのスレッドに処理を渡す}));}}}catch(Exceptionex){MessageBox.Show(ex.Message);}}
IIIの最後のプログラムを実行するためには、COMポートを選択してStartボタンを押す。止めるときはStopボタンを押す。
マイコン側の通信プログラムとしては、arduinoで次のようなプログラムを走らせる。
voidsetup(){pinMode(8,OUTPUT);pinMode(12,OUTPUT);Serial.begin(9600);}voidloop(){inti,s;intx,y,z;//実行・リセット直後digitalWrite(8,HIGH);digitalWrite(12,LOW);while(Serial.available()==0);charc=Serial.read();// 一文字分データを取り出す。//スタートdigitalWrite(8,LOW);digitalWrite(12,LOW);s=0;while(1){x=analogRead(A0);y=analogRead(A1);z=analogRead(A2);if(s==0){if(x>600){s=1;Serial.println("A");digitalWrite(8,HIGH);}}else{if(x<550){s=0;Serial.println("B");digitalWrite(8,LOW);}}delay(100);}}
2) 加速度センサ計測の分析
目標:3つ以上の加速度センサの状態や動きを検知して、PCに伝えるマイコンモジュール(プログラム)を作成する。
ポイント1
Iで作成した静的な加速度計測モジュールを、LEDを光らせるだけではなくシリアル回線用のプロトコルを設計し、そのプロトコルを用いてIII-3で完成したC#プログラムで加速度計測の結果が表示できるようなシステムを開発せよ。
※C#プログラムとの連携で迷うよりも、LED制御やArduino IDEのシリアルツールを使い、仕様を確定させることが重要。
ポイント2
加速度の動的変化に対しても検知することにより、センサーに対する動きを検知することを試みよ(来週への課題)。
3週目は、より柔軟なサーバ駆動を実験する。今回はHTTPアクセスにフォームアプリを使ったが、来週の実験ではコンソールアプリでソフト開発をして構わない。
5.発展課題
Mrmr OSC controller を使い、スマホセンサの加速度計測値に応じてサーバに処理を投げる事が出来るように改変してみよう。
参考文献
- 北村愛実: 『確かな力が身につくC#「超」入門』ソフトバンククリエイティブ, 2017年
- フォームアプリによるArduinoとの通信 https://www.atsumitakeshi.com/csharp_arduino1.html
- Hatada's Home Page http://home.a00.itscom.net/hatada/_toc/dotnet.html#csharp
C#によるフォームアプリの開発入門
Visual C#の入門に良いと思います。
1. プログラミングとゲームの杜 http://www.greenowl5.com/gprogram/index.html
色々メモ
Close メソッド
Stream クラスは Close メソッドも持っているが、Stream を閉じる操作(リソース破棄の一例)も Dispose メソッドを使ってやるべき。
Raspberry Piでnode.js簡単サーバ構築
https://note.mu/agw/n/n3d41dc352b14
https://qiita.com/MKLemma/items/aef171c9c6ff5dc6fbe1
さて、C#でゲームを作るのは良いとして、フレームワーク(ライブラリ?)はどうしましょうか。
今ならUnity一択ですかね。
XNAは開発止まったらしいですね。
MonoGameは昔触った時はいい感触だったんですけど、全然流行ってないですね。
DXLibもいいですよね。私が最初にゲーム作ったときに使ったのがDXライブラリなんですよ。