Две сопрограммы, работающие одновременно с использованием asyncio - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь создать программу, которая считывает данные, а также отправляет и получает данные с сервера через веб-сокет. Цель состоит в том, чтобы создать синхронизированные лампы, где есть две клиентские лампы и один сервер. Когда одна из ламп меняет состояние, она отправляет запрос на сервер, а сервер обновляет другую лампу. В настоящее время я застрял на клиентском коде. Я могу установить sh соединение через веб-сокет с сервером, считывать и отправлять данные на сервер, и я могу читать данные в светлых тонах. У меня проблема с запуском обеих этих задач одновременно. Я хотел бы сделать это асинхронно, чтобы избежать проблем с состоянием гонки. Я использую python 3.8 и asyncio.

Вот мой код клиента websocket:

async def init_connection(message):
  global CONNECTION_OPEN
  global CLIENT_WS
  uri = WS_URI
  async with websockets.connect(uri) as websocket:
      CONNECTION_OPEN = True
      CLIENT_WS = websocket
      # send init message
      await websocket.send(message)
      while CONNECTION_OPEN:
          await handleMessages(websocket, message)
      await websocket.send(json.dumps({'type': MessageType.Close.name, 'message': USERNAME}))
      await websocket.close()

Вот мое чтение в коде данных:

async def calculate_idle(t):
  global STATE
  global prevColor
  x_arr = []
  y_arr = []
  z_arr = []
  while t >= 0:
     x, y, z = lis3dh.acceleration
     print("Current colors")
     print(accel_to_color(x,y,z))
     x_arr.append(x)
     y_arr.append(y)
     z_arr.append(z)
     newColor = accel_to_color(x,y,z)
     # remember prev color
     do_fade(prevColor, newColor)
     #strip.fill((int(a_x), int(a_y), int(a_z), 0))
     #strip.show()
     prevColor = newColor
     time.sleep(.2)
     t -= .2
  is_idle = is_lamp_idle(np.std(x_arr), np.std(y_arr), np.std(z_arr))

  if is_idle and STATE == "NOT IDLE" and CONNECTION_OPEN:
      STATE = "IDLE"
      print("Sending color")
      await asyncio.sleep(1)
  elif is_idle and CONNECTION_OPEN:
      # Check for data
      STATE = "IDLE"
      print ("Receiving data")
      await asyncio.sleep(1)
  elif is_idle and not CONNECTION_OPEN:
     print ("Idle and not connected")
      rainbow_cycle(0.001)    # rainbow cycle with 1ms delay per step
      await asyncio.sleep(1)
  else:
      STATE = "NOT IDLE"
      await asyncio.sleep(1)
      print("Is not idle")

Вот код, который предполагается к t ie их вместе:

async def main():
    message = json.dumps({'type': "authentication", 'payload': {
                            'username': 'user1', 'secret': SHARED_SECRET}})
    loop = asyncio.get_event_loop()
    start_light = asyncio.create_task(calculate_idle(3))
    await asyncio.gather(init_connection(message), start_light)
asyncio.run(main())

Есть и другие функции, но предпосылка в том, что есть соединение через веб-сокет, отправляющее и получающее данные, и другой процесс, считывающий легкие данные. Мне также нужно иметь возможность прочитать текущее состояние источников света и установить текущее состояние источников света, поэтому я использовал глобальные переменные. В настоящее время он будет считывать индикаторы до тех пор, пока не выполнит команду await asyncio.sleep (1) при вычислении простоя, затем переключится на код веб-сокета и повредит получение данных с сервера. В идеале это чередуется между чтением текущего состояния и проверкой сообщений websocket. Если состояние изменится, оно отправит сообщение websocket.

Как я могу выполнить обе эти процедуры асинхронно и обмениваться данными между ними? Любая помощь приветствуется!

1 Ответ

0 голосов
/ 13 марта 2020

Благодаря комментариям user4815162342 , чтобы помочь сузить проблему. У моего вычисления простоя не было истинного времени, и я изменил time.sleep (.2), ​​чтобы ожидать asyncio.sleep (.2), ​​и я смог читать данные с сервера и индикаторов одновременно.

...