mirror of
https://github.com/arendst/Tasmota.git
synced 2025-08-10 03:17:42 +00:00
Merge branch 'development' into sm16716
This commit is contained in:
commit
7b93df4978
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ build
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
*.bak
|
||||
|
@ -14,6 +14,7 @@ TasmotaSerial KEYWORD1
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
hardwareSerial KEYWORD2
|
||||
read KEYWORD2
|
||||
write KEYWORD2
|
||||
available KEYWORD2
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TasmotaSerial",
|
||||
"version": "2.2.0",
|
||||
"version": "2.3.0",
|
||||
"keywords": [
|
||||
"serial", "io", "TasmotaSerial"
|
||||
],
|
@ -1,5 +1,5 @@
|
||||
name=TasmotaSerial
|
||||
version=2.2.0
|
||||
version=2.3.0
|
||||
author=Theo Arends
|
||||
maintainer=Theo Arends <theo@arends.com>
|
||||
sentence=Implementation of software serial with hardware serial fallback for ESP8266.
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TasmotaSerial.cpp - Minimal implementation of software serial for Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends
|
||||
Copyright (C) 2019 Theo Arends
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -100,7 +100,7 @@ TasmotaSerial::TasmotaSerial(int receive_pin, int transmit_pin, int hardware_fal
|
||||
m_buffer = (uint8_t*)malloc(TM_SERIAL_BUFFER_SIZE);
|
||||
if (m_buffer == NULL) return;
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /TM_SERIAL_BAUDRATE;
|
||||
m_bit_time = F_CPU / TM_SERIAL_BAUDRATE;
|
||||
pinMode(m_rx_pin, INPUT);
|
||||
tms_obj_list[m_rx_pin] = this;
|
||||
attachInterrupt(m_rx_pin, ISRList[m_rx_pin], FALLING);
|
||||
@ -145,7 +145,7 @@ bool TasmotaSerial::begin(long speed, int stop_bits) {
|
||||
}
|
||||
} else {
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bit_time = ESP.getCpuFreqMHz() *1000000 /speed;
|
||||
m_bit_time = F_CPU / speed;
|
||||
m_high_speed = (speed > 9600);
|
||||
}
|
||||
return m_valid;
|
||||
@ -257,7 +257,7 @@ void TasmotaSerial::rxRead()
|
||||
TM_SERIAL_WAIT;
|
||||
}
|
||||
// Store the received value in the buffer unless we have an overflow
|
||||
int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE;
|
||||
unsigned int next = (m_in_pos+1) % TM_SERIAL_BUFFER_SIZE;
|
||||
if (next != (int)m_out_pos) {
|
||||
m_buffer[m_in_pos] = rec;
|
||||
m_in_pos = next;
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
TasmotaSerial.h - Minimal implementation of software serial for Tasmota
|
||||
|
||||
Copyright (C) 2018 Theo Arends
|
||||
Copyright (C) 2019 Theo Arends
|
||||
|
||||
This library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -22,7 +22,7 @@
|
||||
/*********************************************************************************************\
|
||||
* TasmotaSerial supports up to 115200 baud with fixed buffer size of 64 bytes using optional no iram
|
||||
*
|
||||
* Based on EspSoftwareSerial v3.3.1 by Peter Lerup (https://github.com/plerup/espsoftwareserial)
|
||||
* Based on EspSoftwareSerial v3.4.3 by Peter Lerup (https://github.com/plerup/espsoftwareserial)
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define TM_SERIAL_BAUDRATE 9600 // Default baudrate
|
@ -65,7 +65,7 @@ build_flags = ${esp82xx_defaults.build_flags}
|
||||
-DVTABLES_IN_FLASH
|
||||
|
||||
[core_2_5_0]
|
||||
; *** Esp8266 core for Arduino version Core 2.5.0 beta3 tested for Tasmota
|
||||
; *** Esp8266 core for Arduino version 2.5.0 release (still not available via platformio)
|
||||
platform = https://github.com/Jason2866/platform-espressif8266.git#Tasmota
|
||||
build_flags = ${esp82xx_defaults.build_flags}
|
||||
-Wl,-Teagle.flash.1m.ld
|
||||
@ -130,12 +130,12 @@ board_build.flash_mode = dout
|
||||
|
||||
platform = ${core_active.platform}
|
||||
build_flags = ${core_active.build_flags}
|
||||
; -DUSE_CLASSIC
|
||||
; -DBE_MINIMAL
|
||||
; -DUSE_SENSORS
|
||||
; -DUSE_BASIC
|
||||
; -DUSE_KNX_NO_EMULATION
|
||||
; -DUSE_DISPLAYS
|
||||
; -DFIRMWARE_CLASSIC
|
||||
; -DFIRMWARE_MINIMAL
|
||||
; -DFIRMWARE_SENSORS
|
||||
; -DFIRMWARE_BASIC
|
||||
; -DFIRMWARE_KNX_NO_EMULATION
|
||||
; -DFIRMWARE_DISPLAYS
|
||||
; -DUSE_CONFIG_OVERRIDE
|
||||
|
||||
; *** Fix espressif8266@1.7.0 induced undesired all warnings
|
||||
@ -184,7 +184,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DBE_MINIMAL
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_MINIMAL
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
@ -198,7 +198,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_BASIC
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_BASIC
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
@ -212,7 +212,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_CLASSIC
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_CLASSIC
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
@ -226,7 +226,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_KNX_NO_EMULATION
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_KNX_NO_EMULATION
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
@ -240,7 +240,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_SENSORS
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_SENSORS
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
@ -254,7 +254,7 @@ board = ${common.board}
|
||||
board_build.flash_mode = ${common.board_build.flash_mode}
|
||||
board_build.f_cpu = ${common.board_build.f_cpu}
|
||||
build_unflags = ${common.build_unflags}
|
||||
build_flags = ${common.build_flags} -DUSE_DISPLAYS
|
||||
build_flags = ${common.build_flags} -DFIRMWARE_DISPLAYS
|
||||
monitor_speed = ${common.monitor_speed}
|
||||
upload_port = ${common.upload_port}
|
||||
upload_resetmethod = ${common.upload_resetmethod}
|
||||
|
@ -1,9 +1,19 @@
|
||||
/* 6.4.1.14 20190203
|
||||
/* 6.4.1.15 20190208
|
||||
* Change image name BE_MINIMAL to FIRMWARE_MINIMAL (#5106)
|
||||
* Change image names USE_xyz to FIRMWARE_xyz (#5106)
|
||||
*
|
||||
* 6.4.1.14 20190203
|
||||
* Add SetOption32 until SetOption49 diagnostic information to Status 3 report as replacement for second property value in SetOption property name
|
||||
* Add Resolution property to Status 3 report providing previous SetOption second value property
|
||||
* Fix IR local echo
|
||||
* Add user configuration of HLW8012 and HJL-01/BL0937 Energy Monitoring as used in Sonoff S31, Pow Ra and many Tuya based devices
|
||||
* Add user configuration of MCP39F501 Energy Monitoring as used in Shelly2
|
||||
* Add support for multiple ADS1115 I2C devices (#5083)
|
||||
* Add rule support for "==", "!=" ">=" and "<=" (#5122)
|
||||
* Add Hass status sensor (#5139)
|
||||
* Change GUI weblog solving possible empty screens (#5154)
|
||||
* Change PN532 support from I2C to Serial for more stability (#5162)
|
||||
* Add MHZ19 Temperature as Domoticz Temperature selection (#5128)
|
||||
*
|
||||
* 6.4.1.13 20190130
|
||||
* Add command SetOption36 to control boot loop default restoration (#4645, #5063)
|
||||
|
@ -160,6 +160,7 @@
|
||||
#define D_JSON_ZERO_POINT_CALIBRATION "Zero Point Calibration"
|
||||
|
||||
#define D_RSLT_ENERGY "ENERGY"
|
||||
#define D_RSLT_HASS_STATE "HASS_STATE"
|
||||
#define D_RSLT_INFO "INFO"
|
||||
#define D_RSLT_MARGINS "MARGINS"
|
||||
#define D_RSLT_POWER "POWER"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Активиране на SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Povol SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 aktivieren"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Ενεργοποίηση SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Enable SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Habilitar SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Activer SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Enable SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 engedélyezése"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Abilita SM16716"
|
||||
|
@ -554,6 +554,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 inschakelen"
|
||||
|
@ -554,6 +554,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Włącz SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Habilitar SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Enable SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Enable SM16716"
|
||||
|
@ -554,6 +554,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Povoľ SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Aktivera SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "SM16716 Aktif"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Увімкнений SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "启用 SM16716"
|
||||
|
@ -553,6 +553,8 @@
|
||||
#define D_SENSOR_MCP39F5_RST "MCP39F5 Rst"
|
||||
#define D_SENSOR_CSE7766_TX "CSE7766 Tx"
|
||||
#define D_SENSOR_CSE7766_RX "CSE7766 Rx"
|
||||
#define D_SENSOR_PN532_TX "PN532 Tx"
|
||||
#define D_SENSOR_PN532_RX "PN532 Rx"
|
||||
#define D_SENSOR_SM16716_CLK "SM16716 CLK"
|
||||
#define D_SENSOR_SM16716_DAT "SM16716 DAT"
|
||||
#define D_SENSOR_SM16716_POWER "Enable SM16716"
|
||||
|
@ -326,9 +326,6 @@
|
||||
// #define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code)
|
||||
// #define USE_RTC_ADDR 0x68 // Default I2C address 0x68
|
||||
// #define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
|
||||
// #define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k7 code, 164 bytes of mem)
|
||||
// #define USE_PN532_DATA_FUNCTION // Enable PN532 DATA Usage using Sensor15 command (+1k6 code, 316 bytes of mem)
|
||||
// #define USE_PN532_CAUSE_EVENTS // Enable PN532 driver to cause event's on card read in addition to immediate telemetry (+64 bytes code, 48 bytes mem)
|
||||
// #define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code)
|
||||
|
||||
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
|
||||
@ -378,6 +375,9 @@
|
||||
#define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code)
|
||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer
|
||||
//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code)
|
||||
//#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
// #define USE_PN532_DATA_FUNCTION // Add sensor40 command support for erase, setting data block content (+1k7 code, 388 bytes mem)
|
||||
// #define USE_PN532_DATA_RAW // Allow DATA block to be used by non-alpha-numberic data (+ 80 bytes code, 48 bytes ram)
|
||||
|
||||
// Power monitoring sensors -----------------------
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
@ -431,12 +431,12 @@
|
||||
* See RELEASENOTES.md for selected features
|
||||
\*********************************************************************************************/
|
||||
|
||||
//#define USE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager
|
||||
//#define USE_BASIC // Create sonoff-basic with no sensors
|
||||
//#define USE_SENSORS // Create sonoff-sensors with useful sensors enabled
|
||||
//#define USE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation
|
||||
//#define USE_DISPLAYS // Create sonoff-display with display drivers enabled
|
||||
//#define BE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC
|
||||
//#define FIRMWARE_CLASSIC // Create sonoff-classic with initial configuration tools WPS, SmartConfig and WifiManager
|
||||
//#define FIRMWARE_BASIC // Create sonoff-basic with no sensors
|
||||
//#define FIRMWARE_SENSORS // Create sonoff-sensors with useful sensors enabled
|
||||
//#define FIRMWARE_KNX_NO_EMULATION // Create sonoff-knx with KNX but without Emulation
|
||||
//#define FIRMWARE_DISPLAYS // Create sonoff-display with display drivers enabled
|
||||
//#define FIRMWARE_MINIMAL // Create sonoff-minimal as intermediate firmware for OTA-MAGIC
|
||||
|
||||
/*********************************************************************************************\
|
||||
* No user configurable items below
|
||||
|
@ -391,7 +391,7 @@ void SettingsSave(uint8_t rotate)
|
||||
* stop_flash_rotate 0 = Allow flash slot rotation (SetOption12 0)
|
||||
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
||||
*/
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if ((GetSettingsCrc() != settings_crc) || rotate) {
|
||||
if (1 == rotate) { // Use eeprom flash slot only and disable flash rotate from now on (upgrade)
|
||||
stop_flash_rotate = 1;
|
||||
@ -441,7 +441,7 @@ void SettingsSave(uint8_t rotate)
|
||||
|
||||
settings_crc = Settings.cfg_crc;
|
||||
}
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
RtcSettingsSave();
|
||||
}
|
||||
|
||||
@ -487,12 +487,12 @@ void SettingsLoad(void)
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if (!settings_location || (Settings.cfg_holder != (uint16_t)CFG_HOLDER)) { // Init defaults if cfg_holder differs from user settings in my_user_config.h
|
||||
SettingsDefault();
|
||||
}
|
||||
settings_crc = GetSettingsCrc();
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
|
||||
RtcSettingsLoad();
|
||||
}
|
||||
@ -504,7 +504,7 @@ void SettingsErase(uint8_t type)
|
||||
1 = Erase SDK parameter area at end of linker memory model (0x0FDxxx - 0x0FFFFF) solving possible wifi errors
|
||||
*/
|
||||
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
bool result;
|
||||
|
||||
uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1;
|
||||
@ -533,7 +533,7 @@ void SettingsErase(uint8_t type)
|
||||
}
|
||||
OsWatchLoop();
|
||||
}
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
}
|
||||
|
||||
// Copied from 2.4.0 as 2.3.0 is incomplete
|
||||
|
@ -1957,7 +1957,7 @@ void Every250mSeconds(void)
|
||||
ota_retry_counter--;
|
||||
if (ota_retry_counter) {
|
||||
strlcpy(mqtt_data, GetOtaUrl(log_data, sizeof(log_data)), sizeof(mqtt_data));
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if (RtcSettings.ota_loader) {
|
||||
char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it
|
||||
char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin
|
||||
@ -1969,7 +1969,7 @@ void Every250mSeconds(void)
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s-" D_JSON_MINIMAL "%s"), mqtt_data, ech); // Minimal filename must be filename-minimal
|
||||
}
|
||||
}
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "%s"), mqtt_data);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2)
|
||||
@ -1980,14 +1980,14 @@ void Every250mSeconds(void)
|
||||
ota_result = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(OTAclient, mqtt_data));
|
||||
#endif
|
||||
if (!ota_result) {
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
int ota_error = ESPhttpUpdate.getLastError();
|
||||
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Ota error %d"), ota_error);
|
||||
// AddLog(LOG_LEVEL_DEBUG);
|
||||
if ((HTTP_UE_TOO_LESS_SPACE == ota_error) || (HTTP_UE_BIN_FOR_WRONG_FLASH == ota_error)) {
|
||||
RtcSettings.ota_loader = 1; // Try minimal image next
|
||||
}
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
ota_state_flag = 2; // Upgrade failed - retry
|
||||
}
|
||||
}
|
||||
@ -2590,10 +2590,10 @@ void setup(void)
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_PROJECT " %s %s " D_VERSION " %s%s-" ARDUINO_ESP8266_RELEASE),
|
||||
PROJECT, Settings.friendlyname[0], my_version, my_image);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
#ifdef BE_MINIMAL
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_WARNING_MINIMAL_VERSION));
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
|
||||
RtcInit();
|
||||
|
||||
|
@ -55,7 +55,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
* Provide an image with useful supported sensors enabled
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_SENSORS
|
||||
#ifdef FIRMWARE_SENSORS
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 3
|
||||
@ -92,7 +92,6 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
//#define USE_MPU6050 // Enable MPU6050 sensor (I2C address 0x68 AD0 low or 0x69 AD0 high) (+2k6 code)
|
||||
//#define USE_DS3231 // Enable DS3231 external RTC in case no Wifi is avaliable. See docs in the source file (+1k2 code)
|
||||
//#define USE_MGC3130 // Enable MGC3130 Electric Field Effect Sensor (I2C address 0x42) (+2k7 code, 0k3 mem)
|
||||
//#define USE_PN532_I2C // Enable PN532 - Near Field Communication (NFC) controller (+1k6 code)
|
||||
//#define USE_MAX44009 // Enable MAX44009 Ambient Light sensor (I2C addresses 0x4A and 0x4B) (+0k8 code)
|
||||
#define USE_MHZ19 // Add support for MH-Z19 CO2 sensor (+2k code)
|
||||
#define USE_SENSEAIR // Add support for SenseAir K30, K70 and S8 CO2 sensor (+2k3 code)
|
||||
@ -114,6 +113,8 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#define TUYA_DIMMER_ID 0 // Default dimmer Id
|
||||
#endif
|
||||
#define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer
|
||||
//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger
|
||||
#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
#define USE_PZEM004T // Add support for PZEM004T Energy monitor (+2k code)
|
||||
#define USE_PZEM_AC // Add support for PZEM014,016 Energy monitor (+1k1 code)
|
||||
#define USE_PZEM_DC // Add support for PZEM003,017 Energy monitor (+1k1 code)
|
||||
@ -138,15 +139,14 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
|
||||
// #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code)
|
||||
#define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code)
|
||||
//#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger
|
||||
#endif // USE_SENSORS
|
||||
#endif // FIRMWARE_SENSORS
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [sonoff-classic.bin]
|
||||
* Provide an image close to version 5.12.0 but still within 499k program space to allow one time OTA
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_CLASSIC
|
||||
#ifdef FIRMWARE_CLASSIC
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 2
|
||||
@ -174,10 +174,6 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
|
||||
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
|
||||
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
|
||||
#undef USE_PZEM004T // Disable PZEM004T energy sensor
|
||||
#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor
|
||||
#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor
|
||||
#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code)
|
||||
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
|
||||
#undef USE_SDM120 // Disable support for Eastron SDM120-Modbus energy meter
|
||||
#undef USE_SDM630 // Disable support for Eastron SDM630-Modbus energy meter
|
||||
@ -185,6 +181,12 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
#undef USE_PZEM004T // Disable PZEM004T energy sensor
|
||||
#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor
|
||||
#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor
|
||||
#undef USE_MCP39F501 // Disable support for MCP39F501 Energy monitor as used in Shelly 2 (+3k1 code)
|
||||
#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI
|
||||
#undef USE_IR_REMOTE // Disable IR remote commands using library IRremoteESP8266 and ArduinoJson
|
||||
#undef USE_IR_RECEIVE // Disable support for IR receiver
|
||||
@ -198,15 +200,14 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
|
||||
#undef DEBUG_THEO // Disable debug code
|
||||
#undef USE_DEBUG_DRIVER // Disable debug code
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#endif // USE_CLASSIC
|
||||
#endif // FIRMWARE_CLASSIC
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [sonoff-knx.bin]
|
||||
* Provide a dedicated KNX image allowing enough code and memory space
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_KNX_NO_EMULATION
|
||||
#ifdef FIRMWARE_KNX_NO_EMULATION
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 4
|
||||
@ -215,14 +216,14 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#define USE_KNX // Enable KNX IP Protocol Support (+23k code, +3k3 mem)
|
||||
#endif
|
||||
#undef USE_EMULATION // Disable Belkin WeMo and Hue Bridge emulation for Alexa (-16k code, -2k mem)
|
||||
#endif // USE_KNX_NO_EMULATION
|
||||
#endif // FIRMWARE_KNX_NO_EMULATION
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [sonoff-display.bin]
|
||||
* Provide an image with display drivers enabled
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_DISPLAYS
|
||||
#ifdef FIRMWARE_DISPLAYS
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 6
|
||||
@ -249,7 +250,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
|
||||
#undef USE_ARILUX_RF // Remove support for Arilux RF remote controller (-0k8 code, 252 iram (non 2.3.0))
|
||||
#undef USE_RF_FLASH // Remove support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB (-3k code)
|
||||
#endif // USE_DISPLAYS
|
||||
#endif // FIRMWARE_DISPLAYS
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Mandatory define for DS18x20 if changed by above image selections
|
||||
@ -265,13 +266,13 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
* Provide an image without sensors
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef USE_BASIC
|
||||
#ifdef FIRMWARE_BASIC
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 5
|
||||
|
||||
#undef APP_SLEEP
|
||||
#define APP_SLEEP 1 // Default to sleep = 1 for USE_BASIC
|
||||
#define APP_SLEEP 1 // Default to sleep = 1 for FIRMWARE_BASIC
|
||||
|
||||
//#undef USE_ENERGY_SENSOR // Disable energy sensors
|
||||
#undef USE_ARDUINO_OTA // Disable support for Arduino OTA
|
||||
@ -307,6 +308,8 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
//#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
#undef USE_PZEM004T // Disable PZEM004T energy sensor
|
||||
#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor
|
||||
#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor
|
||||
@ -324,15 +327,14 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
|
||||
#undef DEBUG_THEO // Disable debug code
|
||||
#undef USE_DEBUG_DRIVER // Disable debug code
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#endif // USE_BASIC
|
||||
#endif // FIRMWARE_BASIC
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [sonoff-minimal.bin]
|
||||
* Provide the smallest image possible while still enabling a webserver for intermediate image load
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef BE_MINIMAL
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
|
||||
#undef CODE_IMAGE
|
||||
#define CODE_IMAGE 1
|
||||
@ -371,6 +373,8 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_TUYA_DIMMER // Disable support for Tuya Serial Dimmer
|
||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
#undef USE_PZEM004T // Disable PZEM004T energy sensor
|
||||
#undef USE_PZEM_AC // Disable PZEM014,016 Energy monitor
|
||||
#undef USE_PZEM_DC // Disable PZEM003,017 Energy monitor
|
||||
@ -388,8 +392,7 @@ void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
|
||||
#undef DEBUG_THEO // Disable debug code
|
||||
#undef USE_DEBUG_DRIVER // Disable debug code
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Mandatory defines satisfying possible disabled defines
|
||||
|
@ -162,6 +162,8 @@ enum UserSelectablePins {
|
||||
GPIO_MCP39F5_TX, // MCP39F501 Serial interface (Shelly2)
|
||||
GPIO_MCP39F5_RX, // MCP39F501 Serial interface (Shelly2)
|
||||
GPIO_MCP39F5_RST, // MCP39F501 Reset (Shelly2)
|
||||
GPIO_PN532_TXD, // PN532 NFC Serial Tx
|
||||
GPIO_PN532_RXD, // PN532 NFC Serial Rx
|
||||
GPIO_SM16716_CLK, // SM16716 CLOCK
|
||||
GPIO_SM16716_DAT, // SM16716 DATA
|
||||
GPIO_SM16716_SEL, // SM16716 SELECT
|
||||
@ -230,6 +232,7 @@ const char kSensorNames[] PROGMEM =
|
||||
D_SENSOR_BUTTON "1in|" D_SENSOR_BUTTON "2in|" D_SENSOR_BUTTON "3in|" D_SENSOR_BUTTON "4in|"
|
||||
D_SENSOR_NRG_SEL "|" D_SENSOR_NRG_SEL "i|" D_SENSOR_NRG_CF1 "|" D_SENSOR_HLW_CF "|" D_SENSOR_HJL_CF "|"
|
||||
D_SENSOR_MCP39F5_TX "|" D_SENSOR_MCP39F5_RX "|" D_SENSOR_MCP39F5_RST "|"
|
||||
D_SENSOR_PN532_TX "|" D_SENSOR_PN532_RX "|"
|
||||
D_SENSOR_SM16716_CLK "|" D_SENSOR_SM16716_DAT "|" D_SENSOR_SM16716_POWER
|
||||
;
|
||||
|
||||
@ -538,14 +541,18 @@ const uint8_t kGpioNiceList[] PROGMEM = {
|
||||
GPIO_TUYA_TX, // Tuya Serial interface
|
||||
GPIO_TUYA_RX, // Tuya Serial interface
|
||||
#endif
|
||||
#ifdef USE_MGC3130
|
||||
GPIO_MGC3130_XFER,
|
||||
GPIO_MGC3130_RESET,
|
||||
#endif
|
||||
#ifdef USE_AZ7798
|
||||
GPIO_AZ_TXD, // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
GPIO_AZ_RXD, // AZ-Instrument 7798 CO2 datalogger Serial interface
|
||||
#endif
|
||||
#ifdef USE_PN532_HSU
|
||||
GPIO_PN532_TXD, // PN532 HSU Tx
|
||||
GPIO_PN532_RXD, // PN532 HSU Rx
|
||||
#endif
|
||||
#ifdef USE_MGC3130
|
||||
GPIO_MGC3130_XFER,
|
||||
GPIO_MGC3130_RESET,
|
||||
#endif
|
||||
#ifdef USE_MAX31855
|
||||
GPIO_MAX31855CS, // MAX31855 Serial interface
|
||||
GPIO_MAX31855CLK, // MAX31855 Serial interface
|
||||
@ -1072,9 +1079,10 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
||||
0, // GPIO09
|
||||
0, // GPIO10
|
||||
// GPIO11 (SD_CMD Flash)
|
||||
0,
|
||||
GPIO_USER, // GPIO12 Optional sensor
|
||||
GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) - Link and Power status
|
||||
0, 0, 0, 0
|
||||
GPIO_USER, // GPIO14 Optional sensor
|
||||
0, 0, 0
|
||||
},
|
||||
{ "Sonoff B1", // Sonoff B1 (ESP8285 - my9231)
|
||||
GPIO_KEY1, // GPIO00 Pad
|
||||
|
@ -20,7 +20,7 @@
|
||||
#ifndef _SONOFF_VERSION_H_
|
||||
#define _SONOFF_VERSION_H_
|
||||
|
||||
#define VERSION 0x0604010E
|
||||
#define VERSION 0x0604010F
|
||||
|
||||
#define D_PROGRAMNAME "Sonoff-Tasmota"
|
||||
#define D_AUTHOR "Theo Arends"
|
||||
|
@ -126,16 +126,16 @@ void GetFeatures(void)
|
||||
#ifdef USE_CONFIG_OVERRIDE
|
||||
feature_drv2 |= 0x00000001; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef BE_MINIMAL
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
feature_drv2 |= 0x00000002; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_SENSORS
|
||||
#ifdef FIRMWARE_SENSORS
|
||||
feature_drv2 |= 0x00000004; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_CLASSIC
|
||||
#ifdef FIRMWARE_CLASSIC
|
||||
feature_drv2 |= 0x00000008; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_KNX_NO_EMULATION
|
||||
#ifdef FIRMWARE_KNX_NO_EMULATION
|
||||
feature_drv2 |= 0x00000010; // user_config(_override).h
|
||||
#endif
|
||||
#ifdef USE_DISPLAY_MODES1TO5
|
||||
@ -378,8 +378,8 @@ void GetFeatures(void)
|
||||
#ifdef USE_MAX31855
|
||||
feature_sns2 |= 0x00080000; // xsns_39_max31855.ino
|
||||
#endif
|
||||
#ifdef USE_PN532_I2C
|
||||
feature_sns2 |= 0x00100000; // xsns_40_pn532_i2c.ino
|
||||
#ifdef USE_PN532_HSU
|
||||
feature_sns2 |= 0x00100000; // xsns_40_pn532.ino
|
||||
#endif
|
||||
#ifdef USE_MAX44009
|
||||
feature_sns2 |= 0x00200000;
|
||||
|
@ -501,12 +501,12 @@ void WifiCheck(uint8_t param)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BE_MINIMAL
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
if (1 == RtcSettings.ota_loader) {
|
||||
RtcSettings.ota_loader = 0;
|
||||
ota_state_flag = 3;
|
||||
}
|
||||
#endif // BE_MINIMAL
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
|
||||
#ifdef USE_DISCOVERY
|
||||
if (Settings.flag3.mdns_enabled) {
|
||||
|
@ -129,11 +129,11 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM =
|
||||
"x.onreadystatechange=function(){"
|
||||
"if(x.readyState==4&&x.status==200){"
|
||||
"var z,d;"
|
||||
"d=x.responseXML;"
|
||||
"id=d.getElementsByTagName('i')[0].childNodes[0].nodeValue;"
|
||||
"if(d.getElementsByTagName('j')[0].childNodes[0].nodeValue==0){t.value='';}"
|
||||
"z=d.getElementsByTagName('l')[0].childNodes;"
|
||||
"if(z.length>0){t.value+=decodeURIComponent(z[0].nodeValue);}"
|
||||
"d=x.responseText.split(/\1/);"
|
||||
"id=d.shift();"
|
||||
"if(d.shift()==0){t.value='';}"
|
||||
"z=d.shift();"
|
||||
"if(z.length>0){t.value+=z;}"
|
||||
"t.scrollTop=99999;"
|
||||
"sn=t.scrollTop;"
|
||||
"}"
|
||||
@ -208,7 +208,7 @@ const char HTTP_HEAD_STYLE[] PROGMEM =
|
||||
"</head>"
|
||||
"<body>"
|
||||
"<div style='text-align:left;display:inline-block;min-width:340px;'>"
|
||||
#ifdef BE_MINIMAL
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
"<div style='text-align:center;color:red;'><h3>" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "</h3></div>"
|
||||
#endif
|
||||
"<div style='text-align:center;'><noscript>" D_NOSCRIPT "<br/></noscript>"
|
||||
@ -227,7 +227,7 @@ const char HTTP_MSG_SLIDER2[] PROGMEM =
|
||||
const char HTTP_MSG_RSTRT[] PROGMEM =
|
||||
"<br/><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br/>";
|
||||
const char HTTP_BTN_MENU1[] PROGMEM =
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
"<br/><form action='cn' method='get'><button>" D_CONFIGURATION "</button></form>"
|
||||
"<br/><form action='in' method='get'><button>" D_INFORMATION "</button></form>"
|
||||
#endif
|
||||
@ -401,7 +401,7 @@ void StartWebserver(int type, IPAddress ipweb)
|
||||
WebServer->on("/ay", HandleAjaxStatusRefresh);
|
||||
WebServer->on("/cm", HandleHttpCommand);
|
||||
WebServer->onNotFound(HandleNotFound);
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
WebServer->on("/cn", HandleConfiguration);
|
||||
WebServer->on("/md", HandleModuleConfiguration);
|
||||
WebServer->on("/wi", HandleWifiConfiguration);
|
||||
@ -416,7 +416,7 @@ void StartWebserver(int type, IPAddress ipweb)
|
||||
#endif // USE_EMULATION
|
||||
XdrvCall(FUNC_WEB_ADD_HANDLER);
|
||||
XsnsCall(FUNC_WEB_ADD_HANDLER);
|
||||
#endif // Not BE_MINIMAL
|
||||
#endif // Not FIRMWARE_MINIMAL
|
||||
}
|
||||
reset_web_log_flag = false;
|
||||
WebServer->begin(); // Web server start
|
||||
@ -601,7 +601,7 @@ void HandleRoot(void)
|
||||
}
|
||||
|
||||
if (HTTP_MANAGER == webserver_state) {
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if ((Settings.web_password[0] != 0) && !(WebServer->hasArg("USER1")) && !(WebServer->hasArg("PASS1"))) {
|
||||
HandleWifiLogin();
|
||||
} else {
|
||||
@ -619,7 +619,7 @@ void HandleRoot(void)
|
||||
HandleWifiLogin();
|
||||
}
|
||||
}
|
||||
#endif // Not BE_MINIMAL
|
||||
#endif // Not FIRMWARE_MINIMAL
|
||||
} else {
|
||||
char stemp[10];
|
||||
String page = FPSTR(HTTP_HEAD);
|
||||
@ -673,12 +673,12 @@ void HandleRoot(void)
|
||||
page += F("</tr></table>");
|
||||
}
|
||||
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
mqtt_data[0] = '\0';
|
||||
XdrvCall(FUNC_WEB_ADD_MAIN_BUTTON);
|
||||
XsnsCall(FUNC_WEB_ADD_MAIN_BUTTON);
|
||||
page += String(mqtt_data);
|
||||
#endif // Not BE_MINIMAL
|
||||
#endif // Not FIRMWARE_MINIMAL
|
||||
|
||||
if (HTTP_ADMIN == webserver_state) {
|
||||
page += FPSTR(HTTP_BTN_MENU1);
|
||||
@ -773,7 +773,7 @@ bool HttpCheckPriviledgedAccess(bool autorequestauth = true)
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef BE_MINIMAL
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
|
||||
void HandleConfiguration(void)
|
||||
{
|
||||
@ -1407,7 +1407,7 @@ void HandleInformation(void)
|
||||
page += FPSTR(HTTP_BTN_MAIN);
|
||||
ShowPage(page);
|
||||
}
|
||||
#endif // Not BE_MINIMAL
|
||||
#endif // Not FIRMWARE_MINIMAL
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
@ -1813,7 +1813,9 @@ void HandleAjaxConsoleRefresh(void)
|
||||
if (strlen(svalue)) { counter = atoi(svalue); }
|
||||
|
||||
bool last_reset_web_log_flag = reset_web_log_flag;
|
||||
String message = F("}9"); // Cannot load mqtt_data here as <> will be encoded by replacements below
|
||||
// mqtt_data used as scratch space
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%d\1%d\1"), web_log_index, last_reset_web_log_flag);
|
||||
String message = mqtt_data;
|
||||
if (!reset_web_log_flag) {
|
||||
counter = 0;
|
||||
reset_web_log_flag = true;
|
||||
@ -1834,20 +1836,13 @@ void HandleAjaxConsoleRefresh(void)
|
||||
cflg = true;
|
||||
}
|
||||
strlcpy(mqtt_data, tmp, len);
|
||||
message += mqtt_data;
|
||||
message += mqtt_data; // mqtt_data used as scratch space
|
||||
}
|
||||
counter++;
|
||||
if (!counter) { counter++; } // Skip 0 as it is not allowed
|
||||
if (!counter) { counter++; } // Skip log index 0 as it is not allowed
|
||||
} while (counter != web_log_index);
|
||||
// XML encoding to fix blank console log in concert with javascript decodeURIComponent
|
||||
message.replace(F("%"), F("%25")); // Needs to be done first as otherwise the % in %26 will also be converted
|
||||
message.replace(F("&"), F("%26"));
|
||||
message.replace(F("<"), F("%3C"));
|
||||
message.replace(F(">"), F("%3E"));
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("<r><i>%d</i><j>%d</j><l>"), web_log_index, last_reset_web_log_flag);
|
||||
message.replace(F("}9"), mqtt_data); // Save to load here
|
||||
message += F("</l></r>");
|
||||
message += F("\1");
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_XML), message);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ void SerialBridgeInput(void)
|
||||
{
|
||||
while (SerialBridgeSerial->available()) {
|
||||
yield();
|
||||
uint8_t serial_in_uint8_t = SerialBridgeSerial->read();
|
||||
uint8_t serial_in_byte = SerialBridgeSerial->read();
|
||||
|
||||
if (serial_in_byte > 127) { // binary data...
|
||||
serial_bridge_in_byte_counter = 0;
|
||||
|
@ -78,6 +78,18 @@
|
||||
|
||||
#define D_JSON_INITIATED "Initiated"
|
||||
|
||||
#define COMPARE_OPERATOR_NONE -1
|
||||
#define COMPARE_OPERATOR_EQUAL 0
|
||||
#define COMPARE_OPERATOR_BIGGER 1
|
||||
#define COMPARE_OPERATOR_SMALLER 2
|
||||
#define COMPARE_OPERATOR_EXACT_DIVISION 3
|
||||
#define COMPARE_OPERATOR_NUMBER_EQUAL 4
|
||||
#define COMPARE_OPERATOR_NOT_EQUAL 5
|
||||
#define COMPARE_OPERATOR_BIGGER_EQUAL 6
|
||||
#define COMPARE_OPERATOR_SMALLER_EQUAL 7
|
||||
#define MAXIMUM_COMPARE_OPERATOR COMPARE_OPERATOR_SMALLER_EQUAL
|
||||
const char kCompareOperators[] PROGMEM = "=\0>\0<\0|\0==!=>=<=";
|
||||
|
||||
enum RulesCommands { CMND_RULE, CMND_RULETIMER, CMND_EVENT, CMND_VAR, CMND_MEM, CMND_ADD, CMND_SUB, CMND_MULT, CMND_SCALE, CMND_CALC_RESOLUTION };
|
||||
const char kRulesCommands[] PROGMEM = D_CMND_RULE "|" D_CMND_RULETIMER "|" D_CMND_EVENT "|" D_CMND_VAR "|" D_CMND_MEM "|" D_CMND_ADD "|" D_CMND_SUB "|" D_CMND_MULT "|" D_CMND_SCALE "|" D_CMND_CALC_RESOLUTION ;
|
||||
|
||||
@ -128,31 +140,20 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
||||
|
||||
String rule_name = rule.substring(pos +1); // "CURRENT>0.100" or "BOOT" or "%var1%" or "MINUTE|5"
|
||||
|
||||
char compare = ' ';
|
||||
pos = rule_name.indexOf(">");
|
||||
if (pos > 0) {
|
||||
compare = '>';
|
||||
} else {
|
||||
pos = rule_name.indexOf("<");
|
||||
if (pos > 0) {
|
||||
compare = '<';
|
||||
} else {
|
||||
pos = rule_name.indexOf("=");
|
||||
if (pos > 0) {
|
||||
compare = '=';
|
||||
} else {
|
||||
pos = rule_name.indexOf("|"); // Modulo, cannot use % easily as it is used for variable detection
|
||||
if (pos > 0) {
|
||||
compare = '%';
|
||||
}
|
||||
}
|
||||
char compare_operator[3];
|
||||
int8_t compare = COMPARE_OPERATOR_NONE;
|
||||
for (int8_t i = MAXIMUM_COMPARE_OPERATOR; i >= 0; i--) {
|
||||
snprintf_P(compare_operator, sizeof(compare_operator), kCompareOperators + (i *2));
|
||||
if ((pos = rule_name.indexOf(compare_operator)) > 0) {
|
||||
compare = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char rule_svalue[CMDSZ] = { 0 };
|
||||
double rule_value = 0;
|
||||
if (pos > 0) {
|
||||
String rule_param = rule_name.substring(pos + 1);
|
||||
if (compare != COMPARE_OPERATOR_NONE) {
|
||||
String rule_param = rule_name.substring(pos + strlen(compare_operator));
|
||||
for (uint8_t i = 0; i < MAX_RULE_VARS; i++) {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%%VAR%d%%"), i +1);
|
||||
if (rule_param.startsWith(stemp)) {
|
||||
@ -224,24 +225,32 @@ bool RulesRuleMatch(uint8_t rule_set, String &event, String &rule)
|
||||
int int_value = int(value);
|
||||
int int_rule_value = int(rule_value);
|
||||
switch (compare) {
|
||||
case '%':
|
||||
if ((int_value > 0) && (int_rule_value > 0)) {
|
||||
if ((int_value % int_rule_value) == 0) { match = true; }
|
||||
}
|
||||
case COMPARE_OPERATOR_EXACT_DIVISION:
|
||||
match = (int_rule_value && (int_value % int_rule_value) == 0);
|
||||
break;
|
||||
case '>':
|
||||
if (value > rule_value) { match = true; }
|
||||
case COMPARE_OPERATOR_EQUAL:
|
||||
match = (!strcasecmp(str_value, rule_svalue)); // Compare strings - this also works for hexadecimals
|
||||
break;
|
||||
case '<':
|
||||
if (value < rule_value) { match = true; }
|
||||
case COMPARE_OPERATOR_BIGGER:
|
||||
match = (value > rule_value);
|
||||
break;
|
||||
case '=':
|
||||
// if (value == rule_value) { match = true; } // Compare values - only decimals or partly hexadecimals
|
||||
if (!strcasecmp(str_value, rule_svalue)) { match = true; } // Compare strings - this also works for hexadecimals
|
||||
case COMPARE_OPERATOR_SMALLER:
|
||||
match = (value < rule_value);
|
||||
break;
|
||||
case ' ':
|
||||
match = true; // Json value but not needed
|
||||
case COMPARE_OPERATOR_NUMBER_EQUAL:
|
||||
match = (value == rule_value);
|
||||
break;
|
||||
case COMPARE_OPERATOR_NOT_EQUAL:
|
||||
match = (value != rule_value);
|
||||
break;
|
||||
case COMPARE_OPERATOR_BIGGER_EQUAL:
|
||||
match = (value >= rule_value);
|
||||
break;
|
||||
case COMPARE_OPERATOR_SMALLER_EQUAL:
|
||||
match = (value <= rule_value);
|
||||
break;
|
||||
default:
|
||||
match = true;
|
||||
}
|
||||
} else match = true;
|
||||
|
||||
|
@ -122,6 +122,11 @@ const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM =
|
||||
"%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass
|
||||
"\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
|
||||
|
||||
const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM =
|
||||
"%s,\"json_attributes_topic\":\"%s\","
|
||||
"\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass
|
||||
"\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"";// "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }}
|
||||
|
||||
const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM =
|
||||
"%s,\"uniq_id\":\"%s\","
|
||||
"\"device\":{\"identifiers\":[\"%06X\"],"
|
||||
@ -130,11 +135,16 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM =
|
||||
"\"sw_version\":\"%s%s\","
|
||||
"\"manufacturer\":\"Tasmota\"}";
|
||||
|
||||
const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM =
|
||||
"%s,\"uniq_id\":\"%s\","
|
||||
"\"device\":{\"identifiers\":[\"%06X\"]}";
|
||||
|
||||
const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM =
|
||||
"%s, \"~\":\"%s\"";
|
||||
|
||||
uint8_t hass_init_step = 0;
|
||||
uint8_t hass_mode = 0;
|
||||
int hass_tele_period = 0;
|
||||
|
||||
static void FindPrefix(char* s1, char* s2, char* out)
|
||||
{
|
||||
@ -156,6 +166,26 @@ static void Shorten(char** s, char *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
int try_snprintf_P(char *s, size_t n, const char *format, ... )
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int len = vsnprintf_P(NULL, 0, format, args);
|
||||
if (len >= n) {
|
||||
snprintf_P(log_data, sizeof(log_data),
|
||||
PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. "
|
||||
"Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n);
|
||||
AddLog(LOG_LEVEL_ERROR);
|
||||
va_start(args, format);
|
||||
vsnprintf_P(log_data, sizeof(log_data), format, args);
|
||||
AddLog(LOG_LEVEL_ERROR);
|
||||
} else {
|
||||
va_start(args, format);
|
||||
vsnprintf_P(s, n, format, args);
|
||||
}
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void HAssAnnounceRelayLight(void)
|
||||
{
|
||||
char stopic[TOPSZ];
|
||||
@ -174,14 +204,16 @@ void HAssAnnounceRelayLight(void)
|
||||
|
||||
// Clear "other" topic first in case the device has been reconfigured from ligth to switch or vice versa
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "RL" : "LI", i);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "switch" : "light", unique_id);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"),
|
||||
(is_topic_light) ? "switch" : "light", unique_id);
|
||||
MqttPublish(stopic, true);
|
||||
// Clear or Set topic
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s_%d"), ESP.getChipId(), (is_topic_light) ? "LI" : "RL", i);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"), (is_topic_light) ? "light" : "switch", unique_id);
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/%s/%s/config"),
|
||||
(is_topic_light) ? "light" : "switch", unique_id);
|
||||
|
||||
if (Settings.flag.hass_discovery && (i <= devices_present)) {
|
||||
char name[33];
|
||||
char name[33+2]; // friendlyname(33) + " " + index
|
||||
char value_template[33];
|
||||
char prefix[TOPSZ];
|
||||
char *command_topic = stemp1;
|
||||
@ -202,27 +234,30 @@ void HAssAnnounceRelayLight(void)
|
||||
Shorten(&command_topic, prefix);
|
||||
Shorten(&state_topic, prefix);
|
||||
Shorten(&availability_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_RELAY,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_RELAY,
|
||||
name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data,
|
||||
unique_id, ESP.getChipId());
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
|
||||
if (is_light) {
|
||||
char *brightness_command_topic = stemp1;
|
||||
|
||||
GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER);
|
||||
Shorten(&brightness_command_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic);
|
||||
|
||||
if (light_subtype >= LST_RGB) {
|
||||
char *rgb_command_topic = stemp1;
|
||||
|
||||
GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR);
|
||||
Shorten(&rgb_command_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic);
|
||||
|
||||
char *effect_command_topic = stemp1;
|
||||
GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME);
|
||||
Shorten(&effect_command_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic);
|
||||
|
||||
}
|
||||
if (LST_RGBW == light_subtype) {
|
||||
@ -230,21 +265,17 @@ void HAssAnnounceRelayLight(void)
|
||||
|
||||
GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE);
|
||||
Shorten(&white_temp_command_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic);
|
||||
}
|
||||
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
|
||||
char *color_temp_command_topic = stemp1;
|
||||
|
||||
GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE);
|
||||
Shorten(&color_temp_command_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic);
|
||||
}
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
|
||||
unique_id, ESP.getChipId(),
|
||||
Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
MqttPublish(stopic, true);
|
||||
}
|
||||
@ -266,7 +297,7 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/binary_sensor/%s/config"), unique_id);
|
||||
|
||||
if (Settings.flag.hass_discovery && present) {
|
||||
char name[33];
|
||||
char name[33+6]; // friendlyname(33) + " " + "BTN" + " " + index
|
||||
char value_template[33];
|
||||
char prefix[TOPSZ];
|
||||
char *state_topic = stemp1;
|
||||
@ -284,16 +315,15 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint
|
||||
FindPrefix(state_topic, availability_topic, prefix);
|
||||
Shorten(&state_topic, prefix);
|
||||
Shorten(&availability_topic, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH,
|
||||
name, state_topic, Settings.state_text[toggle?2:1], availability_topic);
|
||||
if (toggle) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data);
|
||||
else snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data,
|
||||
unique_id, ESP.getChipId());
|
||||
if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data-1, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
if (toggle) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data);
|
||||
else try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]);
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
|
||||
unique_id, ESP.getChipId(),
|
||||
Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
|
||||
if (strlen(prefix) > 0 ) snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
MqttPublish(stopic, true);
|
||||
}
|
||||
@ -374,7 +404,7 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);
|
||||
|
||||
if (Settings.flag.hass_discovery) {
|
||||
char name[33];
|
||||
char name[33+42]; // friendlyname(33) + " " + sensorname(20?) + " " + sensortype(20?)
|
||||
char prefix[TOPSZ];
|
||||
char *state_topic = stemp1;
|
||||
char *availability_topic = stemp2;
|
||||
@ -386,39 +416,40 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype)
|
||||
Shorten(&state_topic, prefix);
|
||||
Shorten(&availability_topic, prefix);
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR,
|
||||
name, state_topic, availability_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data,
|
||||
unique_id, ESP.getChipId());
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_TEMP,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_TEMP,
|
||||
mqtt_data, TempUnit(), sensorname);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_HUM,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HUM,
|
||||
mqtt_data, sensorname);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_PRESS,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_PRESS,
|
||||
mqtt_data, PressureUnit().c_str(), sensorname);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_KWH,
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL))
|
||||
|| !strcmp_P(subsensortype, PSTR(D_JSON_TODAY))
|
||||
|| !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_KWH,
|
||||
mqtt_data, sensorname, subsensortype);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_WATT,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_WATT,
|
||||
mqtt_data, sensorname, subsensortype);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_VOLTAGE,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_VOLTAGE,
|
||||
mqtt_data, sensorname, subsensortype);
|
||||
} else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_AMPERE,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_AMPERE,
|
||||
mqtt_data, sensorname, subsensortype);
|
||||
}
|
||||
else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_SENSOR_ANY,
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_ANY,
|
||||
mqtt_data, sensorname, subsensortype);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_DEVICE_INFO, mqtt_data,
|
||||
unique_id, ESP.getChipId(),
|
||||
Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
MqttPublish(stopic, true);
|
||||
}
|
||||
@ -469,6 +500,57 @@ void HAssAnnounceSensors(void)
|
||||
} while (hass_xsns_index != 0);
|
||||
}
|
||||
|
||||
void HAssAnnounceStatusSensor(void)
|
||||
{
|
||||
char stopic[TOPSZ];
|
||||
char stemp1[TOPSZ];
|
||||
char stemp2[TOPSZ];
|
||||
char unique_id[30];
|
||||
|
||||
// Announce sensor
|
||||
mqtt_data[0] = '\0'; // Clear retained message
|
||||
|
||||
// Clear or Set topic
|
||||
snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s"), ESP.getChipId(), "status");
|
||||
snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id);
|
||||
|
||||
if (Settings.flag.hass_discovery) {
|
||||
char name[33+7]; // friendlyname(33) + " " + "status"
|
||||
char prefix[TOPSZ];
|
||||
char *state_topic = stemp1;
|
||||
char *availability_topic = stemp2;
|
||||
|
||||
snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[0], "status");
|
||||
GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE));
|
||||
GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT);
|
||||
FindPrefix(state_topic, availability_topic, prefix);
|
||||
Shorten(&state_topic, prefix);
|
||||
Shorten(&availability_topic, prefix);
|
||||
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR,
|
||||
name, state_topic, availability_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HASS_STATUS,
|
||||
mqtt_data, state_topic);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO, mqtt_data,
|
||||
unique_id, ESP.getChipId(),
|
||||
Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix);
|
||||
try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
MqttPublish(stopic, true);
|
||||
}
|
||||
|
||||
void HAssPublishStatus(void)
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data),
|
||||
PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\""
|
||||
D_JSON_UPTIME "\":\"%s\",\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\""
|
||||
D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_RSSI "\":\"%d\",\"LoadAvg\":%lu}"),
|
||||
my_version, my_image, ModuleName().c_str(), GetResetReason().c_str(), GetUptime().c_str(), Settings.bootcount,
|
||||
Settings.save_flag, WiFi.localIP().toString().c_str(), WifiGetRssiAsQuality(WiFi.RSSI()), loop_load_avg);
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_HASS_STATE));
|
||||
}
|
||||
|
||||
void HAssDiscovery(void)
|
||||
{
|
||||
// Configure Tasmota for default Home Assistant parameters to keep discovery message as short as possible
|
||||
@ -496,6 +578,9 @@ void HAssDiscovery(void)
|
||||
|
||||
// Send info about sensors
|
||||
HAssAnnounceSensors();
|
||||
|
||||
// Send info about status sensor
|
||||
HAssAnnounceStatusSensor();
|
||||
}
|
||||
}
|
||||
|
||||
@ -525,6 +610,14 @@ bool Xdrv12(uint8_t function)
|
||||
if (!hass_init_step) {
|
||||
HAssDiscovery(); // Scheduled discovery using available resources
|
||||
}
|
||||
} else if (Settings.flag.hass_discovery && Settings.tele_period) {
|
||||
hass_tele_period++;
|
||||
if (hass_tele_period >= Settings.tele_period) {
|
||||
hass_tele_period = 0;
|
||||
|
||||
mqtt_data[0] = '\0';
|
||||
HAssPublishStatus();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
TasmotaSerial *PzemSerial;
|
||||
TasmotaSerial *PzemSerial = NULL;
|
||||
|
||||
#define PZEM_VOLTAGE (uint8_t)0xB0
|
||||
#define RESP_VOLTAGE (uint8_t)0xA0
|
||||
@ -239,7 +239,7 @@ int Xnrg03(uint8_t function)
|
||||
PzemSnsInit();
|
||||
break;
|
||||
case FUNC_EVERY_200_MSECOND:
|
||||
PzemEvery200ms();
|
||||
if (PzemSerial) { PzemEvery200ms(); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#define XNRG_04 4
|
||||
|
||||
#define MCP_BAUDRATE 4800
|
||||
#define MCP_TIMEOUT 4
|
||||
#define MCP_CALIBRATION_TIMEOUT 2
|
||||
|
||||
@ -66,7 +67,7 @@
|
||||
#define MCP_BUFFER_SIZE 60
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
TasmotaSerial *McpSerial;
|
||||
TasmotaSerial *McpSerial = NULL;
|
||||
|
||||
typedef struct mcp_cal_registers_type {
|
||||
uint16_t gain_current_rms;
|
||||
@ -91,9 +92,8 @@ typedef struct mcp_cal_registers_type {
|
||||
uint16_t accumulation_interval;
|
||||
} mcp_cal_registers_type;
|
||||
|
||||
char *mcp_buffer = NULL; // Serial receive buffer
|
||||
int mcp_byte_counter = 0; // Index in serial receive buffer
|
||||
|
||||
char *mcp_buffer = NULL;
|
||||
unsigned long mcp_window = 0;
|
||||
unsigned long mcp_kWhcounter = 0;
|
||||
uint32_t mcp_system_configuration = 0x03000000;
|
||||
uint32_t mcp_active_power;
|
||||
@ -108,6 +108,7 @@ uint8_t mcp_calibration_active = 0;
|
||||
uint8_t mcp_init = 0;
|
||||
uint8_t mcp_timeout = 0;
|
||||
uint8_t mcp_calibrate = 0;
|
||||
uint8_t mcp_byte_counter = 0;
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Olimex tools
|
||||
@ -474,19 +475,20 @@ void McpParseData(void)
|
||||
|
||||
void McpSerialInput(void)
|
||||
{
|
||||
if (McpSerial->available()) {
|
||||
unsigned long start = millis();
|
||||
while (millis() - start < 20) {
|
||||
yield();
|
||||
if (McpSerial->available()) {
|
||||
mcp_buffer[mcp_byte_counter++] = McpSerial->read();
|
||||
start = millis();
|
||||
}
|
||||
}
|
||||
while ((McpSerial->available()) && (mcp_byte_counter < MCP_BUFFER_SIZE)) {
|
||||
yield();
|
||||
mcp_buffer[mcp_byte_counter++] = McpSerial->read();
|
||||
mcp_window = millis();
|
||||
}
|
||||
|
||||
// Ignore until non received after 2 chars (= 12 bits/char) time
|
||||
if ((mcp_byte_counter) && (millis() - mcp_window > (24000 / MCP_BAUDRATE) +1)) {
|
||||
AddLogBuffer(LOG_LEVEL_DEBUG_MORE, (uint8_t*)mcp_buffer, mcp_byte_counter);
|
||||
|
||||
if (1 == mcp_byte_counter) {
|
||||
if (MCP_BUFFER_SIZE == mcp_byte_counter) {
|
||||
// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Overflow"));
|
||||
}
|
||||
else if (1 == mcp_byte_counter) {
|
||||
if (MCP_ERROR_CRC == mcp_buffer[0]) {
|
||||
// AddLog_P(LOG_LEVEL_DEBUG, PSTR("MCP: Send " D_CHECKSUM_FAILURE));
|
||||
mcp_timeout = 0;
|
||||
@ -556,8 +558,13 @@ void McpSnsInit(void)
|
||||
{
|
||||
// Software serial init needs to be done here as earlier (serial) interrupts may lead to Exceptions
|
||||
McpSerial = new TasmotaSerial(pin[GPIO_MCP39F5_RX], pin[GPIO_MCP39F5_TX], 1);
|
||||
if (McpSerial->begin(4800)) {
|
||||
if (McpSerial->hardwareSerial()) { ClaimSerial(); }
|
||||
if (McpSerial->begin(MCP_BAUDRATE)) {
|
||||
if (McpSerial->hardwareSerial()) {
|
||||
ClaimSerial();
|
||||
mcp_buffer = serial_in_buffer; // Use idle serial buffer to save RAM
|
||||
} else {
|
||||
mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE));
|
||||
}
|
||||
if (pin[GPIO_MCP39F5_RST] < 99) {
|
||||
digitalWrite(pin[GPIO_MCP39F5_RST], 1); // MCP enable
|
||||
}
|
||||
@ -570,17 +577,14 @@ void McpDrvInit(void)
|
||||
{
|
||||
if (!energy_flg) {
|
||||
if ((pin[GPIO_MCP39F5_RX] < 99) && (pin[GPIO_MCP39F5_TX] < 99)) {
|
||||
mcp_buffer = (char*)(malloc(MCP_BUFFER_SIZE));
|
||||
if (mcp_buffer != NULL) {
|
||||
if (pin[GPIO_MCP39F5_RST] < 99) {
|
||||
pinMode(pin[GPIO_MCP39F5_RST], OUTPUT);
|
||||
digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's
|
||||
}
|
||||
mcp_calibrate = 0;
|
||||
mcp_timeout = 2; // Initial wait
|
||||
mcp_init = 2; // Initial setup steps
|
||||
energy_flg = XNRG_04;
|
||||
if (pin[GPIO_MCP39F5_RST] < 99) {
|
||||
pinMode(pin[GPIO_MCP39F5_RST], OUTPUT);
|
||||
digitalWrite(pin[GPIO_MCP39F5_RST], 0); // MCP disable - Reset Delta Sigma ADC's
|
||||
}
|
||||
mcp_calibrate = 0;
|
||||
mcp_timeout = 2; // Initial wait
|
||||
mcp_init = 2; // Initial setup steps
|
||||
energy_flg = XNRG_04;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -652,10 +656,10 @@ int Xnrg04(uint8_t function)
|
||||
McpSnsInit();
|
||||
break;
|
||||
case FUNC_LOOP:
|
||||
McpSerialInput();
|
||||
if (McpSerial) { McpSerialInput(); }
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
McpEverySecond();
|
||||
if (McpSerial) { McpEverySecond(); }
|
||||
break;
|
||||
case FUNC_COMMAND:
|
||||
result = McpCommand();
|
||||
|
@ -119,7 +119,8 @@ CONFIG REGISTER
|
||||
uint8_t ads1115_type = 0;
|
||||
uint8_t ads1115_address;
|
||||
uint8_t ads1115_addresses[] = { ADS1115_ADDRESS_ADDR_GND, ADS1115_ADDRESS_ADDR_VDD, ADS1115_ADDRESS_ADDR_SDA, ADS1115_ADDRESS_ADDR_SCL };
|
||||
|
||||
uint8_t ads1115_found[] = {false,false,false,false};
|
||||
int16_t ads1115_values[4];
|
||||
//Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_SINGLE);
|
||||
//Ads1115StartComparator(channel, ADS1115_REG_CONFIG_MODE_CONTIN);
|
||||
void Ads1115StartComparator(uint8_t channel, uint16_t mode)
|
||||
@ -160,52 +161,84 @@ int16_t Ads1115GetConversion(uint8_t channel)
|
||||
void Ads1115Detect(void)
|
||||
{
|
||||
uint16_t buffer;
|
||||
|
||||
if (ads1115_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(ads1115_addresses); i++) {
|
||||
ads1115_address = ads1115_addresses[i];
|
||||
if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT)) {
|
||||
Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN);
|
||||
ads1115_type = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
break;
|
||||
if (!ads1115_found[i]) {
|
||||
ads1115_address = ads1115_addresses[i];
|
||||
if (I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONVERT) &&
|
||||
I2cValidRead16(&buffer, ads1115_address, ADS1115_REG_POINTER_CONFIG)) {
|
||||
Ads1115StartComparator(i, ADS1115_REG_CONFIG_MODE_CONTIN);
|
||||
ads1115_type = 1;
|
||||
ads1115_found[i] = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Ads1115GetValues(uint8_t address)
|
||||
{
|
||||
uint8_t old_address = ads1115_address;
|
||||
ads1115_address = address;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
ads1115_values[i] = Ads1115GetConversion(i);
|
||||
//snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x (%i) = %i", address, i, ads1115_values[i] );
|
||||
//AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
ads1115_address = old_address;
|
||||
}
|
||||
|
||||
void Ads1115toJSON(char *comma_j)
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j);
|
||||
char *comma = (char*)"";
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]);
|
||||
comma = (char*)",";
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
|
||||
void Ads1115toString(uint8_t address)
|
||||
{
|
||||
char label[15];
|
||||
snprintf_P(label, sizeof(label), "ADS1115(%02x)", address);
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, label, i, ads1115_values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Ads1115Show(bool json)
|
||||
{
|
||||
if (ads1115_type) {
|
||||
char stemp[10];
|
||||
if (!ads1115_type) { return; }
|
||||
|
||||
uint8_t dsxflg = 0;
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
int16_t adc_value = Ads1115GetConversion(i);
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data);
|
||||
}
|
||||
|
||||
char *comma = (char*)"";
|
||||
|
||||
for (uint8_t t = 0; t < sizeof(ads1115_addresses); t++) {
|
||||
//snprintf_P(log_data, sizeof(log_data), "Logging ADS1115 %02x", ads1115_addresses[t]);
|
||||
//AddLog(LOG_LEVEL_INFO);
|
||||
if (ads1115_found[t]) {
|
||||
Ads1115GetValues(ads1115_addresses[t]);
|
||||
if (json) {
|
||||
if (!dsxflg ) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data);
|
||||
stemp[0] = '\0';
|
||||
}
|
||||
dsxflg++;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value);
|
||||
strlcpy(stemp, ",", sizeof(stemp));
|
||||
Ads1115toJSON(comma);
|
||||
comma = (char*)",";
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value);
|
||||
else {
|
||||
Ads1115toString(ads1115_addresses[t]);
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
if (json) {
|
||||
if (dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
|
@ -345,7 +345,10 @@ void MhzShow(bool json)
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, types, model, mhz_last_ppm, temperature);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm);
|
||||
if (0 == tele_period) {
|
||||
DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm);
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
|
@ -64,12 +64,14 @@ bool Tsl2561Read(void)
|
||||
void Tsl2561Detect(void)
|
||||
{
|
||||
if (tsl2561_type) { return; }
|
||||
uint8_t id;
|
||||
|
||||
if (I2cDevice(0x29) || I2cDevice(0x39) || I2cDevice(0x49)) {
|
||||
if (!Tsl.id(id)) return;
|
||||
Tsl.begin();
|
||||
if (Tsl.on()) {
|
||||
tsl2561_type = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address());
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, tsl2561_types, Tsl.address(), id);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
}
|
||||
|
615
sonoff/xsns_40_pn532.ino
Normal file
615
sonoff/xsns_40_pn532.ino
Normal file
@ -0,0 +1,615 @@
|
||||
/*
|
||||
xsns_40_pn532.ino - Support for PN532 (HSU) NFC Tag Reader
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_PN532_HSU
|
||||
|
||||
#define XSNS_40 40
|
||||
|
||||
#include <TasmotaSerial.h>
|
||||
|
||||
TasmotaSerial *PN532_Serial;
|
||||
|
||||
#define PN532_INVALID_ACK -1
|
||||
#define PN532_TIMEOUT -2
|
||||
#define PN532_INVALID_FRAME -3
|
||||
#define PN532_NO_SPACE -4
|
||||
|
||||
#define PN532_PREAMBLE 0x00
|
||||
#define PN532_STARTCODE1 0x00
|
||||
#define PN532_STARTCODE2 0xFF
|
||||
#define PN532_POSTAMBLE 0x00
|
||||
|
||||
#define PN532_HOSTTOPN532 0xD4
|
||||
#define PN532_PN532TOHOST 0xD5
|
||||
|
||||
#define PN532_ACK_WAIT_TIME 0x0A
|
||||
|
||||
#define PN532_COMMAND_GETFIRMWAREVERSION 0x02
|
||||
#define PN532_COMMAND_SAMCONFIGURATION 0x14
|
||||
#define PN532_COMMAND_RFCONFIGURATION 0x32
|
||||
#define PN532_COMMAND_INDATAEXCHANGE 0x40
|
||||
#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A
|
||||
|
||||
#define PN532_MIFARE_ISO14443A 0x00
|
||||
#define MIFARE_CMD_READ 0x30
|
||||
#define MIFARE_CMD_AUTH_A 0x60
|
||||
#define MIFARE_CMD_AUTH_B 0x61
|
||||
#define MIFARE_CMD_WRITE 0xA0
|
||||
|
||||
uint8_t pn532_model = 0; // Used to maintain detection flag
|
||||
uint8_t pn532_command = 0; // Used to carry command code between functions
|
||||
uint8_t pn532_scantimer = 0; // Used to prevent multiple successful reads within 2 second window
|
||||
|
||||
uint8_t pn532_packetbuffer[64]; // Global buffer used to store packet
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
uint8_t pn532_function = 0;
|
||||
uint8_t pn532_newdata[16];
|
||||
uint8_t pn532_newdata_len = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_Init(void)
|
||||
{
|
||||
if ((pin[GPIO_PN532_RXD] < 99) && (pin[GPIO_PN532_TXD] < 99)) {
|
||||
PN532_Serial = new TasmotaSerial(pin[GPIO_PN532_RXD], pin[GPIO_PN532_TXD], 1);
|
||||
if (PN532_Serial->begin(115200)) {
|
||||
if (PN532_Serial->hardwareSerial()) { ClaimSerial(); }
|
||||
PN532_wakeup();
|
||||
uint32_t ver = PN532_getFirmwareVersion();
|
||||
if (ver) {
|
||||
PN532_setPassiveActivationRetries(0xFF);
|
||||
PN532_SAMConfig();
|
||||
pn532_model = 1;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC Reader detected (V%u.%u)",(ver>>16) & 0xFF, (ver>>8) & 0xFF);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int8_t PN532_receive(uint8_t *buf, int len, uint16_t timeout)
|
||||
{
|
||||
int read_bytes = 0;
|
||||
int ret;
|
||||
unsigned long start_millis;
|
||||
while (read_bytes < len) {
|
||||
start_millis = millis();
|
||||
do {
|
||||
ret = PN532_Serial->read();
|
||||
if (ret >= 0) {
|
||||
break;
|
||||
}
|
||||
} while((timeout == 0) || ((millis()- start_millis ) < timeout));
|
||||
|
||||
if (ret < 0) {
|
||||
if (read_bytes) {
|
||||
return read_bytes;
|
||||
} else {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
}
|
||||
buf[read_bytes] = (uint8_t)ret;
|
||||
read_bytes++;
|
||||
}
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
int8_t PN532_readAckFrame(void)
|
||||
{
|
||||
const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
|
||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
||||
|
||||
if (PN532_receive(ackBuf, sizeof(PN532_ACK), PN532_ACK_WAIT_TIME) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
|
||||
if (memcmp(&ackBuf, &PN532_ACK, sizeof(PN532_ACK))) {
|
||||
return PN532_INVALID_ACK;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen, const uint8_t *body = 0, uint8_t blen = 0)
|
||||
{
|
||||
// Clear the serial buffer just in case
|
||||
PN532_Serial->flush();
|
||||
|
||||
pn532_command = header[0];
|
||||
PN532_Serial->write((uint8_t)PN532_PREAMBLE);
|
||||
PN532_Serial->write((uint8_t)PN532_STARTCODE1);
|
||||
PN532_Serial->write(PN532_STARTCODE2);
|
||||
|
||||
uint8_t length = hlen + blen + 1; // length of data field: TFI + DATA
|
||||
PN532_Serial->write(length);
|
||||
PN532_Serial->write(~length + 1); // checksum of length
|
||||
|
||||
PN532_Serial->write(PN532_HOSTTOPN532);
|
||||
uint8_t sum = PN532_HOSTTOPN532; // sum of TFI + DATA
|
||||
|
||||
PN532_Serial->write(header, hlen);
|
||||
for (uint8_t i = 0; i < hlen; i++) {
|
||||
sum += header[i];
|
||||
}
|
||||
|
||||
PN532_Serial->write(body, blen);
|
||||
for (uint8_t i = 0; i < blen; i++) {
|
||||
sum += body[i];
|
||||
}
|
||||
|
||||
uint8_t checksum = ~sum + 1; // checksum of TFI + DATA
|
||||
PN532_Serial->write(checksum);
|
||||
PN532_Serial->write((uint8_t)PN532_POSTAMBLE);
|
||||
|
||||
return PN532_readAckFrame();
|
||||
}
|
||||
|
||||
int16_t PN532_readResponse(uint8_t buf[], uint8_t len, uint16_t timeout = 50)
|
||||
{
|
||||
uint8_t tmp[3];
|
||||
|
||||
// Read preamble and start code
|
||||
if (PN532_receive(tmp, 3, timeout)<=0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (0 != tmp[0] || 0!= tmp[1] || 0xFF != tmp[2]) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
// Get length of data to be received
|
||||
uint8_t length[2];
|
||||
if (PN532_receive(length, 2, timeout) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
// Validate that frame is valid
|
||||
if (0 != (uint8_t)(length[0] + length[1])) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
length[0] -= 2;
|
||||
if (length[0] > len) { // If this happens, then pn532_packetbuffer is not large enough
|
||||
return PN532_NO_SPACE;
|
||||
}
|
||||
|
||||
// Get the command byte
|
||||
uint8_t cmd = pn532_command + 1;
|
||||
if (PN532_receive(tmp, 2, timeout) <= 0) { // Time out while receiving
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (PN532_PN532TOHOST != tmp[0] || cmd != tmp[1]) { // Invalid frame received
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
if (PN532_receive(buf, length[0], timeout) != length[0]) { // Timed out
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
|
||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
||||
for (uint8_t i=0; i<length[0]; i++) {
|
||||
sum += buf[i];
|
||||
}
|
||||
|
||||
// Checksum & postamble
|
||||
if (PN532_receive(tmp, 2, timeout) <= 0) {
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
if (0 != (uint8_t)(sum + tmp[0]) || 0 != tmp[1]) { // Checksum fail, so frame must be invalid
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
return length[0];
|
||||
}
|
||||
|
||||
uint32_t PN532_getFirmwareVersion(void)
|
||||
{
|
||||
uint32_t response;
|
||||
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
|
||||
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 1)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Read data packet
|
||||
int16_t status = PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
if (0 > status) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
response = pn532_packetbuffer[0];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[1];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[2];
|
||||
response <<= 8;
|
||||
response |= pn532_packetbuffer[3];
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
void PN532_wakeup(void)
|
||||
{
|
||||
uint8_t wakeup[5] = {0x55, 0x55, 0, 0, 0 };
|
||||
PN532_Serial->write(wakeup,sizeof(wakeup));
|
||||
|
||||
// Flush the serial buffer just in case there's garbage in there
|
||||
PN532_Serial->flush();
|
||||
}
|
||||
|
||||
bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength, uint16_t timeout = 50)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
||||
pn532_packetbuffer[1] = 1; // max 1 cards at once (we can set this to 2 later)
|
||||
pn532_packetbuffer[2] = cardbaudrate;
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 3)) {
|
||||
return 0x0; // command failed
|
||||
}
|
||||
// read data packet
|
||||
if (PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer), timeout) < 0) {
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
/* Check some basic stuff
|
||||
b0 Tags Found
|
||||
b1 Tag Number (only one used in this example)
|
||||
b2..3 SENS_RES
|
||||
b4 SEL_RES
|
||||
b5 NFCID Length
|
||||
b6..NFCIDLen NFCID
|
||||
*/
|
||||
|
||||
if (pn532_packetbuffer[0] != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t sens_res = pn532_packetbuffer[2];
|
||||
sens_res <<= 8;
|
||||
sens_res |= pn532_packetbuffer[3];
|
||||
|
||||
/* Card appears to be Mifare Classic */
|
||||
*uidLength = pn532_packetbuffer[5];
|
||||
|
||||
for (uint8_t i = 0; i < pn532_packetbuffer[5]; i++) {
|
||||
uid[i] = pn532_packetbuffer[6 + i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool PN532_setPassiveActivationRetries(uint8_t maxRetries)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_RFCONFIGURATION;
|
||||
pn532_packetbuffer[1] = 5; // Config item 5 (MaxRetries)
|
||||
pn532_packetbuffer[2] = 0xFF; // MxRtyATR (default = 0xFF)
|
||||
pn532_packetbuffer[3] = 0x01; // MxRtyPSL (default = 0x01)
|
||||
pn532_packetbuffer[4] = maxRetries;
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 5)) {
|
||||
return 0; // no ACK
|
||||
}
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
bool PN532_SAMConfig(void)
|
||||
{
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
|
||||
pn532_packetbuffer[1] = 0x01; // normal mode
|
||||
pn532_packetbuffer[2] = 0x14; // timeout 50ms * 20 = 1 second
|
||||
pn532_packetbuffer[3] = 0x00; // we don't need the external IRQ pin
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 4)) {
|
||||
return false;
|
||||
}
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t _key[6];
|
||||
uint8_t _uid[7];
|
||||
uint8_t _uidLen;
|
||||
|
||||
// Hang on to the key and uid data
|
||||
memcpy(&_key, keyData, 6);
|
||||
memcpy(&_uid, uid, uidLen);
|
||||
_uidLen = uidLen;
|
||||
|
||||
// Prepare the authentication command //
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
|
||||
pn532_packetbuffer[1] = 1; /* Max card numbers */
|
||||
pn532_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
|
||||
memcpy(&pn532_packetbuffer[4], &_key, 6);
|
||||
for (i = 0; i < _uidLen; i++) {
|
||||
pn532_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
|
||||
}
|
||||
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 10 + _uidLen)) { return 0; }
|
||||
|
||||
// Read the response packet
|
||||
PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
|
||||
// Check if the response is valid and we are authenticated???
|
||||
// for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
|
||||
// Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
|
||||
if (pn532_packetbuffer[0] != 0x00) {
|
||||
// Authentification failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the command */
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer));
|
||||
|
||||
/* If byte 8 isn't 0x00 we probably have an error */
|
||||
if (pn532_packetbuffer[0] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the 16 data bytes to the output buffer */
|
||||
/* Block content starts at byte 9 of a valid response */
|
||||
memcpy (data, &pn532_packetbuffer[1], 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the first command */
|
||||
pn532_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
|
||||
pn532_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
memcpy(&pn532_packetbuffer[4], data, 16); /* Data Payload */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_packetbuffer, 20)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
return (0 < PN532_readResponse(pn532_packetbuffer, sizeof(pn532_packetbuffer)));
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_ScanForTag(void)
|
||||
{
|
||||
if (!pn532_model) { return; }
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t uid_len = 0;
|
||||
uint8_t card_data[16];
|
||||
bool erase_success = false;
|
||||
bool set_success = false;
|
||||
if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) {
|
||||
char uids[15];
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
char card_datas[34];
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
sprintf(uids,"");
|
||||
for (uint8_t i = 0;i < uid_len;i++) {
|
||||
sprintf(uids,"%s%02X",uids,uid[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
if (uid_len == 4) { // Lets try to read block 1 of the mifare classic card for more information
|
||||
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
|
||||
if (mifareclassic_ReadDataBlock(1, card_data)) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data));
|
||||
#else
|
||||
for (uint8_t i = 0;i < sizeof(card_data);i++) {
|
||||
if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) {
|
||||
card_datas[i] = char(card_data[i]);
|
||||
} else {
|
||||
card_datas[i] = '\0';
|
||||
}
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
if (pn532_function == 1) { // erase block 1 of card
|
||||
for (uint8_t i = 0;i<16;i++) {
|
||||
card_data[i] = 0x00;
|
||||
}
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
erase_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase success");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
}
|
||||
if (pn532_function == 2) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_data,&pn532_newdata,sizeof(card_data));
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
#else
|
||||
bool IsAlphaNumeric = true;
|
||||
for (uint8_t i = 0;i < pn532_newdata_len;i++) {
|
||||
if ((!isalpha(pn532_newdata[i])) && (!isdigit(pn532_newdata[i]))) {
|
||||
IsAlphaNumeric = false;
|
||||
}
|
||||
}
|
||||
if (IsAlphaNumeric) {
|
||||
memcpy(&card_data,&pn532_newdata,pn532_newdata_len);
|
||||
card_data[pn532_newdata_len] = '\0'; // Enforce null termination
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Data must be alphanumeric");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
} else {
|
||||
sprintf(card_datas,"AUTHFAIL");
|
||||
}
|
||||
}
|
||||
switch (pn532_function) {
|
||||
case 0x01:
|
||||
if (!erase_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Erase fail - exiting erase mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (!set_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Write failed - exiting set mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pn532_function = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas);
|
||||
#else
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
|
||||
#ifdef USE_PN532_CAUSE_EVENTS
|
||||
|
||||
char command[71];
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas);
|
||||
#else
|
||||
sprintf(command,"event PN532_UID=%s",uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
ExecuteCommand(command, SRC_RULE);
|
||||
#endif // USE_PN532_CAUSE_EVENTS
|
||||
|
||||
pn532_scantimer = 7; // Ignore tags found for two seconds
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool PN532_Command(void)
|
||||
{
|
||||
bool serviced = true;
|
||||
uint8_t paramcount = 0;
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
paramcount=1;
|
||||
} else {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
char sub_string[XdrvMailbox.data_len];
|
||||
char sub_string_tmp[XdrvMailbox.data_len];
|
||||
for (uint8_t ca=0;ca<XdrvMailbox.data_len;ca++) {
|
||||
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
|
||||
if (',' == XdrvMailbox.data[ca]) { paramcount++; }
|
||||
}
|
||||
UpperCase(XdrvMailbox.data,XdrvMailbox.data);
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
||||
pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00...
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be erased");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
||||
if (paramcount > 1) {
|
||||
if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
pn532_newdata_len = strlen(sub_string_tmp);
|
||||
if (pn532_newdata_len > 15) { pn532_newdata_len = 15; }
|
||||
memcpy(&pn532_newdata,&sub_string_tmp,pn532_newdata_len);
|
||||
pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string
|
||||
pn532_function = 2;
|
||||
snprintf_P(log_data, sizeof(log_data),"NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_newdata);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool Xsns40(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
PN532_Init();
|
||||
result = true;
|
||||
break;
|
||||
case FUNC_EVERY_50_MSECOND:
|
||||
break;
|
||||
case FUNC_EVERY_100_MSECOND:
|
||||
break;
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
if (pn532_scantimer > 0) {
|
||||
pn532_scantimer--;
|
||||
} else {
|
||||
PN532_ScanForTag();
|
||||
}
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
break;
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_40 == XdrvMailbox.index) {
|
||||
result = PN532_Command();
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_PN532_HSU
|
@ -1,606 +0,0 @@
|
||||
/*
|
||||
xsns_40_pn532.ino - Support for PN532 (I2C) NFC Tag Reader
|
||||
|
||||
Copyright (C) 2019 Andre Thomas and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_PN532_I2C
|
||||
|
||||
/*********************************************************************************************\
|
||||
* PN532 - Near Field Communication (NFC) controller
|
||||
*
|
||||
* Datasheet at https://www.nxp.com/docs/en/nxp/data-sheets/PN532_C1.pdf
|
||||
*
|
||||
* I2C Address: 0x24
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_40 40
|
||||
|
||||
#define PN532_I2C_ADDRESS 0x24
|
||||
|
||||
#define PN532_COMMAND_GETFIRMWAREVERSION 0x02
|
||||
#define PN532_COMMAND_SAMCONFIGURATION 0x14
|
||||
#define PN532_COMMAND_INDATAEXCHANGE 0x40
|
||||
#define PN532_COMMAND_INLISTPASSIVETARGET 0x4A
|
||||
|
||||
#define MIFARE_CMD_READ 0x30
|
||||
#define MIFARE_CMD_AUTH_A 0x60
|
||||
#define MIFARE_CMD_AUTH_B 0x61
|
||||
#define MIFARE_CMD_WRITE 0xA0
|
||||
|
||||
#define PN532_PREAMBLE 0x00
|
||||
#define PN532_STARTCODE1 0x00
|
||||
#define PN532_STARTCODE2 0xFF
|
||||
#define PN532_POSTAMBLE 0x00
|
||||
|
||||
#define PN532_HOSTTOPN532 0xD4
|
||||
#define PN532_PN532TOHOST 0xD5
|
||||
|
||||
#define PN532_INVALID_ACK -1
|
||||
#define PN532_TIMEOUT -2
|
||||
#define PN532_INVALID_FRAME -3
|
||||
#define PN532_NO_SPACE -4
|
||||
|
||||
#define PN532_MIFARE_ISO14443A 0x00
|
||||
|
||||
uint8_t pn532_i2c_detected = 0;
|
||||
uint8_t pn532_i2c_packetbuffer[64];
|
||||
uint8_t pn532_i2c_scan_defer_report = 0; // If a valid card was found we will not scan for one again in the same two seconds so we set this to 19 if a card was found
|
||||
uint8_t pn532_i2c_command = 0;
|
||||
|
||||
uint8_t pn532_i2c_disable = 0;
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
uint8_t pn532_i2c_function = 0;
|
||||
uint8_t pn532_i2c_newdata[16];
|
||||
uint8_t pn532_i2c_newdata_len = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
const uint8_t PROGMEM pn532_global_timeout = 10;
|
||||
|
||||
int16_t PN532_getResponseLength(uint8_t buf[], uint8_t len) {
|
||||
const uint8_t PN532_NACK[] = {0, 0, 0xFF, 0xFF, 0, 0};
|
||||
uint8_t time = 0;
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, 6)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) {
|
||||
return -1;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
uint8_t length = Wire.read();
|
||||
|
||||
// request for last respond msg again
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
for (uint16_t i = 0;i < sizeof(PN532_NACK); ++i) {
|
||||
Wire.write(PN532_NACK[i]);
|
||||
}
|
||||
Wire.endTransmission();
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int16_t PN532_readResponse(uint8_t buf[], uint8_t len)
|
||||
{
|
||||
uint8_t time = 0;
|
||||
uint8_t length;
|
||||
|
||||
length = PN532_getResponseLength(buf, len);
|
||||
|
||||
// [RDY] 00 00 FF LEN LCS (TFI PD0 ... PDn) DCS 00
|
||||
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, 6 + length + 2)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) {
|
||||
return -1;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if ((0x00 != Wire.read()) || (0x00 != Wire.read()) || (0xFF != Wire.read())) { // PREAMBLE || STARTCODE1 || STARTCODE2
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
length = Wire.read();
|
||||
|
||||
if (0 != (uint8_t)(length + Wire.read())) { // checksum of length
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
|
||||
uint8_t cmd = pn532_i2c_command + 1; // response command
|
||||
if ((PN532_PN532TOHOST != Wire.read()) || ((cmd) != Wire.read())) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
length -= 2;
|
||||
if (length > len) {
|
||||
return PN532_NO_SPACE; // not enough space
|
||||
}
|
||||
uint8_t sum = PN532_PN532TOHOST + cmd;
|
||||
for (uint8_t i = 0; i < length; i++) {
|
||||
buf[i] = Wire.read();
|
||||
sum += buf[i];
|
||||
}
|
||||
uint8_t checksum = Wire.read();
|
||||
if (0 != (uint8_t)(sum + checksum)) {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
Wire.read(); // POSTAMBLE
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
int8_t PN532_readAckFrame(void)
|
||||
{
|
||||
const uint8_t PN532_ACK[] = {0, 0, 0xFF, 0, 0xFF, 0};
|
||||
uint8_t ackBuf[sizeof(PN532_ACK)];
|
||||
|
||||
uint8_t time = 0;
|
||||
|
||||
do {
|
||||
if (Wire.requestFrom(PN532_I2C_ADDRESS, sizeof(PN532_ACK) + 1)) {
|
||||
if (Wire.read() & 1) { // check first byte --- status
|
||||
break; // PN532 is ready
|
||||
}
|
||||
}
|
||||
delay(1);
|
||||
time++;
|
||||
if (time > pn532_global_timeout) { // We time out after 10ms
|
||||
return PN532_TIMEOUT;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
for (uint8_t i = 0; i < sizeof(PN532_ACK); i++) {
|
||||
ackBuf[i] = Wire.read();
|
||||
}
|
||||
|
||||
if (memcmp(ackBuf, PN532_ACK, sizeof(PN532_ACK))) {
|
||||
return PN532_INVALID_ACK;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int8_t PN532_writeCommand(const uint8_t *header, uint8_t hlen)
|
||||
{
|
||||
pn532_i2c_command = header[0];
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
Wire.write(PN532_PREAMBLE);
|
||||
Wire.write(PN532_STARTCODE1);
|
||||
Wire.write(PN532_STARTCODE2);
|
||||
uint8_t length = hlen + 1; // TFI + DATA
|
||||
Wire.write(length);
|
||||
Wire.write(~length + 1); // checksum of length
|
||||
Wire.write(PN532_HOSTTOPN532);
|
||||
uint8_t sum = PN532_HOSTTOPN532; // Sum of TFI + DATA
|
||||
for (uint8_t i = 0; i < hlen; i++) {
|
||||
if (Wire.write(header[i])) {
|
||||
sum += header[i];
|
||||
} else {
|
||||
return PN532_INVALID_FRAME;
|
||||
}
|
||||
}
|
||||
uint8_t checksum = ~sum + 1; // Checksum of TFI + DATA
|
||||
Wire.write(checksum);
|
||||
Wire.write(PN532_POSTAMBLE);
|
||||
Wire.endTransmission();
|
||||
return PN532_readAckFrame();
|
||||
}
|
||||
|
||||
uint32_t PN532_getFirmwareVersion(void)
|
||||
{
|
||||
uint32_t response;
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_GETFIRMWAREVERSION;
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 1)) {
|
||||
return 0;
|
||||
}
|
||||
int16_t status = PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
if (0 > status) {
|
||||
return 0;
|
||||
}
|
||||
response = pn532_i2c_packetbuffer[0];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[1];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[2];
|
||||
response <<= 8;
|
||||
response |= pn532_i2c_packetbuffer[3];
|
||||
return response;
|
||||
}
|
||||
|
||||
bool PN532_SAMConfig(void)
|
||||
{
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_SAMCONFIGURATION;
|
||||
pn532_i2c_packetbuffer[1] = 0x01; // normal mode;
|
||||
pn532_i2c_packetbuffer[2] = 0x01; // timeout 50ms * 1 = 50ms
|
||||
pn532_i2c_packetbuffer[3] = 0x00; // Disable IRQ pin
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 4))
|
||||
return false;
|
||||
|
||||
return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)));
|
||||
}
|
||||
|
||||
void PN532_Detect(void)
|
||||
{
|
||||
if ((pn532_i2c_detected) || (pn532_i2c_disable)) { return; }
|
||||
|
||||
Wire.setClockStretchLimit(1000); // Enable 1ms clock stretch as per datasheet Table 12.25 (Timing for the I2C interface)
|
||||
|
||||
uint32_t ver = PN532_getFirmwareVersion();
|
||||
if (ver) {
|
||||
pn532_i2c_detected = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader (V%u.%u)", PN532_I2C_ADDRESS);
|
||||
snprintf_P(log_data, sizeof(log_data), log_data, (ver>>16) & 0xFF, (ver>>8) & 0xFF);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
PN532_SAMConfig();
|
||||
}
|
||||
}
|
||||
|
||||
bool PN532_readPassiveTargetID(uint8_t cardbaudrate, uint8_t *uid, uint8_t *uidLength)
|
||||
{
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
||||
pn532_i2c_packetbuffer[1] = 1;
|
||||
pn532_i2c_packetbuffer[2] = cardbaudrate;
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 3)) {
|
||||
return false; // command failed
|
||||
}
|
||||
|
||||
if (PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)) < 0) { // No data packet so no tag was found
|
||||
Wire.beginTransmission(PN532_I2C_ADDRESS);
|
||||
Wire.endTransmission();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pn532_i2c_packetbuffer[0] != 1) { return false; } // Not a valid tag
|
||||
|
||||
*uidLength = pn532_i2c_packetbuffer[5];
|
||||
for (uint8_t i = 0;i < pn532_i2c_packetbuffer[5]; i++) {
|
||||
uid[i] = pn532_i2c_packetbuffer[6 + i];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
uint8_t mifareclassic_AuthenticateBlock (uint8_t *uid, uint8_t uidLen, uint32_t blockNumber, uint8_t keyNumber, uint8_t *keyData)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t _key[6];
|
||||
uint8_t _uid[7];
|
||||
uint8_t _uidLen;
|
||||
|
||||
// Hang on to the key and uid data
|
||||
memcpy (_key, keyData, 6);
|
||||
memcpy (_uid, uid, uidLen);
|
||||
_uidLen = uidLen;
|
||||
|
||||
// Prepare the authentication command //
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE; /* Data Exchange Header */
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Max card numbers */
|
||||
pn532_i2c_packetbuffer[2] = (keyNumber) ? MIFARE_CMD_AUTH_B : MIFARE_CMD_AUTH_A;
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (1K = 0..63, 4K = 0..255 */
|
||||
memcpy (&pn532_i2c_packetbuffer[4], _key, 6);
|
||||
for (i = 0; i < _uidLen; i++) {
|
||||
pn532_i2c_packetbuffer[10 + i] = _uid[i]; /* 4 bytes card ID */
|
||||
}
|
||||
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 10 + _uidLen))
|
||||
return 0;
|
||||
|
||||
// Read the response packet
|
||||
PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
|
||||
// Check if the response is valid and we are authenticated???
|
||||
// for an auth success it should be bytes 5-7: 0xD5 0x41 0x00
|
||||
// Mifare auth error is technically byte 7: 0x14 but anything other and 0x00 is not good
|
||||
if (pn532_i2c_packetbuffer[0] != 0x00) {
|
||||
// Authentification failed
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_ReadDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the command */
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_i2c_packetbuffer[2] = MIFARE_CMD_READ; /* Mifare Read command = 0x30 */
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer));
|
||||
|
||||
/* If byte 8 isn't 0x00 we probably have an error */
|
||||
if (pn532_i2c_packetbuffer[0] != 0x00) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the 16 data bytes to the output buffer */
|
||||
/* Block content starts at byte 9 of a valid response */
|
||||
memcpy (data, &pn532_i2c_packetbuffer[1], 16);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t mifareclassic_WriteDataBlock (uint8_t blockNumber, uint8_t *data)
|
||||
{
|
||||
/* Prepare the first command */
|
||||
pn532_i2c_packetbuffer[0] = PN532_COMMAND_INDATAEXCHANGE;
|
||||
pn532_i2c_packetbuffer[1] = 1; /* Card number */
|
||||
pn532_i2c_packetbuffer[2] = MIFARE_CMD_WRITE; /* Mifare Write command = 0xA0 */
|
||||
pn532_i2c_packetbuffer[3] = blockNumber; /* Block Number (0..63 for 1K, 0..255 for 4K) */
|
||||
memcpy(&pn532_i2c_packetbuffer[4], data, 16); /* Data Payload */
|
||||
|
||||
/* Send the command */
|
||||
if (PN532_writeCommand(pn532_i2c_packetbuffer, 20)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read the response packet */
|
||||
return (0 < PN532_readResponse(pn532_i2c_packetbuffer, sizeof(pn532_i2c_packetbuffer)));
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
void PN532_ScanForTag(void)
|
||||
{
|
||||
if (pn532_i2c_disable) { return; }
|
||||
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t uid_len = 0;
|
||||
uint8_t card_data[16];
|
||||
bool erase_success = false;
|
||||
bool set_success = false;
|
||||
if (PN532_readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uid_len)) {
|
||||
if (pn532_i2c_scan_defer_report > 0) {
|
||||
pn532_i2c_scan_defer_report--;
|
||||
} else {
|
||||
char uids[15];
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
char card_datas[34];
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
sprintf(uids,"");
|
||||
for (uint8_t i = 0;i < uid_len;i++) {
|
||||
sprintf(uids,"%s%02X",uids,uid[i]);
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
if (uid_len == 4) { // Lets try to read block 0 of the mifare classic card for more information
|
||||
uint8_t keyuniversal[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
if (mifareclassic_AuthenticateBlock (uid, uid_len, 1, 1, keyuniversal)) {
|
||||
if (mifareclassic_ReadDataBlock(1, card_data)) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data));
|
||||
#else
|
||||
for (uint8_t i = 0;i < sizeof(card_data);i++) {
|
||||
if ((isalpha(card_data[i])) || ((isdigit(card_data[i])))) {
|
||||
card_datas[i] = char(card_data[i]);
|
||||
} else {
|
||||
card_datas[i] = '\0';
|
||||
}
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
if (pn532_i2c_function == 1) { // erase block 1 of card
|
||||
for (uint8_t i = 0;i<16;i++) {
|
||||
card_data[i] = 0x00;
|
||||
}
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
erase_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase success");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
}
|
||||
if (pn532_i2c_function == 2) {
|
||||
#ifdef USE_PN532_DATA_RAW
|
||||
memcpy(&card_data,&pn532_i2c_newdata,sizeof(card_data));
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
#else
|
||||
bool IsAlphaNumeric = true;
|
||||
for (uint8_t i = 0;i < pn532_i2c_newdata_len;i++) {
|
||||
if ((!isalpha(pn532_i2c_newdata[i])) && (!isdigit(pn532_i2c_newdata[i]))) {
|
||||
IsAlphaNumeric = false;
|
||||
}
|
||||
}
|
||||
if (IsAlphaNumeric) {
|
||||
memcpy(&card_data,&pn532_i2c_newdata,pn532_i2c_newdata_len);
|
||||
card_data[pn532_i2c_newdata_len] = '\0'; // Enforce null termination
|
||||
if (mifareclassic_WriteDataBlock(1, card_data)) {
|
||||
set_success = true;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data write successful");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
memcpy(&card_datas,&card_data,sizeof(card_data)); // Cast block 1 to a string
|
||||
}
|
||||
} else {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Data must be alphanumeric");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
#endif // USE_PN532_DATA_RAW
|
||||
}
|
||||
} else {
|
||||
sprintf(card_datas,"AUTHFAIL");
|
||||
}
|
||||
}
|
||||
switch (pn532_i2c_function) {
|
||||
case 0x01:
|
||||
if (!erase_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Erase fail - exiting erase mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
break;
|
||||
case 0x02:
|
||||
if (!set_success) {
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Write failed - exiting set mode");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pn532_i2c_function = 0;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas);
|
||||
#else
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
|
||||
#ifdef USE_PN532_CAUSE_EVENTS
|
||||
|
||||
char command[71];
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
sprintf(command,"backlog event PN532_UID=%s;event PN532_DATA=%s",uids,card_datas);
|
||||
#else
|
||||
sprintf(command,"event PN532_UID=%s",uids);
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
ExecuteCommand(command, SRC_RULE);
|
||||
#endif // USE_PN532_CAUSE_EVENTS
|
||||
|
||||
pn532_i2c_scan_defer_report = 7; // Ignore tags found for two seconds
|
||||
}
|
||||
} else {
|
||||
if (pn532_i2c_scan_defer_report > 0) { pn532_i2c_scan_defer_report--; }
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
|
||||
bool PN532_Command(void)
|
||||
{
|
||||
bool serviced = true;
|
||||
uint8_t paramcount = 0;
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
paramcount=1;
|
||||
} else {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
char sub_string[XdrvMailbox.data_len];
|
||||
char sub_string_tmp[XdrvMailbox.data_len];
|
||||
for (uint8_t ca=0;ca<XdrvMailbox.data_len;ca++) {
|
||||
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
|
||||
if (',' == XdrvMailbox.data[ca]) { paramcount++; }
|
||||
}
|
||||
UpperCase(XdrvMailbox.data,XdrvMailbox.data);
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) {
|
||||
pn532_i2c_function = 1; // Block 0 of next card/tag will be reset to 0x00...
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be erased");
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) {
|
||||
if (paramcount > 1) {
|
||||
if (XdrvMailbox.data[XdrvMailbox.data_len-1] == ',') {
|
||||
serviced = false;
|
||||
return serviced;
|
||||
}
|
||||
sprintf(sub_string_tmp,subStr(sub_string, XdrvMailbox.data, ",", 2));
|
||||
pn532_i2c_newdata_len = strlen(sub_string_tmp);
|
||||
if (pn532_i2c_newdata_len > 15) { pn532_i2c_newdata_len = 15; }
|
||||
memcpy(&pn532_i2c_newdata,&sub_string_tmp,pn532_i2c_newdata_len);
|
||||
pn532_i2c_newdata[pn532_i2c_newdata_len] = 0x00; // Null terminate the string
|
||||
pn532_i2c_function = 2;
|
||||
snprintf_P(log_data, sizeof(log_data),"I2C: PN532 NFC - Next scanned tag data block 1 will be set to '%s'",pn532_i2c_newdata);
|
||||
AddLog(LOG_LEVEL_INFO);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data);
|
||||
return serviced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns40(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
if (pn532_i2c_detected) {
|
||||
PN532_ScanForTag();
|
||||
}
|
||||
break;
|
||||
case FUNC_EVERY_SECOND:
|
||||
PN532_Detect();
|
||||
break;
|
||||
|
||||
#ifdef USE_PN532_DATA_FUNCTION
|
||||
case FUNC_COMMAND:
|
||||
if (XSNS_40 == XdrvMailbox.index) {
|
||||
result = PN532_Command();
|
||||
}
|
||||
break;
|
||||
#endif // USE_PN532_DATA_FUNCTION
|
||||
|
||||
case FUNC_SAVE_BEFORE_RESTART:
|
||||
if (!pn532_i2c_disable) {
|
||||
pn532_i2c_disable = 1;
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "PN532 NFC Reader - Disabling for reboot", PN532_I2C_ADDRESS);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_PN532_I2C
|
||||
#endif // USE_I2C
|
@ -123,8 +123,8 @@ a_features = [[
|
||||
"USE_TIMERS","USE_SUNRISE","USE_TIMERS_WEB","USE_RULES",
|
||||
"USE_KNX","USE_WPS","USE_SMARTCONFIG","MQTT_ARDUINOMQTT"
|
||||
],[
|
||||
"USE_CONFIG_OVERRIDE","BE_MINIMAL","USE_SENSORS","USE_CLASSIC",
|
||||
"USE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD",
|
||||
"USE_CONFIG_OVERRIDE","FIRMWARE_MINIMAL","FIRMWARE_SENSORS","FIRMWARE_CLASSIC",
|
||||
"FIRMWARE_KNX_NO_EMULATION","USE_DISPLAY_MODES1TO5","USE_DISPLAY_GRAPH","USE_DISPLAY_LCD",
|
||||
"USE_DISPLAY_SSD1306","USE_DISPLAY_MATRIX","USE_DISPLAY_ILI9341","USE_DISPLAY_EPAPER",
|
||||
"USE_DISPLAY_SH1106","USE_MP3_PLAYER","USE_PCA9685","USE_TUYA_DIMMER",
|
||||
"USE_RC_SWITCH","USE_ARMTRONIX_DIMMERS","","",
|
||||
|
Loading…
x
Reference in New Issue
Block a user