各種設定をflutterアプリから変更する方法

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. 全体の流れ

  1. Flutterアプリで設定値を変更し、「Send Settings」ボタンを押す。
  2. FlutterアプリがBLE経由で設定値をESP32に送信。
  3. ESP32が設定値を受信し、対応する変数に設定。
  4. ESP32が新しい設定値に基づいて動作を更新。

これにより、FlutterアプリからESP32の設定値をリアルタイムで変更できるようになります。

このウィジットだと前の機能が消えてしまいました。機能追加したい

avatar

Ask GPT

前の機能を保持しつつ、新しい設定機能を追加するためには、既存のウィジェットに新しい設定用のUIを統合する必要があります。以下に、既存の機能を保持しつつ、新しい設定機能を追加する方法を示します。

1. Flutter側の実装

既存のbuildメソッドに新しい設定用のUIを追加します。ExpandedColumnを使用して、既存の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. 全体の流れ

  1. Flutterアプリで既存の機能(BLEデバイスのスキャン、接続、設定送信)を使用。
  2. 新しい設定用のUIで設定値を変更し、「Send Settings」ボタンを押す。
  3. FlutterアプリがBLE経由で設定値をESP32に送信。
  4. ESP32が設定値を受信し、対応する変数に設定。
  5. ESP32が新しい設定値に基づいて動作を更新。

これにより、既存の機能を保持しつつ、新しい設定機能を追加することができます。

タイトルとURLをコピーしました