myFare cardアプリのアップデート

以下の記事からのアップデートになります。

https://isehara-3lv.sakura.ne.jp/blog/2023/04/14/golangでwebsocketの実装/

カードリーダーにタッチで参加登録してブラウザで状況が見れる、追加で参加登録があるとwebsocketでその旨のメッセージを表示(画面更新はマニュアル)、発表者は登録のリンクをクリック(トグルになっています、Wi-Fi内の限定ユーザーなのでpwとかは要求しません)すると発表登録というアプリです。

コードの構成は、

uid.jsonはuidとnameのjson形式ファイルです。

全体のコードは、

https://github.com/chateight/golang/tree/master/myfare

になりますが、websocket経由メッセージのブロードキャストのためにコードは以下のようなっています(main.goの部分抜き出し)

① 新規参加者の登録あればその旨のメッセージをserial.goからチャネル経由でmain.goに通知する

② wsはブラウザからのリクエストの都度新規に作成されるから、通知内容が消滅しないようにmain.goの中で共通エリアに保存

③ 余計なwsを消すために、ブラウザから定期的にwebsocket経由でメッセージ送ってforループ内でタイムアウト(今は3秒に設定)すれば未使用wsと判断して終了させる、clients[ws] = trueで確認できるようにしてます

④ ②で保存された通知内容は各ws内で未送信(前回送付と同じかどうか判定、つまり同じ内容は2回以上送らない)であれば送信するが送信条件はタイマーで設定、チャネルから受信と並列条件としています

スマートではなさそうだからもっと別の方法がありそうです。

func msgHandler(ws *websocket.Conn) {
	defer ws.Close()

	clients[ws] = true
	fmt.Println(clients)

	premsg := msg	// initialize websocket message
	t := time.NewTicker(500 * time.Millisecond)
	defer 	t.Stop()
label:
	for {
		msgr := ""
        err := websocket.Message.Receive(ws, &msgr)
		if err != nil {
			//log.Println("receive error")		// main pupose is to check timeout (to detect unused session)
			break label
		}

		select {
			// to send websocket message triggered by the timer
			// the reason to separate receive and send is ws are running multi thread
		case <- t.C:
			if premsg != msg {
				premsg = msg
				err := websocket.Message.Send(ws, msg)
				if err != nil {
					log.Println("send err")
					break label
				}
			}
		case name := <- uidSerial.Notice:	// wait for message from serial.go via channel
			mu.Lock()
			msg = name.(string)
			mu.Unlock()
		}
	}
	clients[ws] = false
}

 

admin