Использование Dash вместе с API сокетов - PullRequest
0 голосов
/ 25 января 2019

Я хочу создать веб-приложение, отображающее данные с датчиков в реальном времени из сетки наших пользовательских устройств. Я знаком с фреймворком Dash Python, поэтому решил использовать его и в этот раз. Одно из устройств взаимодействует со щитом W5500, и это база для запуска. К сожалению, когда я попытался объединить Dash с BSD-сокетами в python, я получил странное поведение как в Linux (Ubuntu 18.04), так и в Windows 10.

При запуске любого приложения Dash с открывающимся сокетом я получаю сообщение об ошибке, утверждающее, что пара порт / адрес повторно используется, когда все еще открыт (errno 98 в Linux или WinError 10048), хотя я явно использую разные интерфейсы и / или порты - приложение Dash размещен на локальном порте 8050, и я использую назначенный IP и другой порт для сокета. Я пробовал разные подходы с пакетом _thread, но все равно появляется та же ошибка.

Мне также известно, что я не принимаю соединение в этом примере, но поскольку bind / listen не работает, я не поместил его здесь.

Если я обслуживаю приложение в отдельном потоке, один из них никоим образом не реагирует, поэтому либо я не обслуживаю приложение, либо не получаю никаких данных. Я прилагаю пример кода учебника Dash, модифицированного таким образом, чтобы показать проблему.

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import socket
import _thread
import atexit

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print('socet created')
PORT = 9001
IP_ADDR = '192.168.0.38'
s.bind((IP_ADDR, PORT))

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    dcc.Input(id='my-id', value='initial value', type='text'),
    html.Div(id='my-div')
])
@app.callback(
    Output(component_id='my-div', component_property='children'),
    [Input(component_id='my-id', component_property='value')]
)
def update_output_div(input_value):
    return 'You\'ve entered "{}"'.format(input_value)

def on_close():
    global s
    print('port closed')
    s.close()

def get_data(dummy):
    while True:
        data, addr = s.recvfrom(1024)
        print('received: ' + str(list(data)))

def run_app(dummy):
    app.run_server(debug=True)
    #while True:
    #     pass

if __name__ == '__main__':
    atexit.register(on_close)

    _thread.start_new_thread( get_data, ('data',))
    #_thread.start_new_thread( run_app, ('app',) )
    app.run_server(debug=True, host = '127.0.0.1')
    while True:
        pass

Все, что я действительно хочу, - это вначале упростить вещи и изменять списки представляющих интерес значений, а затем наносить их на динамический график (независимо от того, обновлялись они или нет) каждые n миллисекунд.

Если кому-то удалось использовать Dash вместе с сокетом, предоставьте некоторую помощь или советы, как установить прослушивание сокета TCP.

1 Ответ

0 голосов
/ 08 мая 2019

Вы можете попробовать что-то вроде этого:

app.layout = html.Div([
    dcc.Input(id='my-id', value='initial value', type='text'),
    html.Div(id='my-div'),
    html.Div(id='my-hidden-div', style='hidden')
    ])

@app.callback(
    [Output(component_id='my-div', component_property='children'),
     Output(component_id='my-hidden-div', component_property='children')
    [State(component_id='my-hidden-div', component_property='children')]
)
def get_data(dummy):
    while True:
        data, addr = s.recvfrom(1024, timeout=0.1)
        print('received: ' + str(list(data)))

    return str(list(data)), str(list(data))

В этом случае обратный вызов get_data запускается всякий раз, когда изменяется my-hidden-div.Время ожидания recvfrom истекает через 100 мс, затем выплевывает значение обратно в my-hidden-div, который затем вызывает обратный вызов get_data.

Я не знаю, работает ли это или нет.

...