标签存档: BroadLink

玩玩智能家居6:接入杜亚电动窗帘

之前还没有玩上 Domoticz 的时候,家里全套系统都是用的 Broadlink,在买窗帘的时候也想着要买电动的,因此很自然的买了支持 Broadlink 的杜亚窗帘电机,可以方便地与 Broadlink 的传感器进行联动。

后来用了 Domoticz,但是 Broadlink 的系统并没有开放 API,想要接入 Domotiz 系统就比较麻烦了。在网上看了一堆帖子之后,发现可以通过分析窗帘电机遥控器信号,然后自己使用 433M 射频模块来自己控制。

Controlling Blinds.com RF Dooya Motors with Arduino and Vera 这篇帖子中提供了一个 PDF,详细介绍了如何嗅探信号,以及杜亚窗帘电机遥控器信号的格式。

准备材料

发射和接收 433M 射频信号需要的材料很简单,只需要 433M 发送和接收模块就可以了,不超过 5 块钱。

再加上需要接入 Domoticz,加个 NodeMCU,完事。

嗅探信号

首先需要嗅探一下窗帘遥控器发出的信号,如果有专业的机器的话可以直接去嗅探 433M 射频信号,如果没有的话,也可以使用 433M 模块自制一个。

根据前面提到的 PDF 中介绍的方法,将一个 433M 模块与 3.5mm 耳机线连接,然后插在电脑上。

因为 MacBook Pro 没有自带专用麦克风插孔,因此还得去买一个 USB 转耳机接口模块,方便接入。另外为了给 433M 模块供电,直接把模块的 VCC 跟 GND 跟 NodeMCU 的 VIN 和 GND 在面包板上连接起来了。

接着就可以使用 Audacity 进行录音操作了:

找到有规律的波形之后放大,开始数格子:

数完格子就知道一个遥控器指令的格式了。

指令格式

一个完整杜亚窗帘遥控器指令是 32 位 + 16 位或 8 位命令位,前 32 位可能包含了窗帘 ID 信息,不过我并没有仔细研究,每个遥控器的都不太一样,也不用太纠结。

例如一个打开窗帘的指令可以像下面这样:

10111101010000011001101101100001 00010001 00011110

每个指令需要发送 6 遍,在发送指令之前,还有一个间隙指令,需要发送三遍。

其实理论上,杜亚窗帘电机使用固定码,并不需要知道指令格式是什么意义,只需要按采集到的波形原样重放就可以了。

发射信号

有了波形,有了指令,就很方便的去重放射频信号了,反正也没什么加密措施,窗帘电机是不认识是由遥控器发出的指令,还是由 433M 模块发出的指令。

把 433M 射频发射模块与一个 NodeMCU 相连,然后使用之前帖子里提供的 BlindsVera.ino 中的代码就可以发射信号了。天线可以简单的使用一根 16cm 左右的导线。

BlindsVera.ino 中的代码都有注释,下面说说关键的几部分。

定义发送管脚,以及指令 1 和 0 所占用的时间

#define SEND_DATA 3 //Data pin for RF Transmitter
#define ZERO_HIGH 395 //Delay for the high part of a 0 in microseconds
#define ZERO_LOW 687 //Delay for the low part of a 0 in microseconds
#define ONE_HIGH 750 //Delay for the high part of a 1 in microseconds
#define ONE_LOW 333//Delay for the low part of a 1 in microseconds

指令中的标准位

unsigned char standardBits1 = 0b00000111;
unsigned char standardBits2 = 0b01110000;
unsigned char standardBits3 = 0b01010101;
unsigned char standardBits4 = 0b11001011;

BlindsVera.ino 中把窗帘 ID 与标准位分离了,但是在实际使用中,其实标准位并不统一,每个遥控器的都会不一致,因此在实际使用中需要把这里的标准位替换为实际的标准位,也就是数格子得到的指令中的前 28 位。

发送指令

void separatorDelay(boolean upDown);
void endDelay();
void blindAction(int c, int a);

最后就是发送指令了,根据之前采集的格式,按顺序发送相应的指令就可以了。

换个思路

杜亚窗帘电机上本身已经带了有线接口,可以直接使用 NodeMCU+继电器的方式来控制,不用去模拟射频信号,每个电机都是使用一样的线序,处理起来更简单一点。

更好的选择

呃,小米的窗帘电机?也许 miio 或者 python-mirobo 会支持吧,相对而言小米还是开放一些的。

参考资料

  1. Controlling Blinds.com RF Dooya Motors with Arduino and Vera
  2. 智能家居:窗帘篇

使用 python-broadlink 发送 BroadLink A1 数据到 Domoticz

之前在 smzdm 上看一些物联网的文章时,看到 Domoticz 这个平台,好像还蛮符合我的需求的,文章里还介绍了使用 RMBridge 来使用 Domoticz 来控制 RM Pro。

但是 RMBridge 并不是特别方便,需要一直跑一个 Android 来作为指令中转,于是在 GitHub 上去找找看有没有其他项目来支持 BroadLink 的 RM 设备,然后就找到了 python-broadlink 这个项目。

在研究 python-broadlink 的代码过程中,发现它同时还支持 BroadLink 的 A1 空气质量监测仪,刚好我就有一个 A1 设备,于是准备试试看能不能把 A1 的数据更新到 Domoticz 平台上。

最终的效果如下图所示:

准备工作

因为我有一个 DSM,并且 Domoticz 有现成的 DSM Package,所以所有工作都是基于 DSM 完成的,需要的软件如下:

  • DSM 6
  • Domoticz v3.5876
  • python-broadlink

创建设备及虚拟传感器

安装完 Domoticz 后,需要创建虚拟设备以及虚拟传感器来接受数据。

在“设置》硬件”中创建一个虚拟设备,只用来创建虚拟传感器:

在刚刚创建的 BroadLink A1 设备上,选创建虚拟传感器,并选择“温度+湿度”:

使用同样的方式来创建两个“文本”类型的虚拟传感器,用来显示光照和声音。

创建完虚拟传感器后,可以在“设置》设备”中看到刚刚创建的虚拟传感器,这里需要记住的是“Idx”这一档,这在后面的代码中需要用到:

在 DSM 上部署更新脚本

先在 DSM 中创建一个共享文件夹 domoticz,用于存放相关的代码文件。

下载 python-broadlink 项目代码,将 broadlink 目录上传至 domoticz 共享文件夹中。

使用 DSM 文本编辑器,在 domoticz 共享文件夹中创建一个新的文件 broadlink-a1.py,内容如下:

#!/usr/bin/python
# -*- encoding: utf-8 -*-

A1_IP = '1.1.1.1' # 修改为 BroadLink A1 IP
A1_MAC = '00:00:00:00:00:00' # 修改为 BroadLink A1 MAC 地址
DOMOTICZ_IP = '1.1.1.1' # 修改为 Domoticz 服务器 IP
DOMOTICZ_PORT = 8084 # 修改为 Domoticz 服务端口

DEV_HUM_TEMP_IDX = 1 # 修改为“温度+湿度”虚拟传感器Idx
DEV_NOISE_IDX = 2 # 修改为“声音”虚拟传感器Idx
DEV_LIGHT_IDX = 3 #修改为“光照”虚拟传感器Idx

import broadlink
import requests
import urllib

a1 = broadlink.a1((A1_IP, 80), A1_MAC)
a1.auth()
data = a1.check_sensors_raw()

hum = data['humidity']
hum_stat = 0
if 45 < = hum <= 60:
  hum_stat = 1
elif hum < 40:
  hum_stat = 2
elif hum > 70:
  hum_stat = 3

# update temp and hum
url = "http://%s:%d/json.htm?type=command¶m=udevice&idx=%d&nvalue=0&svalue=%0.1f;%0.1f;%d" % (DOMOTICZ_IP, DOMOTICZ_PORT, DEV_HUM_TEMP_IDX, data['temperature'], hum, hum_stat)
requests.get(url)

# update noise
db = '未知'
noise = data['noise']
if noise == 0:
  db = '寂静'
elif noise == 1:
  db = '正常'
elif noise == 2:
  db = '吵闹'
db = urllib.quote(db)
url = "http://%s:%d/json.htm?type=command¶m=udevice&idx=%d&nvalue=0&svalue=%s" % (DOMOTICZ_IP, DOMOTICZ_PORT, DEV_NOISE_IDX, db)
requests.get(url)

# update light
light = data['light']
lux = '未知'
if light == 0:
  lux = '黑暗'
elif light == 1:
  lux = '昏暗'
elif light == 2:
  lux = '正常'
elif light == 3:
  lux = '明亮'
lux = urllib.quote(lux)
url = "http://%s:%d/json.htm?type=command¶m=udevice&idx=%d&nvalue=0&svalue=%s" % (DOMOTICZ_IP, DOMOTICZ_PORT, DEV_LIGHT_IDX, lux)
requests.get(url)

请注意需要修改对应 BroadLink A1 的 IP 以及 MAC 地址,以及 Domoticz 安装服务器的地址和端口,如果是以 DSM Package 的形式安装的,那么 IP 与 DSM 的 IP 同样,端口默认为 8084。

之后 domoticz 共享文件的目录应该是这样的:

添加计划任务定时更新 A1 数据

为了能定时更新 A1 数据到 Domoticz,需要在 DSM 中添加一个计划任务,按时运行 broadlink-a1.py 这个脚本。

在 DSM 的“控制面板”中找到“任务计划”,添加一个“计划的任务》用户定义的脚本”,将任务设置为每5分钟运行一次,并且任务设置中运行命令按如下设置:

为了测试脚本是否正确,可以在保存完任务后,选中刚刚创建的任务手动运行一次,如果数据正常上传到 Domoticz 的服务器,那么在 Domoticz 的“设置》设置”中可以看到对应虚拟传感器的最后通讯时间为刚刚运行任务的时间。

如果任务正确运行,也可以在 Domoticz 的温度面板中,也可以看到虚拟传感器会显示正确的温度以及湿度。

至此,所有工作已经完成,Domoticz 可以实时显示 A1 的数据并且记录曲线。

参考资料

  1. 开源IoT平台domoticz与百搭wifi模块esp8266 篇二:domoticz与broadlink的联接
  2. python-broadlink by mjg59
  3. Domoticz API/JSON URL’s

— EOF —