質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
並列処理

複数の計算が同時に実行される手法

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5162閲覧

websocketとthreadingでの並列処理がうまく動きません。

dyrobin

総合スコア13

並列処理

複数の計算が同時に実行される手法

WebSocket

WebSocketとは双方向・全二重コミュニケーションのためのAPIでありプロトコルのことを指します。WebSocketはHTML5に密接に結びついており、多くのウェブブラウザの最新版に導入されています。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/08/26 12:59

編集2021/08/28 11:27

①webブラウザに表示させたボタンをクリックすることでGPIOを入出力する(LEDを点灯消灯)
②GPIOの入力状態(スイッチでLEDを点灯消灯)をwebブラウザにリアルタイムに表示する
上記の動作を同一プロセスで実現したく、threadingを使用して試みました。

しかし下記のようなエラーとなり、うまく動きませんでした。
Traceback (most recent call last):
File "threadgpio.py", line 74, in <module>
thread1 = threading.Thread(target=sendMessage, args=((client, server)))
NameError: name 'client' is not defined

def sendMessage(client, server1):
def receivedMessage(client, server2, message):
上記のコールバック関数の引数を、threadに渡せてないようです。
どのようにすれば引数をthreadに渡すことができるでしょうか。

python

1#!/usr/bin/env python 2# coding:utf-8 3from websocket_server import WebsocketServer 4from time import sleep 5import RPi.GPIO as GPIO 6import subprocess 7import threading 8from threading import Thread 9 10 11GPIO.setmode(GPIO.BCM) 12GPIO.setup(14, GPIO.OUT) 13GPIO.setup(27, GPIO.IN, GPIO.PUD_DOWN) 14 15 16def sendMessage(client, server1): 17 18 while True: 19 if GPIO.input(27) == 0: 20 21 #print("LED消灯中") 22 time.sleep(0.1) 23 server1.send_message_to_all("LED消灯中") 24 25 26 elif GPIO.input(27) == 1: 27 28 #print("LED点灯中") 29 time.sleep(0.1) 30 server1.send_message_to_all("LED点灯中") 31 32server1 = WebsocketServer(9002, host="192.168.43.57") 33server1.set_fn_new_client(sendMessage) 34server1.run_forever() 35 36def receivedMessage(client, server2, message): 37 print(message) 38 39 try: 40 41 if message == 'led_on': 42 GPIO.output(14, True) 43 44 45 elif message == 'led_off': 46 GPIO.output(14, False) 47 48 49 except KeyboardInterrupt: 50 GPIO.cleanup() 51 52server2 = WebsocketServer(9001, host="192.168.43.57") 53server2.set_fn_message_received(receivedMessage) 54server2.run_forever() 55 56thread1 = threading.Thread(target=sendMessage, args=((client, server))) 57thread2 = threading.Thread(target=receivedMessage, args=((client, server, message))) 58thread1.start() 59thread2.start() 60thread1.join() 61thread2.join()

html

1<html> 2<head> 3 <script src="http://code.jquery.com/jquery-latest.min.js"> 4 </script> 5 <meta charset="UTF-8"> 6 <script> 7 $(function(){ 8 var ws1 = new WebSocket("ws://192.168.43.57:9001/"); 9 var ws2 = new WebSocket("ws://192.168.43.57:9002/"); 10 var ws3 = new WebSocket("ws://192.168.43.57:9003/"); 11 12 $('#btn1').on('click', function () { 13 if($('#btn1').text() == "OFF") { 14 $('#btn1').text("ON") 15 ws1.send('led_on'); 16 } else { 17 $('#btn1').text("OFF") 18 ws1.send('led_off'); 19 } 20 }); 21 22 ws2.onmessage = function (message) { 23 //('#test').append(message.data); 24 if (message.data == 'LED点灯中') { 25 $('#test').css('background-color', 'red'); 26 } else { 27 $('#test').css('background-color', 'black'); 28 } 29 }; 30 31 $('#btn2').on('click', function () { 32 ws1.send('csv出力'); 33 34 }); 35 36 ws1.onmessage = function (message) { 37 ('#test').append(message.data); 38 39 }; 40 }); 41 42 </script> 43 <style> 44 #btn1{ 45 width: 500px; 46 height: 100px; 47 font-size: 80px; 48 } 49 50 #test{ 51 display: inline-block; 52 background-color: black; 53 height:100px; 54 width:100px; 55 border-radius:50%; 56 margin-right: 500px; 57 margin-bottom: 100px; 58 margin-top: 10px; 59 } 60 61 #name{ 62 width: 500px; 63 height: 70px; 64 font-size: 60px; 65 } 66 67 #btn2{ 68 width: 500px; 69 height: 100px; 70 font-size: 80px; 71 } 72 </style> 73</head> 74<body> 75 <button id="btn1">OFF</button> 76 <div id="name">LED状態</div> 77 <div id="test"></div> 78 <button id="btn2">csv出力</button> 79</body> 80</html>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

websocket-serverはマルチスレッドには対応していないとREADMEに書かれています。
https://github.com/Pithikos/python-websocket-server


websocketsというライブラリは、Python標準のayncioを採用し、スレッドではなく非同期I/Oを利用することにより、複数処理の同時実行を可能にしています。
https://github.com/aaugustin/websockets

以下はwebsocketsを使ったサンプルプログラムです。GPIOの代わりに、LEDの点灯状態を外部テキストファイルからON/OFFという文字列として、読み込み/書き込みするようにしてあります。

python

1import asyncio 2import websockets 3from websockets.exceptions import ConnectionClosedOK 4 5async def sendMessage(websocket, path): 6 led_status = None 7 while True: 8 try: 9 with open("led_status.txt") as f: 10 gpio_input_27 = f.read().strip() 11 if gpio_input_27 != led_status: 12 if gpio_input_27 == "OFF": 13 await websocket.send("LED消灯中") 14 elif gpio_input_27 == "ON": 15 await websocket.send("LED点灯中") 16 led_status = gpio_input_27 17 await asyncio.sleep(1) 18 except ConnectionClosedOK: 19 break 20 21async def receivedMessage(websocket, path): 22 async for message in websocket: 23 print(message) 24 if message == "led_on": 25 gpio_output_14 = "ON" 26 elif message == "led_off": 27 gpio_output_14 = "OFF" 28 with open("led_status.txt", "w") as f: 29 f.write(gpio_output_14) 30 31async def ws_handlers(websocket, path): 32 await asyncio.gather( 33 sendMessage(websocket, path), 34 receivedMessage(websocket, path), 35 ) 36 37async def main(): 38 async with websockets.serve(ws_handlers, "localhost", 8765): 39 await asyncio.Future() 40 41try: 42 asyncio.run(main()) 43except KeyboardInterrupt: 44 pass

html

1<!DOCTYPE html> 2<html> 3<head> 4 <script src="http://code.jquery.com/jquery-latest.min.js"></script> 5 <script> 6 $(function() { 7 var ws = new WebSocket("ws://localhost:8765/"); 8 $('#btn1').on('click', function () { 9 if($('#btn1').text() == "OFF") { 10 $('#btn1').text("ON") 11 ws.send('led_on'); 12 } else { 13 $('#btn1').text("OFF") 14 ws.send('led_off'); 15 } 16 }); 17 ws.onmessage = function(message) { 18 if (message.data == 'LED点灯中') { 19 $('#test').css('background-color', 'red'); 20 $('#btn1').text("ON") 21 } else { 22 $('#test').css('background-color', 'black'); 23 $('#btn1').text("OFF") 24 } 25 }; 26 }); 27 </script> 28 <style> 29 #test{ 30 display: inline-block; 31 background-color: black; 32 height:100px; 33 width:100px; 34 border-radius:50%; 35 margin-right: 500px; 36 margin-bottom: 100px; 37 margin-top: 10px; 38 } 39 </style> 40</head> 41<body> 42 <button id="btn1">OFF</button> 43 <div id="name">LED状態</div> 44 <div id="test"></div> 45</body> 46</html>

投稿2021/08/29 11:22

etherbeg

総合スコア1195

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dyrobin

2021/08/30 11:08

ご回答ありがとうございました。 なるほど、websocketはmultithreadに対応してなかったのですね。 勉強になりました。 頂いたサンプルスクリプトで理解を深めます。
etherbeg

2021/08/30 11:28 編集

websocketがマルチスレッドに対応していないのではなく、websocket-serverというライブラリが、ユーザがマルチスレッドで使用することを想定した作りになっていない、ということだと思います。websocket-serverも内部では、複数クライアントに対応するために、マルチスレッドを使用しています。
dyrobin

2021/08/30 12:46

補足のご回答まで、ありがとうございます。 承知致しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問