FlutterアプリからESP32の設定値を変更するためには、FlutterアプリからESP32にBLE経由で設定値を送信し、ESP32側でその値を反映する必要があります。以下に、そのための手順とコード例を示します。
1. Flutter側の実装
FlutterアプリからESP32に設定値を送信するために、sendConfigToDeviceメソッドを拡張して、設定値を含むデータを送信できるようにします。
void sendSettingsToDevice(BluetoothDevice device, Map<String, dynamic> settings) async {
try {
List<BluetoothService> services = await device.discoverServices();
for (BluetoothService service in services) {
for (BluetoothCharacteristic characteristic in service.characteristics) {
if (characteristic.uuid.toString().toLowerCase() == "6e400002-b5a3-f393-e0a9-e50e24dcca9e") {
String data = settings.entries.map((e) => "${e.key}:${e.value}").join("|");
await characteristic.write(data.codeUnits);
print("Sent settings: $data");
}
}
}
} catch (e) {
print("Error sending settings: $e");
}
}
このメソッドは、設定値を含むマップを受け取り、それを文字列に変換してESP32に送信します。
2. Flutter UIの拡張
設定値を変更するためのUIを追加します。例えば、スライダーやトグルボタンを使用して、ユーザーが設定値を変更できるようにします。
int hourDivision = 60;
int pumpOnPercentage = 50;
bool autoManualMode = true;
double autoTemperatureSetting = 25.0;
int manualTemperaturePercent = 30;
bool coolHeatMode = false;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BLE Device Settings'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Hour Division: $hourDivision"),
Slider(
value: hourDivision.toDouble(),
min: 1,
max: 120,
onChanged: (value) {
setState(() {
hourDivision = value.toInt();
});
},
),
Text("Pump On Percentage: $pumpOnPercentage"),
Slider(
value: pumpOnPercentage.toDouble(),
min: 0,
max: 100,
onChanged: (value) {
setState(() {
pumpOnPercentage = value.toInt();
});
},
),
Text("Auto Temperature Setting: $autoTemperatureSetting"),
Slider(
value: autoTemperatureSetting,
min: 10.0,
max: 40.0,
onChanged: (value) {
setState(() {
autoTemperatureSetting = value;
});
},
),
Text("Manual Temperature Percent: $manualTemperaturePercent"),
Slider(
value: manualTemperaturePercent.toDouble(),
min: 0,
max: 100,
onChanged: (value) {
setState(() {
manualTemperaturePercent = value.toInt();
});
},
),
SwitchListTile(
title: Text("Auto/Manual Mode"),
value: autoManualMode,
onChanged: (value) {
setState(() {
autoManualMode = value;
});
},
),
SwitchListTile(
title: Text("Cool/Heat Mode"),
value: coolHeatMode,
onChanged: (value) {
setState(() {
coolHeatMode = value;
});
},
),
ElevatedButton(
onPressed: () {
if (connectedDevice != null) {
Map<String, dynamic> settings = {
"hour_devision": hourDivision,
"pump_on_percentage": pumpOnPercentage,
"auto_manual_mode": autoManualMode,
"auto_temperature_setting": autoTemperatureSetting,
"manual_temperature_percent": manualTemperaturePercent,
"cool_heat_mode": coolHeatMode,
};
sendSettingsToDevice(connectedDevice!, settings);
}
},
child: Text("Send Settings"),
),
],
),
),
);
}
3. ESP32側の実装
ESP32側で、Flutterアプリから送信された設定値を解析し、対応する変数に設定します。
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
// 設定値を解析
int separatorIndex = rxValue.indexOf('|');
while (separatorIndex != -1) {
String setting = rxValue.substring(0, separatorIndex);
rxValue = rxValue.substring(separatorIndex + 1);
separatorIndex = rxValue.indexOf('|');
int colonIndex = setting.indexOf(':');
if (colonIndex != -1) {
String key = setting.substring(0, colonIndex);
String value = setting.substring(colonIndex + 1);
if (key == "hour_devision") {
hour_devision = value.toInt();
} else if (key == "pump_on_percentage") {
pump_on_percentage = value.toInt();
} else if (key == "auto_manual_mode") {
auto_manual_mode = value == "true";
} else if (key == "auto_temperature_setting") {
auto_temperature_setting = value.toFloat();
} else if (key == "manual_temperature_percent") {
manual_temperature_percent = value.toInt();
} else if (key == "cool_heat_mode") {
cool_heat_mode = value == "true";
}
}
}
}
}
このコードは、Flutterアプリから送信された設定値を解析し、対応する変数に設定します。
4. 全体の流れ
- Flutterアプリで設定値を変更し、「Send Settings」ボタンを押す。
- FlutterアプリがBLE経由で設定値をESP32に送信。
- ESP32が設定値を受信し、対応する変数に設定。
- ESP32が新しい設定値に基づいて動作を更新。
これにより、FlutterアプリからESP32の設定値をリアルタイムで変更できるようになります。
このウィジットだと前の機能が消えてしまいました。機能追加したい
前の機能を保持しつつ、新しい設定機能を追加するためには、既存のウィジェットに新しい設定用のUIを統合する必要があります。以下に、既存の機能を保持しつつ、新しい設定機能を追加する方法を示します。
1. Flutter側の実装
既存のbuildメソッドに新しい設定用のUIを追加します。ExpandedやColumnを使用して、既存のUIと新しいUIを並べて表示します。
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('BLE Device Selector'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Status: $status"),
if (connectedDevice != null) Text("Connected to: ${connectedDevice!.name ?? connectedDevice!.id.toString()}"),
Text("Received Data: $receivedData"),
DropdownButton<DeviceConfig>(
value: selectedConfig,
onChanged: (DeviceConfig? newValue) {
setState(() {
selectedConfig = newValue;
});
},
items: deviceConfigs.map<DropdownMenuItem<DeviceConfig>>((DeviceConfig config) {
return DropdownMenuItem<DeviceConfig>(
value: config,
child: Text(config.name),
);
}).toList(),
),
ElevatedButton(
onPressed: () {
if (connectedDevice != null && selectedConfig != null) {
sendConfigToDevice(connectedDevice!, selectedConfig!);
}
},
child: Text("Send Config"),
),
Expanded(
child: ListView.builder(
itemCount: devices.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(devices[index].name ?? "Unknown Device (${devices[index].id})"),
subtitle: Text(devices[index].id.toString()),
onTap: () => connectToDevice(devices[index]),
);
},
),
),
ElevatedButton(
onPressed: startScan,
child: Text("Rescan"),
),
// 新しい設定用のUIを追加
Divider(),
Text("Settings", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
Text("Hour Division: $hourDivision"),
Slider(
value: hourDivision.toDouble(),
min: 1,
max: 120,
onChanged: (value) {
setState(() {
hourDivision = value.toInt();
});
},
),
Text("Pump On Percentage: $pumpOnPercentage"),
Slider(
value: pumpOnPercentage.toDouble(),
min: 0,
max: 100,
onChanged: (value) {
setState(() {
pumpOnPercentage = value.toInt();
});
},
),
Text("Auto Temperature Setting: $autoTemperatureSetting"),
Slider(
value: autoTemperatureSetting,
min: 10.0,
max: 40.0,
onChanged: (value) {
setState(() {
autoTemperatureSetting = value;
});
},
),
Text("Manual Temperature Percent: $manualTemperaturePercent"),
Slider(
value: manualTemperaturePercent.toDouble(),
min: 0,
max: 100,
onChanged: (value) {
setState(() {
manualTemperaturePercent = value.toInt();
});
},
),
SwitchListTile(
title: Text("Auto/Manual Mode"),
value: autoManualMode,
onChanged: (value) {
setState(() {
autoManualMode = value;
});
},
),
SwitchListTile(
title: Text("Cool/Heat Mode"),
value: coolHeatMode,
onChanged: (value) {
setState(() {
coolHeatMode = value;
});
},
),
ElevatedButton(
onPressed: () {
if (connectedDevice != null) {
Map<String, dynamic> settings = {
"hour_devision": hourDivision,
"pump_on_percentage": pumpOnPercentage,
"auto_manual_mode": autoManualMode,
"auto_temperature_setting": autoTemperatureSetting,
"manual_temperature_percent": manualTemperaturePercent,
"cool_heat_mode": coolHeatMode,
};
sendSettingsToDevice(connectedDevice!, settings);
}
},
child: Text("Send Settings"),
),
],
),
),
);
}
2. 既存の機能を保持
上記のコードでは、既存のBLEデバイススキャンや接続機能を保持しつつ、新しい設定用のUIを追加しています。Expandedウィジェットを使用して、デバイスリストと設定用のUIを並べて表示しています。
3. ESP32側の実装
ESP32側のコードは変更なしで、既存のonWriteメソッドが新しい設定値を処理します。
void onWrite(BLECharacteristic *pCharacteristic) {
String rxValue = pCharacteristic->getValue();
if (rxValue.length() > 0) {
// 設定値を解析
int separatorIndex = rxValue.indexOf('|');
while (separatorIndex != -1) {
String setting = rxValue.substring(0, separatorIndex);
rxValue = rxValue.substring(separatorIndex + 1);
separatorIndex = rxValue.indexOf('|');
int colonIndex = setting.indexOf(':');
if (colonIndex != -1) {
String key = setting.substring(0, colonIndex);
String value = setting.substring(colonIndex + 1);
if (key == "hour_devision") {
hour_devision = value.toInt();
} else if (key == "pump_on_percentage") {
pump_on_percentage = value.toInt();
} else if (key == "auto_manual_mode") {
auto_manual_mode = value == "true";
} else if (key == "auto_temperature_setting") {
auto_temperature_setting = value.toFloat();
} else if (key == "manual_temperature_percent") {
manual_temperature_percent = value.toInt();
} else if (key == "cool_heat_mode") {
cool_heat_mode = value == "true";
}
}
}
}
}
4. 全体の流れ
- Flutterアプリで既存の機能(BLEデバイスのスキャン、接続、設定送信)を使用。
- 新しい設定用のUIで設定値を変更し、「Send Settings」ボタンを押す。
- FlutterアプリがBLE経由で設定値をESP32に送信。
- ESP32が設定値を受信し、対応する変数に設定。
- ESP32が新しい設定値に基づいて動作を更新。
これにより、既存の機能を保持しつつ、新しい設定機能を追加することができます。
