LoginSignup
1
0

Node-RED MCU EditionのDashboardで日本語を表示できるようにしてみた

Last updated at Posted at 2024-02-24

はじめに

Node-RED MCU EditionのDashboardで日本語を使用すると「???」で表示されます。

before.png

ふと、Moddableのブログ記事を見ていたら、Moddable自体は日本語を表示する機能が実装されていることを知りました。

仕組み

Moddableでフォントを扱う仕組みについて調べました。

また、DashboardはPiuを使用しているので、Piuでフォントを扱う仕組みを調べました。

BMFont(BitMap Font)が採用されていることまでわかりましたが、使い方がピンと来なかったので、次に実際の使用例を調べました。

前例(実装例)

スタックチャンの生みの親の石川さんがModdableのTwitterクライアントをサンプルで作られており、日本語が表示されていることを確認しました。

そのままではビルドが失敗し、起動後もメモリ不足のエラーで動作しなかったので、コードを一部修正しました。

manifest.json
$ diff manifest.json manifest.json_org

11a12
>       "./secret-token",
34,46c35,36
<     "static": 0,
<     "chunk": {
<         "initial": 65536,
<         "incremental": 0
<     },
<     "heap": {
<         "initial": 4096,
<         "incremental": 0
<     },
<     "keys": {
<         "available": 128
<     },
<     "stack": 600
---
>     "stack": 512,
>     "static": 131072
twitter.js
$ diff twitter.js twitter.js_org 

2a3
> import secret from 'secret-token'
5c6
< const BEARER_TOKEN = ''
---
> const BEARER_TOKEN = secret.BEARER_TOKEN

IMG_4763.jpg

仕組み

assets/fontsフォルダにフォントファイル(.fnt、.png)が置かれています。

├── assets
│   ├── fonts
│   │   ├── Cica-Bold.fnt
│   │   ├── Cica-Bold.png
│   │   ├── Cica-Regular.fnt
│   │   └── Cica-Regular.png
│   ├── icons
│   │   ├── comment_18x18.png
│   │   ├── favorite_18x18.png
│   │   ├── retweet_18x18.png
│   │   └── search_36x36.png
│   └── images
│       └── m5stack.png
├── cert
│   ├── digicerthasca.der
│   └── digicertssca.der
├── main.js
├── manifest.json
├── test.json
├── tweet-application.js
├── tweets.js
└── twitter.js

manifest.jsonのresourcesで指定しています。

  "resources": {
    "*": ["./assets/icons/*", "./assets/images/*"],
    "*-alpha": ["./assets/fonts/*"]

main.jsとtweet-application.jsでfontを指定しています。

font: 'Cica-Regular'
font: 'Cica-Bold'

これでようやく使い方がわかりました。

Dashboardの実装調査

assetsフォルダにフォントファイル(*.fnt, *.png)が置かれています。

node-red-mcu/nodes/dashboard
├── ScrollerBehaviors.js
├── assets
│   ├── Roboto-Medium-12.fnt
│   ├── Roboto-Medium-12.png
│   ├── Roboto-Medium-18.fnt
│   ├── Roboto-Medium-18.png
│   ├── Roboto-Regular-18.fnt
│   ├── Roboto-Regular-18.png
│   ├── button.png
│   ├── glyphs.png
│   ├── popup.png
│   ├── slider.png
│   ├── switch.png
│   ├── ui_colour_picker.png
│   └── ui_colour_picker_mask.png
├── manifest.json
├── ui_chart.js
├── ui_colour_picker.js
├── ui_gauge.js
├── ui_nodes.js
├── ui_templates.js
└── ui_text_input.js

manifest.jsonのresourcesで指定しています。

        "resources":{
                "*": [
                        "./assets/ui_colour_picker"
                ],
                "*-mask": [
                        "./assets/Roboto-Medium-12",
                        "./assets/Roboto-Medium-18",
                        "./assets/Roboto-Regular-18",

ui_templates.jsでfontを指定しています。

			chartNoData: new Style({ font:"18px Roboto", color:halfGray, horizontal:"center" }),
			chartX: new Style({ font:"medium 12px Roboto", color:widgetText, horizontal:"center" }),
			chartY: new Style({ font:"medium 12px Roboto", color:widgetText, horizontal:"right" }),
			notification: new Style({ font:"18px Roboto", color:widgetText, horizontal:"left", left:10, right:10, top:10, bottom:10 }),
			keyboard: new Style({ font:"18px Roboto", color:BLACK }),
			textName: new Style({ font:"18px Roboto", color:widgetText, left:5, right:5 }),
			textValue: new Style({ font:"medium 18px Roboto", color:widgetText, left:5, right:5 }),
			textNameLeft: new Style({ font:"18px Roboto", color:widgetText, horizontal:"left", left:10 }),
			textValueLeft: new Style({ font:"medium 18px Roboto", color:widgetText, horizontal:"left", left:10 }),
			textNameRight: new Style({ font:"18px Roboto", color:widgetText, horizontal:"right", right:10 }),
			textValueRight: new Style({ font:"medium 18px Roboto", color:widgetText, horizontal:"right", right:10 }),
			textField: new Style({ font:"medium 18px Roboto", color:[TRANSPARENT,widgetText,widgetText,widget], horizontal:"left", left:10 }),
	result.styles.title = new Style({ font:"medium 18px Roboto", color:WHITE, horizontal:"left" });
	result.styles.titleMenuItem = new Style({ font:"medium 18px Roboto", color:[halfGray,groupText,groupText,WHITE], horizontal:"left" });
	result.styles.group = new Style({ font:"medium 18px Roboto", color:[groupText,groupText,groupText,groupText], horizontal:"left" });
	result.styles.button = new Style({ font:"medium 18px Roboto", color:[halfGray,WHITE,WHITE,WHITE] });
	result.styles.dropDown = new Style({ font:"medium 18px Roboto", color:[halfGray,widgetText,widgetText,WHITE], horizontal:"left", left:10 });
	result.styles.dropDownMenuItem = new Style({ font:"medium 18px Roboto", color:[halfGray,widgetText,widgetText,WHITE], horizontal:"left", left:10 });
			container.first.style = new Style({ font:"medium 18px Roboto", color:[REDTheme.colors.halfGray,color,color,color] });

これで修正すべき場所がわかりました。

フォントファイルの比較

フォントファイルの中身を見ると明らかですが、Twitterクライアントで使用しているフォントファイルには日本語が含まれていますが、Node-RED MCU EditionのDashboardで使用しているフォントファイルには日本語が含まれていません。

Cica-Regular.png

Roboto-Regular-18.png

フォントファイルの作成

Twitterクライアントで使用しているフォントファイルを流用してNode-RED MCU EditionのDashboardで日本語表示できることを確認しましたが、フォントファイルを作ってみます。

Windowsの場合

Bitmap Font Generator、一択です。GUIアプリケーションでフォントファイルを作成できます。

macOSの場合

Glyph Designerが紹介されていますが、有償となるため、fontbmツールを使用しました。

macOSとLinuxの場合 (無償のfontbmツールを使用する場合)

fontbmツールはWindowsとLinuxはバイナリファイル(実行形式)が提供されていますが、macOSの場合はソースコードからビルドする必要があります。

ビルド手順

$ brew install freetype
$ git clone https://github.com/vladimirgamalyan/fontbm.git
$ cd fontbm
$ cmake .
$ make

フォントの準備

Noto Sans日本語フォントをダウンロードします。

zipファイルを展開し、staticフォルダの中のNotoSansJP-Regular.ttfを使用します。

BMFontファイルの作成

NotoSansJP-Regular.ttfをfontbmフォルダに置きます。
BMFontファイルを作成する場合、文字コードのブロック単位で指定するか、文字単位で指定するか選択できます。
ブロック単位で指定すると日本語以外の文字(例えば、中国語の漢字など)が含まれてしまうため、文字単位で指定してBMFontファイルを作成することにしました。

こちらのサイトでShift JISに含まれる文字を一覧化したファイルが公開されていましたので、こちらを使用することにしました。

$ wget https://raw.github.com/nakamura001/JIS_CharacterSet/master/SHIFTJIS_custom/SHIFTJIS_custom_win_bom_utf8.txt
$ ./fontbm --font-file NotoSansJP-Regular.ttf --data-format bin --color 0,0,0 --font-size 18 --chars-file SHIFTJIS_custom_win_bom_utf8.txt --kerning-pairs regular --output Noto-Regular

警告(warning)が表示されますが、気にしなくて大丈夫です。

warning: glyph 8786 not found.
warning: glyph 65279 not found (it looks like Unicode byte order mark (BOM)).

コマンド実行が終了すると、Noto-Regular.fntとNoto-Regular_0.pngファイルが作成されます。
Noto-Regular_0.pngのファイル名はNoto-Regular.pngへ変更します。

$ mv Noto-Regular_0.png Noto-Regular.png

参考

.fntファイルはバイナリ形式のため、内容を確認するにはプログラムを作成します。

$ npm init -y
$ npm i fs
$ npm i parse-bmfont-binary

font.jsファイルを作成します。

font.js
var fs = require('fs')
var parse = require('parse-bmfont-binary')

fs.readFile('Noto-Regular.fnt', function(err, data) {
  if (err) throw err
  var font = parse(data)
  
  //do something with your font
  console.log(font)
})

font.jsを実行します。

$ node font.js

(省略)
      xadvance: 11,
      page: 0,
      chnl: 15
    },
    ... 6936 more items
  ],
  info: {
    size: -18,
    smooth: 0,
    unicode: 0,
    italic: 0,
    bold: 0,
    charset: '',
    stretchH: 100,
    aa: 1,
    padding: [ 0, 0, 0, 0 ],
    spacing: [ 0, 0 ],
    outline: 0,
    face: 'Noto Sans JP'
  },
  common: {
    lineHeight: 26,
    base: 21,
    scaleW: 2048,
    scaleH: 1024,
    pages: 1,
    packed: 0,
    alphaChnl: 0,
    redChnl: 4,
    greenChnl: 4,
    blueChnl: 4
  },
  pages: [ 'Noto-Regular_0.png' ]
}

Dashboardの日本語化

node-red-mcuのdashboardノードのassetsフォルダにNoto-Regular.fntとNoto-Regular.pngファイルを置きます。
また、manifest.jsonとui_templates.jsを変更します。

node-red-mcu/nodes/dashboard
├── ScrollerBehaviors.js
├── assets
│   ├── Noto-Regular.fnt        (←追加)
│   ├── Noto-Regular.png        (←追加)
│   ├── Roboto-Medium-12.fnt
│   ├── Roboto-Medium-12.png
│   ├── Roboto-Medium-18.fnt
│   ├── Roboto-Medium-18.png
│   ├── Roboto-Regular-18.fnt
│   ├── Roboto-Regular-18.png
│   ├── button.png
│   ├── glyphs.png
│   ├── popup.png
│   ├── slider.png
│   ├── switch.png
│   ├── ui_colour_picker.png
│   └── ui_colour_picker_mask.png
├── manifest.json              (←変更)
├── ui_chart.js
├── ui_colour_picker.js
├── ui_gauge.js
├── ui_nodes.js
├── ui_templates.js            (←変更)
└── ui_text_input.js

フォントファイルと変更したファイル(manifest.json、ui_templates.js)はGitHubに置きました。

結果

シミュレータも実機も問題なく表示されることを確認しました。

after.png

GHA2_wgasAAZ_Ud.jpg

応用

MQTTでメッセージを送れば、デバイス側でサイネージ的に表示できます。

GHBQeljbEAAgTwx.jpg

IMG_4766.jpg

さいごに

これでようやくDashboardを実用的に使えるようになりました!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0