flutter_hue 0.1.1 copy "flutter_hue: ^0.1.1" to clipboard
flutter_hue: ^0.1.1 copied to clipboard

An SDK designed for the Flutter framework that enables developers to easily integrate Philips Hue smart devices into their applications.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_hue/flutter_hue.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  static const double padding = 15.0;

  /// Whether or not the page is loading some async action.
  bool isLoading = false;

  /// The IP address of the bridges on the network.
  final List<String> bridgeIps = [];

  /// Controls the bridge discovery process.
  final DiscoveryTimeoutController timeoutController =
      DiscoveryTimeoutController(timeoutSeconds: 25);

  /// Cancels the "first contact" action.
  VoidCallback? onContactCancel;

  /// The bridge that [firstContact] decided to connect with.
  Bridge? bridge;

  /// All of the Philips Hue resources connected to [bridge].
  HueNetwork? hueNetwork;

  /// The light that is being worked with in the "writing data" section.
  Light? light;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Builder(
        builder: (context) => Scaffold(
          appBar: AppBar(
            title: const Text("Flutter Hue"),
            actions: isLoading
                ? [
                    Padding(
                      padding: const EdgeInsets.only(right: padding),
                      child: Row(
                        children: const [
                          Text("Loading... "),
                          Icon(Icons.query_builder),
                        ],
                      ),
                    ),
                  ]
                : null,
          ),
          body: SafeArea(
            child: SingleChildScrollView(
              child: Column(
                children: [
                  const SizedBox(height: padding),

                  sectionHeader("Getting Started"),

                  // DISCOVER BRIDGES
                  Column(
                    children: [
                      ElevatedButton(
                        onPressed: discoverBridges,
                        child: const Text("Discover Bridges"),
                      ),
                      Visibility(
                        visible: bridgeIps.isNotEmpty,
                        child: TextButton(
                          onPressed: () => showIps(context),
                          child: Text("Found ${bridgeIps.length} bridge IP"
                              "${bridgeIps.length == 1 ? "" : "s"}"),
                        ),
                      ),
                    ],
                  ),

                  const SizedBox(height: padding * 2),

                  // FIRST CONTACT
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton(
                        onPressed:
                            bridgeIps.isEmpty ? null : () => firstContact(),
                        child: const Text("First Contact"),
                      ),
                      const SizedBox(width: 11),
                      ElevatedButton(
                        onPressed: onContactCancel,
                        child: const Text("Cancel"),
                      ),
                    ],
                  ),

                  const SizedBox(height: padding * 2),

                  sectionHeader("Reading Data"),

                  // FETCH NETWORK
                  ElevatedButton(
                    onPressed: bridge == null ? null : fetchNetwork,
                    child: const Text("Fetch Network"),
                  ),

                  const SizedBox(height: padding * 2),

                  // FETCH BRIDGE
                  ElevatedButton(
                    onPressed: bridge == null ? null : fetchBridge,
                    child: const Text("Fetch Bridge"),
                  ),

                  const SizedBox(height: padding * 2),

                  // FETCH LIGHT
                  ElevatedButton(
                    onPressed: bridge == null ? null : fetchLight,
                    child: const Text("Fetch Light"),
                  ),

                  const SizedBox(height: padding * 2),

                  sectionHeader("Writing Data"),

                  // IDENTIFY LIGHT
                  ElevatedButton(
                    onPressed: light == null ? null : identifyLight,
                    child: const Text("Identify Light"),
                  ),

                  const SizedBox(height: padding * 2),

                  // TOGGLE LIGHT ON/OFF
                  ElevatedButton(
                    onPressed: light == null ? null : toggleLight,
                    child: const Text("Toggle Light on/off"),
                  ),

                  const SizedBox(height: padding * 2),

                  // LIGHT COLORS
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: padding),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        // RED
                        ElevatedButton(
                          onPressed:
                              light == null ? null : () => colorLight("red"),
                          child: const Text("Red"),
                        ),

                        // GREEN
                        ElevatedButton(
                          onPressed:
                              light == null ? null : () => colorLight("green"),
                          child: const Text("Green"),
                        ),

                        // BLUE
                        ElevatedButton(
                          onPressed:
                              light == null ? null : () => colorLight("blue"),
                          child: const Text("Blue"),
                        ),

                        // WHITE
                        ElevatedButton(
                          onPressed:
                              light == null ? null : () => colorLight("white"),
                          child: const Text("White"),
                        ),
                      ],
                    ),
                  ),

                  const SizedBox(height: padding),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }

  /// The titles and dividers that separate each group of buttons.
  Widget sectionHeader(String title) {
    return Column(
      children: [
        Row(
          children: [
            const SizedBox(width: padding),
            Text(
              title,
              style: const TextStyle(
                fontSize: padding,
                fontWeight: FontWeight.bold,
              ),
            ),
          ],
        ),
        const Padding(
          padding: EdgeInsets.symmetric(horizontal: padding),
          child: Divider(thickness: 2.0),
        ),
      ],
    );
  }

  /// Show the IP addresses of the bridges that have been found on the network.
  void showIps(BuildContext context) {
    showDialog<void>(
      context: context,
      builder: (context) {
        return AlertDialog(
          title: const Text("Bridge IP"),
          content: SingleChildScrollView(
            child: ListBody(
              children: bridgeIps.map((ip) => Text(ip)).toList(),
            ),
          ),
          actions: [
            TextButton(
              child: const Text("Ok"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  /// Searches the network for bridges.
  ///
  /// If any are found, their IP addresses are placed in the [bridgeIps] list.
  Future<void> discoverBridges() async {
    setState(() {
      isLoading = true;
    });

    List<String> bridges = await BridgeDiscoveryRepo.discoverBridges();

    setState(() {
      bridgeIps.addAll(bridges);
      isLoading = false;
    });
  }

  /// For the simplicity of this demo, this method only looks at the first
  /// bridge from the [bridgeIps] list.
  ///
  /// It attempts to establish contact with the bridge. This is when the user
  /// needs to press the button on their bridge.
  Future<void> firstContact() async {
    setState(() {
      onContactCancel = () => timeoutController.cancelDiscovery = true;
      isLoading = true;
    });

    bridge = await BridgeDiscoveryRepo.firstContact(
      bridgeIpAddr: bridgeIps.first,
      controller: timeoutController,
    );

    setState(() {
      onContactCancel = null;
      isLoading = false;
    });
  }

  /// Fetches all of the resources that are attached to [bridge].
  Future<void> fetchNetwork() async {
    setState(() {
      isLoading = true;
    });

    hueNetwork = HueNetwork(bridges: [bridge!]);

    await hueNetwork?.fetchAll();

    try {
      light = hueNetwork!.lights.first;
    } catch (_) {
      // Do nothing
    }

    setState(() {
      isLoading = false;
    });
  }

  /// This does nothing for the demo other than to show the code that is used to
  /// fetch a bridge object from JSON.
  Future<void> fetchBridge() async {
    setState(() {
      isLoading = true;
    });

    final List<Map<String, dynamic>>? res =
        await bridge!.getResource(ResourceType.bridge);

    try {
      // ignore: unused_local_variable
      Bridge myBridge = Bridge.fromJson(res?.first ?? {});
    } catch (_) {
      // res list was empty
    }

    // Shows a way to display the info in these objects.
    // log("Bridge Json - ${JsonTool.writeJson(res ?? {})}");
    // log("Bridge Object - ${JsonTool.writeJson(bridge.toJson(optimizeFor: OptimizeFor.dontOptimize))}");

    setState(() {
      isLoading = false;
    });
  }

  /// This does nothing for the demo other than to show the code that is used to
  /// fetch a light object from JSON.
  Future<void> fetchLight() async {
    setState(() {
      isLoading = true;
    });

    final Map<String, dynamic>? res =
        (await bridge!.getResource(ResourceType.light))?.first;

    // ignore: unused_local_variable
    Light light = Light.fromJson(res ?? {});

    setState(() {
      isLoading = false;
    });
  }

  /// Causes the light to "breath" to let the user know which light they are
  /// working with.
  Future<void> identifyLight() async {
    setState(() {
      isLoading = true;
    });

    Device lightDevice;

    try {
      lightDevice = hueNetwork!.devices
          // ignore: deprecated_member_use
          .firstWhere((device) => device.metadata.name == light!.metadata.name);
    } catch (_) {
      return;
    }

    lightDevice.identifyAction = "identify";

    await bridge!.put(lightDevice);

    setState(() {
      isLoading = false;
    });
  }

  /// Toggles [light] on and off.
  Future<void> toggleLight() async {
    setState(() {
      isLoading = true;
    });

    bool isOn = light!.isOn;

    light!.on.isOn = !isOn;

    await bridge!.put(light!);

    setState(() {
      isLoading = false;
    });
  }

  /// Changes the color of [light].
  Future<void> colorLight(String color) async {
    setState(() {
      isLoading = true;
    });

    double x;
    double y;

    if (color == "red") {
      x = 0.6718;
      y = 0.3184;
    } else if (color == "green") {
      x = 0.2487;
      y = 0.6923;
    } else if (color == "blue") {
      x = 0.1121;
      y = 0.1139;
    } else {
      x = 0.3127;
      y = 0.3127;
    }

    light = light!
        .copyWith(color: light!.color.copyWith(xy: LightColorXy(x: x, y: y)));

    await bridge!.put(light!);

    setState(() {
      isLoading = false;
    });
  }
}
25
likes
150
points
800
downloads

Publisher

verified publisherhexcat.dev

Weekly Downloads

An SDK designed for the Flutter framework that enables developers to easily integrate Philips Hue smart devices into their applications.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

collection, flutter, http, multicast_dns, path_provider

More

Packages that depend on flutter_hue