NFC(Near-field communication,近距离无线通讯)可以作为一种很好的验证方式,以一种方便的形式实现一些自动化,比如:
- 扫描 NFC 卡之后播放特定的音乐列表清单
- 利用 NFC 标籤激活房间中的场景
- 通过 NFC 卡开锁
- 读取后 NFC 标签打开设备详情页
- 等等
现在人人随身携带手机,手机也自带 NFC 功能,NFC 使用场景更加充满实用性和想象力。Home Assistant 在 App 中已为标籤编写特殊的 Home Assistant URL扫描 NFC 标籤后,可以触發 Home Assistant 应用并将标识符發送到 Home Assistant 实例处理。
不过不是所有手机都支持 NFC(如 iPhone 需要 iPhone XS、XR、iPhone 11 及以上可以后台读取 NFC 卡片)。有大大利用 ESPHome 自制了一个 NFC 读卡器,小弟跟着步骤踩了一遍坑,以下是步骤:
所需材料
1、ESP8266(或 D1 Mini,D1 mini 体积更小)
2、PN532 NFC 读卡器(PN532 可能是最好的 NFC 读写模块)
3、WS2812(非必须,用作读卡后的 LED 灯泡反馈)
4、蜂鸣器(非必须,作为读卡后的声音反馈)
5、3D 打印外(非必须),地址在这里
6、杜邦线若干
准备工作
如果使用 D1 Mini,可能需要焊接。
另外,确保将 PN532 上的开关设置为以下开关状态:
开关1:打开(向上)
开关2:关闭(向下)
刷机
确保 ESPHome 版本在 1.16.0 及以上,在 ESPHome 中新增一个 ESP8266 设备,在配置中加入以下代码(若无 WS2812 和蜂鸣器可以删去相应代码):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
| substitutions: devicename: tagreader friendly_name: TagReader
on_boot: priority: -10 then: - wait_until: api.connected: - logger.log: API is connected! - rtttl.play: "success:d=24,o=5,b=100:c,g,b" - light.turn_on: id: activity_led brightness: 100% red: 0% green: 0% blue: 100% flash_length: 500ms
switch: - platform: template name: "${friendly_name} Buzzer Enabled" id: buzzer_enabled icon: mdi:volume-high optimistic: true restore_state: true - platform: template name: "${friendly_name} LED enabled" id: led_enabled icon: mdi:alarm-light-outline optimistic: true restore_state: true
api: services: - service: rfidreader_tag_ok then: - rtttl.play: "beep:d=16,o=5,b=100:b"
- service: rfidreader_tag_ko then: - rtttl.play: "beep:d=8,o=5,b=100:b"
- service: play_rtttl variables: song_str: string then: - rtttl.play: !lambda 'return song_str;'
- service: write_tag_random then: - lambda: |- static const char alphanum[] = "0123456789abcdef"; std::string uri = "https://www.home-assistant.io/tag/"; for (int i = 0; i < 8; i++) uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; uri += "-"; for (int j = 0; j < 3; j++) { for (int i = 0; i < 4; i++) uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; uri += "-"; } for (int i = 0; i < 12; i++) uri += alphanum[random_uint32() % (sizeof(alphanum) - 1)]; auto message = new nfc::NdefMessage(); message->add_uri_record(uri); ESP_LOGD("tagreader", "Writing payload: %s", uri.c_str()); id(pn532_board).write_mode(message); - service: write_tag_id variables: tag_id: string then: - lambda: |- auto message = new nfc::NdefMessage(); std::string uri = "https://www.home-assistant.io/tag/"; uri += tag_id; message->add_uri_record(uri); id(pn532_board).write_mode(message); - service: clean_tag then: - lambda: 'id(pn532_board).clean_mode();'
- service: cancel_writing then: - lambda: 'id(pn532_board).read_mode();'
i2c: scan: False frequency: 400kHz
pn532_i2c: id: pn532_board on_tag: then: - homeassistant.tag_scanned: !lambda | if (!tag.has_ndef_message()) { ESP_LOGD("tagreader", "No NDEF"); return x; } auto message = tag.get_ndef_message(); auto records = message->get_records(); for (auto &record : records) { std::string payload = record->get_payload(); size_t pos = payload.find("https://www.home-assistant.io/tag/"); if (pos != std::string::npos) { return payload.substr(pos + 34); } } ESP_LOGD("tagreader", "Bad NDEF, fallback to uid"); return x; - if: condition: switch.is_on: buzzer_enabled then: - rtttl.play: "success:d=24,o=5,b=100:c,g,b" - if: condition: switch.is_on: led_enabled then: - light.turn_on: id: activity_led brightness: 100% red: 0% green: 100% blue: 0% flash_length: 500ms
output: - platform: esp8266_pwm pin: D7 id: buzzer
binary_sensor: - platform: status name: "${friendly_name} Status"
rtttl: output: buzzer
light: - platform: fastled_clockless chipset: WS2812 pin: D8 default_transition_length: 10ms num_leds: 1 rgb_order: GRB id: activity_led name: "${friendly_name} LED" restore_mode: ALWAYS_OFF
|
之后编译并下载固件,使用 NodeMCU PyFlasher 将固件刷入 ESP8266/D1 Mini。
连线
按照以下将 ESP8266 与 PN532 连线:
PN532 |
ESP8266 |
GND |
G |
VCC |
VIN |
SDA |
D2 |
SCL |
D1 |
LED 等与蜂鸣器可以按照以下连线:
最终效果如下:
使用
确保 Home Assistant版本在 0.115 及以上,待 NFC 读取器连接到与 HA 同一网络,Home Assistant 会自动發现 NFC 读取器。
之后从 Home Assistant 中的标籤界面中可以管理扫描的标籤(在 config->tag 下可以找到。