Flutter Dashロボット
FlutterでTCP通信例を作ったので、備忘録です。
Flutter Dashさんが左右に動く装置を、遠隔操作します。
TCP通信なのか、TELNET通信なのか、正確な名称はよくわかりませんが、
TELNETで接続後、コマンド「left」「right」で、Dashさんが左右に動かすことができる装置をコントロールします。
通信部分は以下を参照しました。
https://medium.com/flutter-community/working-with-sockets-in-dart-15b443007bc9
通信仕様
項目 | 設定値 |
---|---|
サーバーIP | 127.0.0.1 |
ポート | 5000 |
ログインID | なし |
パスワード | なし |
終端文字 | \r\n |
操作コマンド
コマンド | 説明 |
---|---|
left | Dashさんが左に動きます |
right | Dashさんが右に動きます |
操作方法
1 装置を起動する
2 コントローラを起動する
3 コントローラからConnectする
4 ボタンが有効になったら、左右に動かす
コントローラ
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => TcpClient(),
child: MaterialApp(
home: ClientPage(),
debugShowCheckedModeBanner: false,
),
),
);
}
class TcpClient with ChangeNotifier {
Socket? socket;
bool isConnect = false;
String serverResponse = '';
Future<void> connect() async {
try {
socket = await Socket.connect('127.0.0.1', 5000);
} catch (e) {
throw Exception('connect error!!');
}
// connect server
isConnect = true;
notifyListeners();
// listen for responses from the server
socket?.listen(
// handle data from the server
(Uint8List data) {
serverResponse = String.fromCharCodes(data).replaceAll('\r\n', '');
notifyListeners();
},
// handle errors
onError: (error) {
socket?.destroy();
},
// handle server ending connection
onDone: () {
isConnect = false;
socket?.destroy();
notifyListeners();
},
);
}
Future<void> sendMessage(String message) async {
socket?.write(message);
await Future.delayed(Duration(milliseconds: 500));
}
}
/// Fcontroller main page
class ClientPage extends StatefulWidget {
const ClientPage({Key? key}) : super(key: key);
@override
_ClientPageState createState() => _ClientPageState();
}
class _ClientPageState extends State<ClientPage> {
@override
Widget build(BuildContext context) {
var client = context.read<TcpClient>();
return Scaffold(
appBar: AppBar(
title: const Text('Fobot controller'),
),
body: Row(
children: [
TextButton(
onPressed: () {
client.connect();
},
child: Text('connect')),
const Padding(padding: EdgeInsets.all(3)),
ElevatedButton(
child: Icon(Icons.arrow_left_rounded),
onPressed: context.watch<TcpClient>().isConnect
? () {
client.sendMessage('left');
}
: null),
const Padding(padding: EdgeInsets.all(3)),
ElevatedButton(
child: Icon(Icons.arrow_right_rounded),
onPressed: context.watch<TcpClient>().isConnect
? () {
client.sendMessage('right');
}
: null),
],
),
);
}
}
装置
コントローラの動作確認用に作ったもの
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => TcpServer(),
child: MaterialApp(
home: ServerPage(),
),
),
);
}
/// network server
class TcpServer with ChangeNotifier {
String request = '';
/// constructor
TcpServer() {
start();
}
void start() async {
final server = await ServerSocket.bind("127.0.0.1", 5000);
server.listen((client) {
client.listen(
(Uint8List data) async {
request = String.fromCharCodes(data).replaceAll('\r\n', '');
client.write('ret:' + request + '\r\n');
notifyListeners();
},
// handle errors
onError: (error) {
client.close();
},
// handle the closing the connection
onDone: () {
client.close();
},
);
});
}
}
/// fobot server main page
class ServerPage extends StatefulWidget {
const ServerPage({Key? key}) : super(key: key);
@override
_ServerPageState createState() => _ServerPageState();
}
class _ServerPageState extends State<ServerPage> {
final positionMax = 10;
int position = 2;
@override
Widget build(BuildContext context) {
var req = context.watch<TcpServer>().request;
if (req == 'left') {
position = position - 1 < 0 ? 0 : position - 1;
} else if (req == 'right') {
position = position >= positionMax - 1 ? positionMax - 1 : position + 1;
}
return Scaffold(
body: Row(
children: List.generate(positionMax, (index) {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.black),
),
child: Icon(position == index ? Icons.flutter_dash : null));
})));
}
}