ESP32をJavascriptでLチカする：MQTTでPublish/Subscribeする

前回の投稿「[ESP32をJavascriptでLチカする](https://qiita.com/poruruba/items/96db9d20e7e4ced7635d)」に引き続き、ESP32でJavascriptを動かします。
今回は、MQTTでPublish/Subscribeします。

まだ、MQTTブローカを立ち上げていない場合はインターネット上にたくさんの有志の方が紹介しています。あるいは、以下を参考にしてください。
　[AWS IoTにMosquittoをブリッジにしてつなぐ](https://qiita.com/poruruba/items/084317e01b9fababc02e)

ソースコードもろもろは、前回同様以下に上げてあります。
随時、修正、拡張しています。

poruruba/QuickJS_ESP32

https://github.com/poruruba/QuickJS_ESP32

※M5StickCとM5Core2用で、PlatformIOのプロジェクトを分けていますが、ソースコードは共通です。

(2022/1/5 更新)
・M5StickCとM5Core2用でPlatformIOでプロジェクトを分けていましたが、platformio.iniで併記できることに気づき、1つのプロジェクトにまとめました。

#今回作成する構成

2台のESP32をMQTTで互いに通信します。
M5StickCとM5Core2を使ってみます。

互いにトピックを待ち受け、受信したらM5StickCの場合はLEDを点灯または消灯、M5Core2の場合は、LCDの背景を黒またはピンクにします。
M5StickCではボタンAを押すとトピックにPublishし、M5Core2ではタッチスクリーンにタッチするとトピックにPublishするようにします。

MQTT関連の操作は、mqttモジュールに実装してあります。

```js
import * as mqtt from "mqtt";
```

あとは、接続して、Subscribeしつつ、好きなタイミングでPublishします。

```js
mqtt.connect(クライアント名)

mqtt.subscribe(トピック名, () =>{
	var 受信メッセージ = mqtt.getPayload();
	受信したときの処理
});

mqtt.publish(トピック名, 送信メッセージ);
```

実装を簡単にするため、現状は待ち受けられるトピックは1つのみです。

M5StickCとM5Core2で同じJavascriptを使えるように、ESP32のモデルで処理分岐するようにします。
モデル名は以下で取得できます。（ちなみに、動的にモデルを判別しているのではなく、コンパイル時に特定しています）

```js
esp32.getDeviceModel()
```

※あるいは、Macアドレスと同名のファイル名があったらそれを読み込むようにしておきました。

#ソースコード

結局以下のようなソースコードになりました。
トピック「m5/test」をSubscribe/Publishしています。

```js:public/main.js
import * as lcd from "lcd";
import * as gpio from "gpio";
import * as input from "input";
import * as mqtt from "mqtt";

var width, height;
var model;
var modelName = "OTHER";
var onoff = false;
const topic = "m5/test";

async function setup()
{
	var ipaddress = esp32.getIpAddress();
	console.log("ipaddress=" + ((ipaddress >> 24) & 0xff) + "." + ((ipaddress >> 16) & 0xff) + "." + ((ipaddress >> 8) & 0xff) + "." + (ipaddress & 0xff));

	width = lcd.width();
	height = lcd.height();
	
	lcd.setTextColor(0xffffff);
    lcd.setTextDatum(lcd.middle_left);

	model = esp32.getDeviceModel();
	if( model == esp32.MODEL_M5StickC ){
		modelName = "M5StickC";
		lcd.setTextSize(2);
		gpio.pinMode(10, gpio.OUTPUT);
		gpio.digitalWrite(10, onoff ? gpio.LOW : gpio.HIGH);
	}else if( model == esp32.MODEL_M5Core2 ){
		modelName = "M5Core2";
		lcd.setTextSize(3.5);
		lcd.fillScreen(onoff ? 0xff00ff : 0x000000);
	}

	lcd.setCursor((width - lcd.textWidth(modelName)) / 2, height / 2);
	lcd.print(modelName);

	mqtt.connect(modelName);
	mqtt.subscribe(topic, () => {
		console.log("received: " + mqtt.getPayload() );
		
		if( model == esp32.MODEL_M5StickC ){
			onoff = !onoff;
			gpio.digitalWrite(10, onoff ? gpio.LOW : gpio.HIGH);
		}else if( model == esp32.MODEL_M5Core2 ){
			onoff = !onoff;
			lcd.fillScreen(onoff ? 0xff00ff : 0x000000);
			lcd.setCursor((width - lcd.textWidth(modelName)) / 2, height / 2);
			lcd.print(modelName);
		}
	});
}

async function loop()
{
	esp32.update();

	if( model == esp32.MODEL_M5StickC ){
		if( input.wasPressed(input.BUTTON_A) ){
			console.log("wasPressed");
			mqtt.publish(topic, "hello " + modelName );
		}
	}else if( model == esp32.MODEL_M5Core2 ){
		if( input.isTouched() ){
			console.log("isTouched");
			mqtt.publish(topic, "hello " + modelName );
		}
	}
}
```

#終わりに

また、アイディアを思いついたら、随時拡張していこうと思います。

以上