为你的圣诞灯构建一个应用程序

2021-12-28 08:43:42 浏览数 (1)

物联网不在互联网上

将你和你的家连接到互联网的产品并不短缺。每一个都会有一个WiFi设备连接到您的网络,以及另一组麦克风,每个麦克风都会在您的家中监听它们的特殊触发字。

在今天的帖子中,我们将构建一个小型web应用程序(以及iPhone/Android应用程序!)控制只有在家中且连接到家庭网络时才能工作的圣诞灯。

局域网工具

Jetson Nano是我最喜欢的构建本地化物联网项目的平台。这是一个ARM64设备,有四个内置USB端口,设计用于在边缘进行机器学习。

我们将把它用作Z-Wave U盘的服务器。Z-Wave是一种用于家庭自动化的协议。对我们来说,重要的是,它与您的WiFi分开运行。

在我的例子中,我把它连接到2个户外电灯开关上,用来打开和关闭我的圣诞灯。电灯开关有防水罩,上面有一个手动按钮。您可以按下按钮启用配对模式,也可以手动打开和关闭灯光。最后,还有在我的iPhone上运行的React原生应用程序。

通常,我不会尝试为这么小的项目构建iPhone应用程序。但Expo(https://expo.dev/)让在手机上运行代码成为了一种很棒的体验。它们通过应用程序和命令行自动构建并推送到您的手机上。

为你的圣诞灯构建API

我们要做的第一件事是检查以确保我们已在 Jetson Nano 的 USB 驱动器上安装并运行 Z-Wave 棒。

每次使用 Z-Wave 时,我都会忘记 Z-Wave 网络模型如何工作的细节。正因为如此,我喜欢打开一个 IPython 会话,并开始玩弄网络:

代码语言:javascript复制
import openzwave
from openzwave.option import ZWaveOption
from openzwave.network import ZWaveNetwork

# make sure these Z-wave commands get flushed with a time.sleep
# also, /dev/ttyACM0 is the name of my USB port for the Z-Stick

options = ZWaveOption('/dev/ttyACM0')
options.lock()

network = ZWaveNetwork(options)

# the next two lines start an IPython session in line
import IPython
IPython.embed()

从这里开始,我开始记住事情是如何工作的,并且看到它list(network.nodes.keys())给了我一个nodes连接到 Z-Wave 网络的列表。因为我使用的是 IPython,所以我还可以通过选项卡浏览每个对象以查看可用的函数。

但是您如何知道每个 Z-Wave 节点具有哪些功能?

一些 Z-Wave 设备内置了多个开关,每个开关都可能带有自己的调光器。要抓住开关,我们需要做一个list(network.nodes[node].get_switches.keys()).

综上所述,我们可以通过一个set_switch函数调用在每个节点上设置状态:

代码语言:javascript复制
node_list = list(network.nodes.keys())
for node in node_list:
    switches = list(network.nodes[node].get_switches().keys())
    if switches:
        if change['state'] == 'ON':
            network.nodes[node].set_switch(switches[0], True)
        else:
            network.nodes[node].set_switch(switches[0], False)

现在我知道如何影响更改,我可以在 Flask 中构建一个 API 来提供更改:

代码语言:javascript复制
@app.route('/state', methods=['GET', 'POST'])
def get_state():
    if request.method == 'GET':
        node_list = list(network.nodes.keys())
        ON = False
        for node in node_list:
            switches = list(network.nodes[node].get_switches().keys())
            if switches:
                state = network.nodes[node].get_switch_state(switches[0])
                if state:
                    ON = True
                    continue
        if ON:
            return jsonify({'state': 'ON'})

        return jsonify({'state': 'OFF'})

    change = request.json

    node_list = list(network.nodes.keys())
    for node in node_list:
        switches = list(network.nodes[node].get_switches().keys())
        if switches:
            if change['state'] == 'ON':
                network.nodes[node].set_switch(switches[0], True)
            else:
                network.nodes[node].set_switch(switches[0], False)
    time.sleep(2)
    return jsonify(change)

我添加了一个time.sleep,因为 Z-Wave 网络传播状态可能需要一些时间。两秒钟可能太长了,无法入睡,但是,嘿,它有效,而且我并不着急。

使用 Expo 构建 React Native 应用程序

同样,对于这样一个小项目来说,构建一个应用程序通常工作量太大。但是自从我构建应用程序以来已经有一段时间了,而且我一直在听说 React Native,所以我决定试一试。

我很惊讶能够在不到一个小时的时间内在我的手机上安装我的应用程序的构建版本。有一个名为 Expo 的新平台,它处理通常与部署 iPhone 应用程序相关的所有繁重工作。

确实,因为我的“应用程序”太小了(字面意思是一个按钮和一个状态ON或OFF),除了基本的示例应用程序之外,我真的没有什么可做的:

代码语言:javascript复制
import React, {useState, useEffect } from 'react';
import { StyleSheet, Text, View, Button, Alert } from 'react-native';

export default function App() {
  const [currentState, setCurrentState] = useState(0);

  const handlePress = e => {
    const newState = (currentState == 'ON') ? 'OFF' : 'ON'
    const data = {'state': newState}

    const requestOptions = {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data)
    }
    fetch('http://192.168.1.44:8050/state', requestOptions)
      .then(response => response.json())
      .then(res => setCurrentState(res.state))
  }

  useEffect(() => {
    fetch('http://192.168.1.44:8050/state').then(res => res.json()).then(data => {
      setCurrentState(data.state);
    })
  }, []);

  return (
    <View style={styles.container}>
      <Text>Lights are currently {currentState} </Text>
      <Button title="Toggle Lights" onPress={handlePress} />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

在这里,您可以在我的局域网上看到对我的 Flask 应用程序 API 的调用。我已经为我的 Jetson Nano 设置了一个静态 IP 地址,并且正在一个非标准端口上运行 Flask 服务器,8050. 我这样做是因为我的 Nano 上运行着其他 Flask 应用程序。

当应用程序打开时,GET会向/state资源发出请求。它返回一个 JSON 对象,其中包含 Z-Wave 开关的当前状态。如果打开,则认为是网络ON。

从这里,我们可以按下一个按钮来翻转状态。这会POST向/state资源发出请求,并具有所需的新状态。

我可以通过expo build:ios. 完成后,我可以打开 Expo 应用程序并控制我的圣诞灯饰。

任务完成!

代码在哪里?

所有代码都是开源的,并且存在于Github 上(https://github.com/burningion/minimum-viable-christmas-lights)。Flask 应用程序中还有一个视图,您也可以在浏览器中访问它来控制灯光。你可以在/网址上看到它。

我鼓励你让你的应用程序看起来比我的更好,并分享结果。

节日快乐! 本文翻译自:

https://www.makeartwithpython.com/blog/minimum-viable-christmas-lights/

0 人点赞