以下の記事からのアップデートになります。
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