Flutter StreamBuilder和Python TCP套接字服务器Cant Connect



我正在尝试为IoT应用程序编写一个flutter应用程序。移动设备将通过WiFi连接到硬件,数据将通过tcp套接字发送。物联网硬件正在开发中,但我需要开始使用该应用程序。

我得到了一些关于python脚本的帮助,该脚本运行一个套接字并输出两个稍微随机化的正弦波。它工作得很好,我有一个python主机脚本连接到它,并在数据通过时绘制数据。我要假装这是传感器数据,所以我想用flutter连接到这个,这样我就可以开始处理我的UI等。

我尝试了1000种方法,但大部分都通过了:https://flutter.dev/docs/cookbook/networking/web-sockets.

我尝试过的另一件事是将nodejs与socket.io一起使用,并使用adhara\ocket_io包与flutter进行了通信,但其中有太多抽象内容,我担心它无法复制我从硬件中获得的内容。

以下是python代码:

import queue
import time
#import matplotlib.pyplot as plt
import math
from queue import Queue
import numpy as np
import random
import socket
import threading
import asyncio

# A Queue in which the wave threads will store their values
# We will use this queue to get the data we need to send to our clients
Q = queue.Queue()
# replace this with your own host ip
HOST = '192.168.0.13'
PORT = 65432
Afrequency = float(input('give the frequency of the data output wave A: '))
Aperiod = int(input('give the output period (multiples of pi) of wave A: '))
Bfrequency = float(input('give the frequency of data output wave B: '))
Bperiod = int(input('give the output period (multiples of pi) of wave B: '))
# this function will continuosly generate x and y values for a given sine wave
# it waits 1/freq seconds so our frequency matches the given input

def generateTuples(name, outputfrequency, outputperiod):
sincurveshift = 10
rmax = 1.25
rmin = 0.75
outputperiod = outputperiod * math.pi
numberOfPoints = outputfrequency * outputperiod
increment = (2 * math.pi) / numberOfPoints
xcounter = 0
while True:
jitterValue = rmin + (random.random() * (rmax - rmin))
x = xcounter * increment
sinValue = 5 * math.sin(x) + sincurveshift * jitterValue
partOfTheMessage = '%s(%09.2f,%09.2f)*' % (name, x, sinValue)
xcounter += 1
Q.put(partOfTheMessage)
time.sleep(1/outputfrequency)

# this is a thread that will be created each time a client connects
# it sends the total string with values from wave A and B
class clientThread(threading.Thread):
def __init__(self, clientAddress, clientSocket, q):
threading.Thread.__init__(self)
self.clientSocket = clientSocket
print("New client connected with address: " + str(clientAddress))
def run(self):
while True:
self.clientSocket.send(bytes(Q.get(), 'utf-8'))
time.sleep(0.1)

def main():
# first we start up 2 threads that will each generate a y value every 1/freq seconds
# we let them run in the background so we can move on to listening for clients
print('starting sine wave 1')
print('starting sine wave 2')
wave1 = threading.Thread(target=generateTuples, args=(
'A', Afrequency, Aperiod), daemon=True)
wave2 = threading.Thread(target=generateTuples, args=(
'B', Bfrequency, Bperiod), daemon=True)
wave1.start()
wave2.start()
time.sleep(1)
print('starting transmission')
# here we set up the host
# we continously look for clients and give each of them their own thread
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((HOST, PORT))
s.listen()
while True:
conn, addr = s.accept()
client = clientThread(addr, conn, queue)
client.start()

if __name__ == "__main__":
main()

这是我的颤振代码。

import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/io.dart';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MyApp Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'MyApp Mobile'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final channel = IOWebSocketChannel.connect('ws://192.168.0.13:65432');
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: StreamBuilder(
stream: channel.stream,
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
case ConnectionState.none:
print('trying to connect');
return LinearProgressIndicator();
case ConnectionState.active:
print("OMG ITS CONNECTED");
print(snapshot.data);
return Text(snapshot.data);
case ConnectionState.done:
return Text('Its done ${snapshot.data}');
}
return Text(snapshot.hasData ? '${snapshot.data}' : 'No Data');
},
)),
);
}
}

我正在用手机运行开发中的应用程序——不确定这是否有意义。非常感谢您的帮助!

N

编辑-我现在在python控制台中看到一个错误:

New client connected with address: ('192.168.0.16', 65020)
Exception in thread Thread-24:
Traceback (most recent call last):
File "C:UsersnickcAppDataLocalProgramsPythonPython38-32libthreading.py", line 932, in _bootstrap_inner
self.run()
File "host.py", line 62, in run
self.clientSocket.send(bytes(Q.get(), 'utf-8'))
ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine

所以它看起来像是连接了,然后中止了连接?

就像shubham在其中一个答案中提到的那样,我可以成功地连接并打印传入数据到控制台,使用:

Socket socket = await Socket.connect(host, port);
socket.listen((event) {
print(String.fromCharCodes(event));
});

我对web套接字通道包不太了解,但当我尝试运行您的代码时,我的客户端(电话(一连接,python代码就出现了管道破裂错误,看完这篇文章后,我认为客户端套接字不知怎的被关闭了。

但我可以使用dart的套接字包连接到您的python套接字这是代码

Socket socket = await Socket.connect(host, port);
socket.listen((event) {
log(String.fromCharCodes(event));
});

这是我得到的输出

[log] B(000051.07,000013.89)*
[log] B(000051.11,000013.26)*
[log] B(000051.14,000016.09)*
[log] B(000051.18,000013.77)*
[log] B(000051.21,000015.63)*
[log] B(000051.25,000013.78)*
[log] B(000051.29,000013.49)*
[log] B(000051.32,000016.75)*
[log] A(000103.50,000012.36)*
[log] A(000103.58,000009.93)*
[log] A(000103.67,000007.72)*
[log] A(000103.75,000009.02)*
[log] A(000103.83,000008.28)*

最新更新