Javascript(Obniz)で電光掲示板を動かし、朝の連続テレビ小説のあらすじを毎朝7時に流す。

#概要

![5.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/35435653-8cb6-3089-2f85-350bf2a5a534.gif)
![6.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/1ca2b473-428e-a5f2-2c14-0355fc080b8d.gif)
![7.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/4c539518-af03-7730-4178-3d005df1a794.gif)



連続テレビ小説　まんぷく(112)「できたぞ！福子！」 / 佳境を迎えた即席ラーメン作り。最終調整の末、家族や仲間を集めて試食会を行うことに。みんなにおいしさを認めてもらえるのでしょうか…

2019年2月13日放送分のタイトルとあらすじが流れています。

#Obnizとは
![004.jpg](https://qiita-image-store.s3.amazonaws.com/0/288001/cbe6c172-6456-23d8-0b19-540be796c7f4.jpeg)
ObnizはJavascriptで動作するIOT開発ボードです
https://obniz.io/

#電光掲示板=LEDマトリクス
![005.jpg](https://qiita-image-store.s3.amazonaws.com/0/288001/082dba9a-ac80-cb01-53bc-4da237d291ba.jpeg)
LEDコントローラMAX7219搭載のこちらのパーツです。
https://www.amazon.co.jp/gp/product/B07FFV537V/

##LEDに文字を表示する
MAX7219を操作するクラスが用意されています。
これを利用して文字を表示します。
https://obniz.io/sdk/parts/MatrixLED_MAX7219/

#配線
![Untitled Sketch_ブレッドボード.png](https://qiita-image-store.s3.amazonaws.com/0/288001/ae860970-0019-0137-0cf8-1fe83e4799c0.png)

このようになっています。

![008.jpg](https://qiita-image-store.s3.amazonaws.com/0/288001/ea6ba1d0-d1c8-b0a7-cd32-31230d7e0d0b.jpeg)
![007.jpg](https://qiita-image-store.s3.amazonaws.com/0/288001/485f1459-4fb0-3bfa-9c16-fbdf79814b50.jpeg)
![090.jpg](https://qiita-image-store.s3.amazonaws.com/0/288001/7647457c-d0e2-e8ef-551d-bac0301d6f5b.jpeg)
・絡まり防止のため配線をプラ部品に通しています。
・テープや熱収縮チューブでまとめる方法もありましたが、後ほど全て分解したいのでこのようになってます。
・パーツは再利用したい:innocent:

#NHK番組表API
番組リストを取得できます。
毎朝5時に更新されます。
https://api-portal.nhk.or.jp/
#コード

```html
<html>
<head>
<meta charset="utf-8">
<style>
	/*表示しているテキストがわかりやすくなるように整形 */
	body{
		display:flex;
		flex-direction:column;
	}
	canvas{
		width:32px;
		margin-bottom:5px;
	}
</style>
<script src="https://unpkg.com/obniz@1.12.2/obniz.js" crossorigin="anonymous"></script>
<script>

//////////////////////////////////////////////////////
// 環境変数
//////////////////////////////////////////////////////

// Obniz用
const obnizKey = '0000-0000';	// あなたのObniz id
const deviceName = 'MatrixLED_MAX7219';	// デバイス名
const width = 8*4;	// LEDマトリクスの幅
const height = 8;	// LEDマトリクスの高さ
const brightness = 1;	// LED明るさ 1～15
const speed = 60;	// 文字の流れるスピード
const font = '19px sans-serif';	// フォント

// NHK API用
const now = new Date();
const year = now.getFullYear();
const month = ("0"+(now.getMonth() + 1)).slice(-2);
const date =  ("0"+now.getDate()).slice(-2);
const today = `${year}-${month}-${date}`
const week = now.getDay();

const apiKey = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';	// お持ちのNHK APIキー
const apiUrl = `http://api.nhk.or.jp/v2/pg/list/040/g1/${today}.json?key=${apiKey}`;	// NHK番組API
const programTitle = "連続テレビ小説　まんぷく"	// 連続テレビ小説のタイトル

//////////////////////////////////////////////////////
// 番組情報を取得　放送していない日曜日は除く
//////////////////////////////////////////////////////
if(week!=6){
	const myJSON = new XMLHttpRequest();
	myJSON.onreadystatechange = function() {
		if ((myJSON.readyState === 4) && (myJSON.status === 200)) {

			// API叩いてJSON取得
			const programs = JSON.parse(myJSON.responseText);
			const program = programs.list.g1.find((e)=> {
				if (e.id == programTitle) {
					return e;
				}
			});

			// 表示するテキストに整形
			let text = `${program.title} / ${program.subtitle}`;

			// 取得したテキストに全角英数があって気持ち悪かったので半角に変換
			text = text.replace(/[Ａ-Ｚａ-ｚ０-９]/g, function(s) {
			return String.fromCharCode(s.charCodeAt(0) - 65248);
			});

			// テキストをLEDに送り出す
			display(text);

		}
	}
	myJSON.open("GET", apiUrl, true);
	myJSON.send(null);
}


//////////////////////////////////////////////////////
// 画面表示
//////////////////////////////////////////////////////
const display = (text) => {

	const obniz = new Obniz(obnizKey);
		obniz.onconnect = async () => {

		// Obnizの配線
		// 上部のLEDマトリクス
		const matrixTop = obniz.wired(deviceName, { clk:0, cs:1, din:2, gnd:3, vcc:4});
		// 下部のLEDマトリクス
		const matrixBottom = obniz.wired(deviceName, { clk:5, cs:6, din:7, gnd:8, vcc:9});

		// LEDマトリクスの初期設定
		matrixTop.init(width, height);
		matrixTop.brightness(brightness);
		matrixBottom.init(width, height);
		matrixBottom.brightness(brightness);

		//LEDマトリクスに表示させるCanvasを生成
		const canvasTop = obniz.util.createCanvasContext(width, height);
		const canvasBottom = obniz.util.createCanvasContext(width, height);

		let x = width;

		obniz.repeat(async () =>{

			// 上部LEDマトリクスに表示
			canvasTop.fillStyle = "black";
			canvasTop.fillRect(0, 0, width, height);
			canvasTop.fillStyle = "white";
			canvasTop.font = font;
			canvasTop.textBaseline = "top";
			canvasTop.fillText(text, x, -2); // 文字が上半分だけ表示されるように位置調整
			matrixTop.draw(canvasTop);

			// 下部LEDマトリクスに表示
			canvasBottom.fillStyle = "black";
			canvasBottom.fillRect(0, 0, width, height);
			canvasBottom.fillStyle = "white";
			canvasBottom.font = font;
			canvasBottom.textBaseline = "top";
			canvasBottom.fillText(text, x, -11); // 文字が下半分だけ表示されるように位置調整
			matrixBottom.draw(canvasBottom);

			x--;

		}, 1000/speed)

	}
}

</script>
</head>
<body></body>
</html>
```

#動作中の様子
HTMLに2つのCanvasが表示されます。
![e0eb81e22275935d7fe25ad50444edde.png](https://qiita-image-store.s3.amazonaws.com/0/288001/847a9c9e-001d-ee07-27b2-56b430e47fda.png)
境目がわかるように余白を開けています

Canvas上に文字が流れます。
![333.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/b0ca17b3-4472-9fb1-c185-a7f8268ec6db.gif)
これが上下それぞれのLEDに表示されます。

#毎朝7時にあらすじが流れる
Obnizにはサーバーレスイベントが用意されています。
https://obniz.io/doc/about_event

決められた時間にプログラムを実行できます。

これで毎朝7時にNHK番組表を取得して
朝の連続テレビ小説「まんぷく」のあらすじが自動で流れます。

![8.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/1ef77ea2-8867-9e79-a25c-b4f2e2ff82bc.gif)

#どこでも流せる
ネット環境と電源があればどこでもあらすじが流れます。
今回はモバイルバッテリーを電源にしているので持ち運びが楽です。

#ほか

###LEDが1列だと読めない
1列だとフォントサイズ9pxほどにするのですが、漢字が読みにくくなってしまいました。
これではドラマのあらすじが頭に入ってきません。
![9.gif](https://qiita-image-store.s3.amazonaws.com/0/288001/6f3b14f5-e21e-443f-5110-913d9fbbb48e.gif)
できたぞ**■子！**:thinking:

###配線をもっと簡易にできるはず
![222.png](https://qiita-image-store.s3.amazonaws.com/0/288001/59a0cc12-1347-d7ed-1fbe-f84f83c1eac5.png)
ObnizのIOを10個も使っていますが、
表示データを工夫すればこのようにつなげた配線で
LED2列表示ができるはずなのです。




以上です。
ありがとうございました。