diff --git a/Device_Groups.md b/Device_Groups.md
index 40bca68a7..c109865af 100644
--- a/Device_Groups.md
+++ b/Device_Groups.md
@@ -11,7 +11,7 @@ To enable device groups, execute the command SetOption85 1.
## Device Groups Operation
-The device group name is the MQTT group topic set with the GroupTopic command. All devices in the same IP network with the same group topic are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups.
+The device group name is set with the DevGroupName command. If the device group name is not set for a group, the MQTT group topic is used (with the device group number appended for device group numbers > 1). All devices in the same IP network with the same device group name are in the same group. Some modules may define additional device groups. For example, if Remote Device Mode is enabled, the PWM Dimmer module defines three devices groups.
The items that are sent to the group and the items that are received from the group are selected with the DevGroupShare command. By default all items are sent and received from the group. An example of when the DevGroupShare command would be used is when you have a group of lights that you control with a dimmer switch and home automation software. You want the dimmer switch to be able to control all items. The home automation software controls each light individually. When it controls the whole group, it actually sends command to each light in the group. If you use the home automation software to turn an individual light on or off or change it’s brightness, color or scheme, you do not want the change to be replicated to the other lights. In this case, you would set the incoming and outgoing item masks to 0xffffffff (all items) on the dimmer switch (DevGroupShare 0xffffffff,0xffffffff) and set the incoming item mask to 0xffffffff and outgoing item mask to 0 on all the lights (DevGroupShare 0xffffffff,0).
@@ -34,10 +34,10 @@ The items that are sent to the group and the items that are received from the gr
- GroupTopic<x>
+ | DevGroupName<x>
|
- 1 = reset device group <x> MQTT group topic to firmware default (MQTT_GRPTOPIC) and restart
-<value> = set device group <x> MQTT group topic (32 chars max) and restart
+ | 0 = clear device group <x> name and restart
+<value> = set device group <x>name and restart
|
\ No newline at end of file
diff --git a/lib/ArduinoNTPd/NTPServer.cpp b/lib/ArduinoNTPd/NTPServer.cpp
index 6ee82bd6c..a5d0515d0 100644
--- a/lib/ArduinoNTPd/NTPServer.cpp
+++ b/lib/ArduinoNTPd/NTPServer.cpp
@@ -17,63 +17,81 @@
bool NtpServer::beginListening()
{
- if (timeServerPort_.begin(NTP_PORT)){
- return true;
- }
- return false;
+ if (timeServerPort_.begin(NTP_PORT)){
+ return true;
+ }
+ return false;
}
bool NtpServer::processOneRequest(uint32_t utc, uint32_t millisecs)
{
- // We need the time we've received the packet in our response.
- uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
- double recvFractDouble = (double)millisecs/0.00023283064365386963; // millisec/((10^6)/(2^32))
- uint32_t recvFract = (double)recvFractDouble; //TODO: really handle this!!!
- bool processed = false;
-
- int packetDataSize = timeServerPort_.parsePacket();
- if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
- {
- // Received what is probably an NTP packet. Read it in and verify
- // that it's legit.
- NtpPacket packet;
- timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
- // TODO: verify packet.
+ // millisecs is millis() at the time of the last iTOW reception, where iTOW%1000 == 0
+ uint32_t refMillis = millis()-millisecs;
+ if (refMillis>999){
+ utc++;
+ refMillis = refMillis%1000;
+ }
- // Populate response.
- packet.swapEndian();
- packet.leapIndicator(0);
- packet.versionNumber(4);
- packet.mode(4);
- packet.stratum = 2; // I guess stratum 1 is too optimistic
- packet.poll = 10; // 6-10 per RFC 5905.
- packet.precision = -21; // ~0.5 microsecond precision.
- packet.rootDelay = 0; //60 * (0xFFFF / 1000); // ~60 milliseconds, TBD
- packet.rootDispersion = 0; //10 * (0xFFFF / 1000); // ~10 millisecond dispersion, TBD
- packet.referenceId[0] = 'G';
- packet.referenceId[1] = 'P';
- packet.referenceId[2] = 'S';
- packet.referenceId[3] = 0;
- packet.referenceTimestampSeconds = utc;
- packet.referenceTimestampFraction = recvFract;
- packet.originTimestampSeconds = packet.transmitTimestampSeconds;
- packet.originTimestampFraction = packet.transmitTimestampFraction;
- packet.receiveTimestampSeconds = recvSecs;
- packet.receiveTimestampFraction = recvFract;
-
- // ...and the transmit time.
- // timeSource_.now(&packet.transmitTimestampSeconds, &packet.transmitTimestampFraction);
-
- // Now transmit the response to the client.
- packet.swapEndian();
- timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
- for (int count = 0; count < NtpPacket::PACKET_SIZE; count++)
- {
- timeServerPort_.write(packet.packet()[count]);
- }
- timeServerPort_.endPacket();
- processed = true;
- }
-
- return processed;
+ bool processed = false;
+
+ int packetDataSize = timeServerPort_.parsePacket();
+ if (packetDataSize && packetDataSize >= NtpPacket::PACKET_SIZE)
+ {
+ // We need the time we've received the packet in our response.
+ uint32_t recvSecs = utc + NTP_TIMESTAMP_DIFF;
+
+ uint64_t recvFract64 = refMillis;
+ recvFract64 <<= 32;
+ recvFract64 /= 1000;
+ uint32_t recvFract = recvFract64 & 0xffffffff;
+ // is equal to:
+ // uint32_t recvFract = (double)(refMillis)/0.00000023283064365386963;
+
+ // Received what is probably an NTP packet. Read it in and verify
+ // that it's legit.
+ NtpPacket packet;
+ timeServerPort_.read((char*)&packet, NtpPacket::PACKET_SIZE);
+ // TODO: verify packet.
+
+ // Populate response.
+ packet.swapEndian();
+ packet.leapIndicator(0);
+ packet.versionNumber(4);
+ packet.mode(4);
+ packet.stratum = 1; // >1 will lead to misinterpretation of refId
+ packet.poll = 10; // 6-10 per RFC 5905.
+ packet.precision = -21; // ~0.5 microsecond precision.
+ packet.rootDelay = 100 * (0xFFFF / 1000); //~100 milliseconds
+ packet.rootDispersion = 50 * (0xFFFF / 1000);; //~50 millisecond dispersion
+ packet.referenceId[0] = 'G';
+ packet.referenceId[1] = 'P';
+ packet.referenceId[2] = 'S';
+ packet.referenceId[3] = 0;
+ packet.referenceTimestampSeconds = recvSecs;
+ packet.referenceTimestampFraction = 0; // the "click" of the GPS
+ packet.originTimestampSeconds = packet.transmitTimestampSeconds;
+ packet.originTimestampFraction = packet.transmitTimestampFraction;
+ packet.receiveTimestampSeconds = recvSecs;
+ packet.receiveTimestampFraction = recvFract;
+
+ // ...and the transmit time.
+ // the latency has been between 135 and 175 microseconds in internal testing, so we harcode 150
+ uint32_t transFract = recvFract+(150*(10^3)/(2^32)); // microsec/((10^3)/(2^32))
+ if (recvFract>transFract){
+ recvSecs++; //overflow
+ }
+ packet.transmitTimestampSeconds = recvSecs;
+ packet.transmitTimestampFraction = transFract;
+
+ // Now transmit the response to the client.
+ packet.swapEndian();
+
+ timeServerPort_.beginPacket(timeServerPort_.remoteIP(), timeServerPort_.remotePort());
+ timeServerPort_.write(packet.packet(), NtpPacket::PACKET_SIZE);
+ timeServerPort_.endPacket();
+
+ processed = true;
+ }
+
+ return processed;
}
\ No newline at end of file
diff --git a/platformio.ini b/platformio.ini
index 6b0bb6edc..6a3820d02 100644
--- a/platformio.ini
+++ b/platformio.ini
@@ -57,8 +57,7 @@ default_envs =
framework = arduino
board = esp01_1m
board_build.flash_mode = dout
-; board_build.ldscript = eagle.flash.1m.ld
-board_build.ldscript = ${PROJECTSRC_DIR}/ld/eagle.flash.1m.ld_FP_IN_IROM
+board_build.ldscript = eagle.flash.1m.ld
platform = ${core_active.platform}
platform_packages = ${core_active.platform_packages}
@@ -92,6 +91,7 @@ extra_scripts = pio/strip-floats.py
build_flags = -D NDEBUG
-mtarget-align
-Wl,-Map,firmware.map
+ -DFP_IN_IROM
; new mechanism to set the IRremoteESP8266 supported protocols: none except HASH, NEC, RC5, RC6
-D_IR_ENABLE_DEFAULT_=false
-DDECODE_HASH=true -DDECODE_NEC=true -DSEND_NEC=true
diff --git a/platformio_override_sample.ini b/platformio_override_sample.ini
index f8ff1af64..70be7c34e 100644
--- a/platformio_override_sample.ini
+++ b/platformio_override_sample.ini
@@ -179,7 +179,7 @@ build_flags = ${esp82xx_defaults.build_flags}
[tasmota_feature_stage]
; *** Esp8266 core for Arduino version Tasmota feature stage
platform = espressif8266@2.4.0
-platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#e64cb619f79a3c888dd56b957d8f48ce74f35735
+platform_packages = framework-arduinoespressif8266 @ https://github.com/esp8266/Arduino.git#d600cc7fa6c3fc5c31ed903ec12fd2e2da2c3678
build_flags = ${esp82xx_defaults.build_flags}
-DBEARSSL_SSL_BASIC
; NONOSDK221
diff --git a/tasmota/CHANGELOG.md b/tasmota/CHANGELOG.md
index 924a76c44..f6a964397 100644
--- a/tasmota/CHANGELOG.md
+++ b/tasmota/CHANGELOG.md
@@ -17,6 +17,7 @@
- Add command ``SetOption90 1`` to disable non-json MQTT messages (#8044)
- Add command ``Sensor10 0/1/2`` to control BH1750 resolution - 0 = High (default), 1 = High2, 2 = Low (#8016)
- Add command ``Sensor10 31..254`` to control BH1750 measurement time which defaults to 69 (#8016)
+- Add command ``SetOption91 1`` to enable fading at startup / power on
### 8.2.0.2 20200328
diff --git a/tasmota/i18n.h b/tasmota/i18n.h
index 7f225838e..6a6f04cec 100644
--- a/tasmota/i18n.h
+++ b/tasmota/i18n.h
@@ -293,6 +293,7 @@
#define D_CMND_SPEEDUNIT "SpeedUnit"
#define D_CMND_I2CSCAN "I2CScan"
#define D_CMND_I2CDRIVER "I2CDriver"
+#define D_CMND_DEVGROUP_NAME "DevGroupName"
#define D_CMND_DEVGROUP_SHARE "DevGroupShare"
#define D_CMND_SERIALSEND "SerialSend"
#define D_CMND_SERIALDELIMITER "SerialDelimiter"
diff --git a/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM b/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM
deleted file mode 100644
index 3e338cebd..000000000
--- a/tasmota/ld/eagle.flash.1m.ld_FP_IN_IROM
+++ /dev/null
@@ -1,336 +0,0 @@
-/* Flash Split for 1M chips */
-/* sketch @0x40200000 (~999KB) (1023984B) */
-/* empty @0x402F9FF0 (~4KB) (4112B) */
-/* spiffs @0x402FB000 (~0KB) (0B) */
-/* eeprom @0x402FB000 (4KB) */
-/* rfcal @0x402FC000 (4KB) */
-/* wifi @0x402FD000 (12KB) */
-
-MEMORY
-{
- dport0_0_seg : org = 0x3FF00000, len = 0x10
- dram0_0_seg : org = 0x3FFE8000, len = 0x14000
- iram1_0_seg : org = 0x40100000, len = 0x8000
- irom0_0_seg : org = 0x40201010, len = 0xf9ff0
-}
-
-PROVIDE ( _FS_start = 0x402FB000 );
-PROVIDE ( _FS_end = 0x402FB000 );
-PROVIDE ( _FS_page = 0x0 );
-PROVIDE ( _FS_block = 0x0 );
-PROVIDE ( _EEPROM_start = 0x402fb000 );
-/* The following symbols are DEPRECATED and will be REMOVED in a future release */
-PROVIDE ( _SPIFFS_start = 0x402FB000 );
-PROVIDE ( _SPIFFS_end = 0x402FB000 );
-PROVIDE ( _SPIFFS_page = 0x0 );
-PROVIDE ( _SPIFFS_block = 0x0 );
-
-/* This linker script generated from xt-genldscripts.tpp for LSP . */
-/* Linker Script for ld -N */
-
-PHDRS
-{
- dport0_0_phdr PT_LOAD;
- dram0_0_phdr PT_LOAD;
- dram0_0_bss_phdr PT_LOAD;
- iram1_0_phdr PT_LOAD;
- irom0_0_phdr PT_LOAD;
-}
-
-
-/* Default entry point: */
-ENTRY(app_entry)
-EXTERN(_DebugExceptionVector)
-EXTERN(_DoubleExceptionVector)
-EXTERN(_KernelExceptionVector)
-EXTERN(_NMIExceptionVector)
-EXTERN(_UserExceptionVector)
-EXTERN(core_version)
-PROVIDE(_memmap_vecbase_reset = 0x40000000);
-/* Various memory-map dependent cache attribute settings: */
-_memmap_cacheattr_wb_base = 0x00000110;
-_memmap_cacheattr_wt_base = 0x00000110;
-_memmap_cacheattr_bp_base = 0x00000220;
-_memmap_cacheattr_unused_mask = 0xFFFFF00F;
-_memmap_cacheattr_wb_trapnull = 0x2222211F;
-_memmap_cacheattr_wba_trapnull = 0x2222211F;
-_memmap_cacheattr_wbna_trapnull = 0x2222211F;
-_memmap_cacheattr_wt_trapnull = 0x2222211F;
-_memmap_cacheattr_bp_trapnull = 0x2222222F;
-_memmap_cacheattr_wb_strict = 0xFFFFF11F;
-_memmap_cacheattr_wt_strict = 0xFFFFF11F;
-_memmap_cacheattr_bp_strict = 0xFFFFF22F;
-_memmap_cacheattr_wb_allvalid = 0x22222112;
-_memmap_cacheattr_wt_allvalid = 0x22222112;
-_memmap_cacheattr_bp_allvalid = 0x22222222;
-PROVIDE(_memmap_cacheattr_reset = _memmap_cacheattr_wb_trapnull);
-
-SECTIONS
-{
-
- .dport0.rodata : ALIGN(4)
- {
- _dport0_rodata_start = ABSOLUTE(.);
- *(.dport0.rodata)
- *(.dport.rodata)
- _dport0_rodata_end = ABSOLUTE(.);
- } >dport0_0_seg :dport0_0_phdr
-
- .dport0.literal : ALIGN(4)
- {
- _dport0_literal_start = ABSOLUTE(.);
- *(.dport0.literal)
- *(.dport.literal)
- _dport0_literal_end = ABSOLUTE(.);
- } >dport0_0_seg :dport0_0_phdr
-
- .dport0.data : ALIGN(4)
- {
- _dport0_data_start = ABSOLUTE(.);
- *(.dport0.data)
- *(.dport.data)
- _dport0_data_end = ABSOLUTE(.);
- } >dport0_0_seg :dport0_0_phdr
-
- .data : ALIGN(4)
- {
- _data_start = ABSOLUTE(.);
- *(.data)
- *(.data.*)
- *(.gnu.linkonce.d.*)
- *(.data1)
- *(.sdata)
- *(.sdata.*)
- *(.gnu.linkonce.s.*)
- *(.sdata2)
- *(.sdata2.*)
- *(.gnu.linkonce.s2.*)
- *(.jcr)
- . = ALIGN(4);
- _Pri_3_HandlerAddress = ABSOLUTE(.);
- _data_end = ABSOLUTE(.);
- } >dram0_0_seg :dram0_0_phdr
-
- .noinit : ALIGN(4)
- {
- *(.noinit)
- } >dram0_0_seg :dram0_0_phdr
-
- /* IRAM is split into .text and .text1 to allow for moving specific */
- /* functions into IRAM that would be matched by the irom0.text matcher */
- .text : ALIGN(4)
- {
- _stext = .;
- _text_start = ABSOLUTE(.);
- *(.UserEnter.text)
- . = ALIGN(16);
- *(.DebugExceptionVector.text)
- . = ALIGN(16);
- *(.NMIExceptionVector.text)
- . = ALIGN(16);
- *(.KernelExceptionVector.text)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- . = ALIGN(16);
- *(.UserExceptionVector.text)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- . = ALIGN(16);
- *(.DoubleExceptionVector.text)
- LONG(0)
- LONG(0)
- LONG(0)
- LONG(0)
- . = ALIGN (16);
- *(.entry.text)
- *(.init.literal)
- *(.init)
-
- *(.text.app_entry*) /* The main startup code */
-
- *(.text.gdbstub*, .text.gdb_init) /* Any GDB hooks */
-
- /* all functional callers are placed in IRAM (including SPI/IRQ callbacks/etc) here */
- *(.text._ZNKSt8functionIF*EE*) /* std::function::operator()() const */
- } >iram1_0_seg :iram1_0_phdr
-
- .irom0.text : ALIGN(4)
- {
- _irom0_text_start = ABSOLUTE(.);
- *(.ver_number)
- *.c.o(.literal*, .text*)
- *.cpp.o(EXCLUDE_FILE (umm_malloc.cpp.o) .literal*, EXCLUDE_FILE (umm_malloc.cpp.o) .text*)
- *.cc.o(.literal*, .text*)
-/* #ifdef VTABLES_IN_FLASH */
- *(.rodata._ZTV*) /* C++ vtables */
-/* #endif */
-
- *libgcc.a:unwind-dw2.o(.literal .text .rodata .literal.* .text.* .rodata.*)
- *libgcc.a:unwind-dw2-fde.o(.literal .text .rodata .literal.* .text.* .rodata.*)
-
- *libc.a:(.literal .text .literal.* .text.*)
- *libm.a:(.literal .text .literal.* .text.*)
-/* #ifdef FP_IN_IROM */
- *libgcc.a:*f2.o(.literal .text)
- *libgcc.a:*f3.o(.literal .text)
- *libgcc.a:*fsi.o(.literal .text)
- *libgcc.a:*fdi.o(.literal .text)
- *libgcc.a:*ifs.o(.literal .text)
- *libgcc.a:*idf.o(.literal .text)
-/* #endif */
- *libgcc.a:_umoddi3.o(.literal .text)
- *libgcc.a:_udivdi3.o(.literal .text)
- *libstdc++.a:( .literal .text .literal.* .text.*)
- *libstdc++-exc.a:( .literal .text .literal.* .text.*)
- *libsmartconfig.a:(.literal .text .literal.* .text.*)
- *liblwip_gcc.a:(.literal .text .literal.* .text.*)
- *liblwip_src.a:(.literal .text .literal.* .text.*)
- *liblwip2-536.a:(.literal .text .literal.* .text.*)
- *liblwip2-1460.a:(.literal .text .literal.* .text.*)
- *liblwip2-536-feat.a:(.literal .text .literal.* .text.*)
- *liblwip2-1460-feat.a:(.literal .text .literal.* .text.*)
- *liblwip6-536-feat.a:(.literal .text .literal.* .text.*)
- *liblwip6-1460-feat.a:(.literal .text .literal.* .text.*)
- *libbearssl.a:(.literal .text .literal.* .text.*)
- *libaxtls.a:(.literal .text .literal.* .text.*)
- *libat.a:(.literal.* .text.*)
- *libcrypto.a:(.literal.* .text.*)
- *libespnow.a:(.literal.* .text.*)
- *libjson.a:(.literal.* .text.*)
- *liblwip.a:(.literal.* .text.*)
- *libmesh.a:(.literal.* .text.*)
- *libnet80211.a:(.literal.* .text.*)
- *libsmartconfig.a:(.literal.* .text.*)
- *libssl.a:(.literal.* .text.*)
- *libupgrade.a:(.literal.* .text.*)
- *libwpa.a:(.literal.* .text.*)
- *libwpa2.a:(.literal.* .text.*)
- *libwps.a:(.literal.* .text.*)
- *(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom0.text.* .irom.text .irom.text.*)
-
- /* Constant strings in flash (PSTRs) */
- *(.irom0.pstr.*)
-
- /* __FUNCTION__ locals */
- *(.rodata._ZZ*__FUNCTION__)
- *(.rodata._ZZ*__PRETTY_FUNCTION__)
- *(.rodata._ZZ*__func__)
-
- /* std::* exception strings, in their own section to allow string coalescing */
- *(.irom.exceptiontext)
-
- /* c++ typeof IDs, etc. */
- *(.rodata._ZTIN* .rodata._ZTSN10* .rodata._ZTISt* .rodata._ZTSSt*)
-
- /* Fundamental type info */
- *(.rodata._ZTIPKc .rodata._ZTIc .rodata._ZTIv .rodata._ZTSv .rodata._ZTSc .rodata._ZTSPKc .rodata._ZTSi .rodata._ZTIi)
-
- . = ALIGN(4);
- *(.gcc_except_table .gcc_except_table.*)
- . = ALIGN(4);
- __eh_frame = ABSOLUTE(.);
- KEEP(*(.eh_frame))
- . = (. + 7) & ~ 3; /* Add a 0 entry to terminate the list */
-
- _irom0_text_end = ABSOLUTE(.);
- _flash_code_end = ABSOLUTE(.);
- } >irom0_0_seg :irom0_0_phdr
-
-
-
- .text1 : ALIGN(4)
- {
- *(.literal .text .iram.literal .iram.text .iram.text.* .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
-
- *(.fini.literal)
- *(.fini)
- *(.gnu.version)
- _text_end = ABSOLUTE(.);
- _etext = .;
- } >iram1_0_seg :iram1_0_phdr
-
- .rodata : ALIGN(4)
- {
- _rodata_start = ABSOLUTE(.);
- *(.sdk.version)
- *(.rodata)
- *(.rodata.*)
- *(.gnu.linkonce.r.*)
- *(.rodata1)
- __XT_EXCEPTION_TABLE__ = ABSOLUTE(.);
- *(.xt_except_table)
- *(.gcc_except_table)
- *(.gnu.linkonce.e.*)
- *(.gnu.version_r)
- *(.eh_frame)
- . = (. + 3) & ~ 3;
- /* C++ constructor and destructor tables, properly ordered: */
- __init_array_start = ABSOLUTE(.);
- KEEP (*crtbegin.o(.ctors))
- KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
- KEEP (*(SORT(.ctors.*)))
- KEEP (*(.ctors))
- __init_array_end = ABSOLUTE(.);
- KEEP (*crtbegin.o(.dtors))
- KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
- KEEP (*(SORT(.dtors.*)))
- KEEP (*(.dtors))
- /* C++ exception handlers table: */
- __XT_EXCEPTION_DESCS__ = ABSOLUTE(.);
- *(.xt_except_desc)
- *(.gnu.linkonce.h.*)
- __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
- *(.xt_except_desc_end)
- *(.dynamic)
- *(.gnu.version_d)
- . = ALIGN(4); /* this table MUST be 4-byte aligned */
- _bss_table_start = ABSOLUTE(.);
- LONG(_bss_start)
- LONG(_bss_end)
- _bss_table_end = ABSOLUTE(.);
- _rodata_end = ABSOLUTE(.);
- } >dram0_0_seg :dram0_0_phdr
-
- .bss ALIGN(8) (NOLOAD) : ALIGN(4)
- {
- . = ALIGN (8);
- _bss_start = ABSOLUTE(.);
- *(.dynsbss)
- *(.sbss)
- *(.sbss.*)
- *(.gnu.linkonce.sb.*)
- *(.scommon)
- *(.sbss2)
- *(.sbss2.*)
- *(.gnu.linkonce.sb2.*)
- *(.dynbss)
- *(.bss)
- *(.bss.*)
- *(.gnu.linkonce.b.*)
- *(COMMON)
- . = ALIGN (8);
- _bss_end = ABSOLUTE(.);
- _heap_start = ABSOLUTE(.);
-/* _stack_sentry = ALIGN(0x8); */
- } >dram0_0_seg :dram0_0_bss_phdr
-/* __stack = 0x3ffc8000; */
-
-
- .lit4 : ALIGN(4)
- {
- _lit4_start = ABSOLUTE(.);
- *(*.lit4)
- *(.lit4.*)
- *(.gnu.linkonce.lit4.*)
- _lit4_end = ABSOLUTE(.);
- } >iram1_0_seg :iram1_0_phdr
-
-
-}
-
-/* get ROM code address */
-INCLUDE "../ld/eagle.rom.addr.v6.ld"
diff --git a/tasmota/ld/eagle.rom.addr.v6.ld b/tasmota/ld/eagle.rom.addr.v6.ld
deleted file mode 100644
index 84c5e3acf..000000000
--- a/tasmota/ld/eagle.rom.addr.v6.ld
+++ /dev/null
@@ -1,352 +0,0 @@
-PROVIDE ( Cache_Read_Disable = 0x400047f0 );
-PROVIDE ( Cache_Read_Enable = 0x40004678 );
-PROVIDE ( FilePacketSendReqMsgProc = 0x400035a0 );
-PROVIDE ( FlashDwnLdParamCfgMsgProc = 0x4000368c );
-PROVIDE ( FlashDwnLdStartMsgProc = 0x40003538 );
-PROVIDE ( FlashDwnLdStopReqMsgProc = 0x40003658 );
-PROVIDE ( GetUartDevice = 0x40003f4c );
-PROVIDE ( MD5Final = 0x40009900 );
-PROVIDE ( MD5Init = 0x40009818 );
-PROVIDE ( MD5Update = 0x40009834 );
-PROVIDE ( MemDwnLdStartMsgProc = 0x400036c4 );
-PROVIDE ( MemDwnLdStopReqMsgProc = 0x4000377c );
-PROVIDE ( MemPacketSendReqMsgProc = 0x400036f0 );
-PROVIDE ( RcvMsg = 0x40003eac );
-PROVIDE ( SHA1Final = 0x4000b648 );
-PROVIDE ( SHA1Init = 0x4000b584 );
-PROVIDE ( SHA1Transform = 0x4000a364 );
-PROVIDE ( SHA1Update = 0x4000b5a8 );
-PROVIDE ( SPI_read_status = 0x400043c8 );
-PROVIDE ( SPI_write_status = 0x40004400 );
-PROVIDE ( SPI_write_enable = 0x4000443c );
-PROVIDE ( Wait_SPI_Idle = 0x4000448c );
-PROVIDE ( Enable_QMode = 0x400044c0 );
-PROVIDE ( SPIEraseArea = 0x40004b44 );
-PROVIDE ( SPIEraseBlock = 0x400049b4 );
-PROVIDE ( SPIEraseChip = 0x40004984 );
-PROVIDE ( SPIEraseSector = 0x40004a00 );
-PROVIDE ( SPILock = 0x400048a8 );
-PROVIDE ( SPIParamCfg = 0x40004c2c );
-PROVIDE ( SPIRead = 0x40004b1c );
-PROVIDE ( SPIReadModeCnfig = 0x400048ec );
-PROVIDE ( SPIUnlock = 0x40004878 );
-PROVIDE ( SPIWrite = 0x40004a4c );
-PROVIDE ( SelectSpiFunction = 0x40003f58 );
-PROVIDE ( SendMsg = 0x40003cf4 );
-PROVIDE ( UartConnCheck = 0x40003230 );
-PROVIDE ( UartConnectProc = 0x400037a0 );
-PROVIDE ( UartDwnLdProc = 0x40003368 );
-PROVIDE ( UartGetCmdLn = 0x40003ef4 );
-PROVIDE ( UartRegReadProc = 0x4000381c );
-PROVIDE ( UartRegWriteProc = 0x400037ac );
-PROVIDE ( UartRxString = 0x40003c30 );
-PROVIDE ( Uart_Init = 0x40003a14 );
-PROVIDE ( _ResetHandler = 0x400000a4 );
-PROVIDE ( _ResetVector = 0x40000080 );
-PROVIDE ( __adddf3 = 0x4000c538 );
-PROVIDE ( __addsf3 = 0x4000c180 );
-PROVIDE ( __divdf3 = 0x4000cb94 );
-PROVIDE ( __divdi3 = 0x4000ce60 );
-PROVIDE ( __divsi3 = 0x4000dc88 );
-PROVIDE ( __extendsfdf2 = 0x4000cdfc );
-PROVIDE ( __fixdfsi = 0x4000ccb8 );
-PROVIDE ( __fixunsdfsi = 0x4000cd00 );
-PROVIDE ( __fixunssfsi = 0x4000c4c4 );
-PROVIDE ( __floatsidf = 0x4000e2f0 );
-PROVIDE ( __floatsisf = 0x4000e2ac );
-PROVIDE ( __floatunsidf = 0x4000e2e8 );
-PROVIDE ( __floatunsisf = 0x4000e2a4 );
-PROVIDE ( __muldf3 = 0x4000c8f0 );
-PROVIDE ( __muldi3 = 0x40000650 );
-PROVIDE ( __mulsf3 = 0x4000c3dc );
-PROVIDE ( __subdf3 = 0x4000c688 );
-PROVIDE ( __subsf3 = 0x4000c268 );
-PROVIDE ( __truncdfsf2 = 0x4000cd5c );
-PROVIDE ( __udivdi3 = 0x4000d310 );
-PROVIDE ( __udivsi3 = 0x4000e21c );
-PROVIDE ( __umoddi3 = 0x4000d770 );
-PROVIDE ( __umodsi3 = 0x4000e268 );
-PROVIDE ( __umulsidi3 = 0x4000dcf0 );
-PROVIDE ( _rom_store = 0x4000e388 );
-PROVIDE ( _rom_store_table = 0x4000e328 );
-PROVIDE ( _start = 0x4000042c );
-PROVIDE ( _xtos_alloca_handler = 0x4000dbe0 );
-PROVIDE ( _xtos_c_wrapper_handler = 0x40000598 );
-PROVIDE ( _xtos_cause3_handler = 0x40000590 );
-PROVIDE ( _xtos_ints_off = 0x4000bda4 );
-PROVIDE ( _xtos_ints_on = 0x4000bd84 );
-PROVIDE ( _xtos_l1int_handler = 0x4000048c );
-PROVIDE ( _xtos_p_none = 0x4000dbf8 );
-PROVIDE ( _xtos_restore_intlevel = 0x4000056c );
-PROVIDE ( _xtos_return_from_exc = 0x4000dc54 );
-PROVIDE ( _xtos_set_exception_handler = 0x40000454 );
-PROVIDE ( _xtos_set_interrupt_handler = 0x4000bd70 );
-PROVIDE ( _xtos_set_interrupt_handler_arg = 0x4000bd28 );
-PROVIDE ( _xtos_set_intlevel = 0x4000dbfc );
-PROVIDE ( _xtos_set_min_intlevel = 0x4000dc18 );
-PROVIDE ( _xtos_set_vpri = 0x40000574 );
-PROVIDE ( _xtos_syscall_handler = 0x4000dbe4 );
-PROVIDE ( _xtos_unhandled_exception = 0x4000dc44 );
-PROVIDE ( _xtos_unhandled_interrupt = 0x4000dc3c );
-PROVIDE ( aes_decrypt = 0x400092d4 );
-PROVIDE ( aes_decrypt_deinit = 0x400092e4 );
-PROVIDE ( aes_decrypt_init = 0x40008ea4 );
-PROVIDE ( aes_unwrap = 0x40009410 );
-PROVIDE ( base64_decode = 0x40009648 );
-PROVIDE ( base64_encode = 0x400094fc );
-PROVIDE ( bzero = 0x4000de84 );
-PROVIDE ( cmd_parse = 0x40000814 );
-PROVIDE ( conv_str_decimal = 0x40000b24 );
-PROVIDE ( conv_str_hex = 0x40000cb8 );
-PROVIDE ( convert_para_str = 0x40000a60 );
-PROVIDE ( dtm_get_intr_mask = 0x400026d0 );
-PROVIDE ( dtm_params_init = 0x4000269c );
-PROVIDE ( dtm_set_intr_mask = 0x400026c8 );
-PROVIDE ( dtm_set_params = 0x400026dc );
-PROVIDE ( eprintf = 0x40001d14 );
-PROVIDE ( eprintf_init_buf = 0x40001cb8 );
-PROVIDE ( eprintf_to_host = 0x40001d48 );
-PROVIDE ( est_get_printf_buf_remain_len = 0x40002494 );
-PROVIDE ( est_reset_printf_buf_len = 0x4000249c );
-PROVIDE ( ets_bzero = 0x40002ae8 );
-PROVIDE ( ets_char2xdigit = 0x40002b74 );
-PROVIDE ( ets_delay_us = 0x40002ecc );
-PROVIDE ( ets_enter_sleep = 0x400027b8 );
-PROVIDE ( ets_external_printf = 0x40002578 );
-PROVIDE ( ets_get_cpu_frequency = 0x40002f0c );
-PROVIDE ( ets_getc = 0x40002bcc );
-PROVIDE ( ets_install_external_printf = 0x40002450 );
-PROVIDE ( ets_install_putc1 = 0x4000242c );
-PROVIDE ( ets_install_putc2 = 0x4000248c );
-PROVIDE ( ets_install_uart_printf = 0x40002438 );
-/* Undocumented function to print character to UART */
-PROVIDE ( ets_uart_putc1 = 0x40001dcc );
-/* permanently hide reimplemented ets_intr_*lock(), see #6484
-PROVIDE ( ets_intr_lock = 0x40000f74 );
-PROVIDE ( ets_intr_unlock = 0x40000f80 );
-*/
-PROVIDE ( ets_isr_attach = 0x40000f88 );
-PROVIDE ( ets_isr_mask = 0x40000f98 );
-PROVIDE ( ets_isr_unmask = 0x40000fa8 );
-PROVIDE ( ets_memcmp = 0x400018d4 );
-PROVIDE ( ets_memcpy = 0x400018b4 );
-PROVIDE ( ets_memmove = 0x400018c4 );
-PROVIDE ( ets_memset = 0x400018a4 );
-/* renamed to ets_post_rom(), see #6484
-PROVIDE ( ets_post = 0x40000e24 );
-*/
-PROVIDE ( ets_post_rom = 0x40000e24 );
-PROVIDE ( ets_printf = 0x400024cc );
-PROVIDE ( ets_putc = 0x40002be8 );
-PROVIDE ( ets_rtc_int_register = 0x40002a40 );
-PROVIDE ( ets_run = 0x40000e04 );
-PROVIDE ( ets_set_idle_cb = 0x40000dc0 );
-PROVIDE ( ets_set_user_start = 0x40000fbc );
-PROVIDE ( ets_str2macaddr = 0x40002af8 );
-PROVIDE ( ets_strcmp = 0x40002aa8 );
-PROVIDE ( ets_strcpy = 0x40002a88 );
-PROVIDE ( ets_strlen = 0x40002ac8 );
-PROVIDE ( ets_strncmp = 0x40002ab8 );
-PROVIDE ( ets_strncpy = 0x40002a98 );
-PROVIDE ( ets_strstr = 0x40002ad8 );
-PROVIDE ( ets_task = 0x40000dd0 );
-PROVIDE ( ets_timer_arm = 0x40002cc4 );
-PROVIDE ( ets_timer_disarm = 0x40002d40 );
-PROVIDE ( ets_timer_done = 0x40002d80 );
-PROVIDE ( ets_timer_handler_isr = 0x40002da8 );
-PROVIDE ( ets_timer_init = 0x40002e68 );
-PROVIDE ( ets_timer_setfn = 0x40002c48 );
-PROVIDE ( ets_uart_printf = 0x40002544 );
-PROVIDE ( ets_update_cpu_frequency = 0x40002f04 );
-PROVIDE ( ets_vprintf = 0x40001f00 );
-PROVIDE ( ets_wdt_disable = 0x400030f0 );
-PROVIDE ( ets_wdt_enable = 0x40002fa0 );
-PROVIDE ( ets_wdt_get_mode = 0x40002f34 );
-PROVIDE ( ets_wdt_init = 0x40003170 );
-PROVIDE ( ets_wdt_restore = 0x40003158 );
-PROVIDE ( ets_write_char = 0x40001da0 );
-PROVIDE ( get_first_seg = 0x4000091c );
-PROVIDE ( gpio_init = 0x40004c50 );
-PROVIDE ( gpio_input_get = 0x40004cf0 );
-PROVIDE ( gpio_intr_ack = 0x40004dcc );
-PROVIDE ( gpio_intr_handler_register = 0x40004e28 );
-PROVIDE ( gpio_intr_pending = 0x40004d88 );
-PROVIDE ( gpio_intr_test = 0x40004efc );
-PROVIDE ( gpio_output_set = 0x40004cd0 );
-PROVIDE ( gpio_pin_intr_state_set = 0x40004d90 );
-PROVIDE ( gpio_pin_wakeup_disable = 0x40004ed4 );
-PROVIDE ( gpio_pin_wakeup_enable = 0x40004e90 );
-PROVIDE ( gpio_register_get = 0x40004d5c );
-PROVIDE ( gpio_register_set = 0x40004d04 );
-PROVIDE ( hmac_md5 = 0x4000a2cc );
-PROVIDE ( hmac_md5_vector = 0x4000a160 );
-PROVIDE ( hmac_sha1 = 0x4000ba28 );
-PROVIDE ( hmac_sha1_vector = 0x4000b8b4 );
-PROVIDE ( lldesc_build_chain = 0x40004f40 );
-PROVIDE ( lldesc_num2link = 0x40005050 );
-PROVIDE ( lldesc_set_owner = 0x4000507c );
-PROVIDE ( main = 0x40000fec );
-PROVIDE ( md5_vector = 0x400097ac );
-PROVIDE ( mem_calloc = 0x40001c2c );
-PROVIDE ( mem_free = 0x400019e0 );
-PROVIDE ( mem_init = 0x40001998 );
-PROVIDE ( mem_malloc = 0x40001b40 );
-PROVIDE ( mem_realloc = 0x40001c6c );
-PROVIDE ( mem_trim = 0x40001a14 );
-PROVIDE ( mem_zalloc = 0x40001c58 );
-PROVIDE ( memcmp = 0x4000dea8 );
-PROVIDE ( memcpy = 0x4000df48 );
-PROVIDE ( memmove = 0x4000e04c );
-PROVIDE ( memset = 0x4000e190 );
-PROVIDE ( multofup = 0x400031c0 );
-PROVIDE ( pbkdf2_sha1 = 0x4000b840 );
-PROVIDE ( phy_get_romfuncs = 0x40006b08 );
-PROVIDE ( rand = 0x40000600 );
-PROVIDE ( rc4_skip = 0x4000dd68 );
-PROVIDE ( recv_packet = 0x40003d08 );
-PROVIDE ( remove_head_space = 0x40000a04 );
-PROVIDE ( rijndaelKeySetupDec = 0x40008dd0 );
-PROVIDE ( rijndaelKeySetupEnc = 0x40009300 );
-PROVIDE ( rom_abs_temp = 0x400060c0 );
-PROVIDE ( rom_ana_inf_gating_en = 0x40006b10 );
-PROVIDE ( rom_cal_tos_v50 = 0x40007a28 );
-PROVIDE ( rom_chip_50_set_channel = 0x40006f84 );
-PROVIDE ( rom_chip_v5_disable_cca = 0x400060d0 );
-PROVIDE ( rom_chip_v5_enable_cca = 0x400060ec );
-PROVIDE ( rom_chip_v5_rx_init = 0x4000711c );
-PROVIDE ( rom_chip_v5_sense_backoff = 0x4000610c );
-PROVIDE ( rom_chip_v5_tx_init = 0x4000718c );
-PROVIDE ( rom_dc_iq_est = 0x4000615c );
-PROVIDE ( rom_en_pwdet = 0x400061b8 );
-PROVIDE ( rom_get_bb_atten = 0x40006238 );
-PROVIDE ( rom_get_corr_power = 0x40006260 );
-PROVIDE ( rom_get_fm_sar_dout = 0x400062dc );
-PROVIDE ( rom_get_noisefloor = 0x40006394 );
-PROVIDE ( rom_get_power_db = 0x400063b0 );
-PROVIDE ( rom_i2c_readReg = 0x40007268 );
-PROVIDE ( rom_i2c_readReg_Mask = 0x4000729c );
-PROVIDE ( rom_i2c_writeReg = 0x400072d8 );
-PROVIDE ( rom_i2c_writeReg_Mask = 0x4000730c );
-PROVIDE ( rom_iq_est_disable = 0x40006400 );
-PROVIDE ( rom_iq_est_enable = 0x40006430 );
-PROVIDE ( rom_linear_to_db = 0x40006484 );
-PROVIDE ( rom_mhz2ieee = 0x400065a4 );
-PROVIDE ( rom_pbus_dco___SA2 = 0x40007bf0 );
-PROVIDE ( rom_pbus_debugmode = 0x4000737c );
-PROVIDE ( rom_pbus_enter_debugmode = 0x40007410 );
-PROVIDE ( rom_pbus_exit_debugmode = 0x40007448 );
-PROVIDE ( rom_pbus_force_test = 0x4000747c );
-PROVIDE ( rom_pbus_rd = 0x400074d8 );
-PROVIDE ( rom_pbus_set_rxgain = 0x4000754c );
-PROVIDE ( rom_pbus_set_txgain = 0x40007610 );
-PROVIDE ( rom_pbus_workmode = 0x40007648 );
-PROVIDE ( rom_pbus_xpd_rx_off = 0x40007688 );
-PROVIDE ( rom_pbus_xpd_rx_on = 0x400076cc );
-PROVIDE ( rom_pbus_xpd_tx_off = 0x400076fc );
-PROVIDE ( rom_pbus_xpd_tx_on = 0x40007740 );
-PROVIDE ( rom_pbus_xpd_tx_on__low_gain = 0x400077a0 );
-PROVIDE ( rom_phy_reset_req = 0x40007804 );
-PROVIDE ( rom_restart_cal = 0x4000781c );
-PROVIDE ( rom_rfcal_pwrctrl = 0x40007eb4 );
-PROVIDE ( rom_rfcal_rxiq = 0x4000804c );
-PROVIDE ( rom_rfcal_rxiq_set_reg = 0x40008264 );
-PROVIDE ( rom_rfcal_txcap = 0x40008388 );
-PROVIDE ( rom_rfcal_txiq = 0x40008610 );
-PROVIDE ( rom_rfcal_txiq_cover = 0x400088b8 );
-PROVIDE ( rom_rfcal_txiq_set_reg = 0x40008a70 );
-PROVIDE ( rom_rfpll_reset = 0x40007868 );
-PROVIDE ( rom_rfpll_set_freq = 0x40007968 );
-PROVIDE ( rom_rxiq_cover_mg_mp = 0x40008b6c );
-PROVIDE ( rom_rxiq_get_mis = 0x40006628 );
-PROVIDE ( rom_sar_init = 0x40006738 );
-PROVIDE ( rom_set_ana_inf_tx_scale = 0x4000678c );
-PROVIDE ( rom_set_channel_freq = 0x40006c50 );
-PROVIDE ( rom_set_loopback_gain = 0x400067c8 );
-PROVIDE ( rom_set_noise_floor = 0x40006830 );
-PROVIDE ( rom_set_rxclk_en = 0x40006550 );
-PROVIDE ( rom_set_txbb_atten = 0x40008c6c );
-PROVIDE ( rom_set_txclk_en = 0x4000650c );
-PROVIDE ( rom_set_txiq_cal = 0x40008d34 );
-PROVIDE ( rom_start_noisefloor = 0x40006874 );
-PROVIDE ( rom_start_tx_tone = 0x400068b4 );
-PROVIDE ( rom_stop_tx_tone = 0x4000698c );
-PROVIDE ( rom_tx_mac_disable = 0x40006a98 );
-PROVIDE ( rom_tx_mac_enable = 0x40006ad4 );
-PROVIDE ( rom_txtone_linear_pwr = 0x40006a1c );
-PROVIDE ( rom_write_rfpll_sdm = 0x400078dc );
-PROVIDE ( roundup2 = 0x400031b4 );
-PROVIDE ( rtc_enter_sleep = 0x40002870 );
-PROVIDE ( rtc_get_reset_reason = 0x400025e0 );
-PROVIDE ( rtc_intr_handler = 0x400029ec );
-PROVIDE ( rtc_set_sleep_mode = 0x40002668 );
-PROVIDE ( save_rxbcn_mactime = 0x400027a4 );
-PROVIDE ( save_tsf_us = 0x400027ac );
-PROVIDE ( send_packet = 0x40003c80 );
-PROVIDE ( sha1_prf = 0x4000ba48 );
-PROVIDE ( sha1_vector = 0x4000a2ec );
-PROVIDE ( sip_alloc_to_host_evt = 0x40005180 );
-PROVIDE ( sip_get_ptr = 0x400058a8 );
-PROVIDE ( sip_get_state = 0x40005668 );
-PROVIDE ( sip_init_attach = 0x4000567c );
-PROVIDE ( sip_install_rx_ctrl_cb = 0x4000544c );
-PROVIDE ( sip_install_rx_data_cb = 0x4000545c );
-PROVIDE ( sip_post = 0x400050fc );
-PROVIDE ( sip_post_init = 0x400056c4 );
-PROVIDE ( sip_reclaim_from_host_cmd = 0x4000534c );
-PROVIDE ( sip_reclaim_tx_data_pkt = 0x400052c0 );
-PROVIDE ( sip_send = 0x40005808 );
-PROVIDE ( sip_to_host_chain_append = 0x40005864 );
-PROVIDE ( sip_to_host_evt_send_done = 0x40005234 );
-PROVIDE ( slc_add_credits = 0x400060ac );
-PROVIDE ( slc_enable = 0x40005d90 );
-PROVIDE ( slc_from_host_chain_fetch = 0x40005f24 );
-PROVIDE ( slc_from_host_chain_recycle = 0x40005e94 );
-PROVIDE ( slc_init_attach = 0x40005c50 );
-PROVIDE ( slc_init_credit = 0x4000608c );
-PROVIDE ( slc_pause_from_host = 0x40006014 );
-PROVIDE ( slc_reattach = 0x40005c1c );
-PROVIDE ( slc_resume_from_host = 0x4000603c );
-PROVIDE ( slc_select_tohost_gpio = 0x40005dc0 );
-PROVIDE ( slc_select_tohost_gpio_mode = 0x40005db8 );
-PROVIDE ( slc_send_to_host_chain = 0x40005de4 );
-PROVIDE ( slc_set_host_io_max_window = 0x40006068 );
-PROVIDE ( slc_to_host_chain_recycle = 0x40005f10 );
-PROVIDE ( software_reset = 0x4000264c );
-PROVIDE ( spi_flash_attach = 0x40004644 );
-PROVIDE ( srand = 0x400005f0 );
-PROVIDE ( strcmp = 0x4000bdc8 );
-PROVIDE ( strcpy = 0x4000bec8 );
-PROVIDE ( strlen = 0x4000bf4c );
-PROVIDE ( strncmp = 0x4000bfa8 );
-PROVIDE ( strncpy = 0x4000c0a0 );
-PROVIDE ( strstr = 0x4000e1e0 );
-PROVIDE ( timer_insert = 0x40002c64 );
-PROVIDE ( uartAttach = 0x4000383c );
-PROVIDE ( uart_baudrate_detect = 0x40003924 );
-PROVIDE ( uart_buff_switch = 0x400038a4 );
-PROVIDE ( uart_rx_intr_handler = 0x40003bbc );
-PROVIDE ( uart_rx_one_char = 0x40003b8c );
-PROVIDE ( uart_rx_one_char_block = 0x40003b64 );
-PROVIDE ( uart_rx_readbuff = 0x40003ec8 );
-PROVIDE ( uart_tx_one_char = 0x40003b30 );
-PROVIDE ( wepkey_128 = 0x4000bc40 );
-PROVIDE ( wepkey_64 = 0x4000bb3c );
-PROVIDE ( xthal_bcopy = 0x40000688 );
-PROVIDE ( xthal_copy123 = 0x4000074c );
-PROVIDE ( xthal_get_ccompare = 0x4000dd4c );
-PROVIDE ( xthal_get_ccount = 0x4000dd38 );
-PROVIDE ( xthal_get_interrupt = 0x4000dd58 );
-PROVIDE ( xthal_get_intread = 0x4000dd58 );
-PROVIDE ( xthal_memcpy = 0x400006c4 );
-PROVIDE ( xthal_set_ccompare = 0x4000dd40 );
-PROVIDE ( xthal_set_intclear = 0x4000dd60 );
-PROVIDE ( xthal_spill_registers_into_stack_nw = 0x4000e320 );
-PROVIDE ( xthal_window_spill = 0x4000e324 );
-PROVIDE ( xthal_window_spill_nw = 0x4000e320 );
-
-PROVIDE ( Te0 = 0x3fffccf0 );
-PROVIDE ( Td0 = 0x3fffd100 );
-PROVIDE ( Td4s = 0x3fffd500);
-PROVIDE ( rcons = 0x3fffd0f0);
-PROVIDE ( UartDev = 0x3fffde10 );
-PROVIDE ( flashchip = 0x3fffc714);
diff --git a/tasmota/settings.h b/tasmota/settings.h
index 44c2e061a..54958754c 100644
--- a/tasmota/settings.h
+++ b/tasmota/settings.h
@@ -110,7 +110,7 @@ typedef union { // Restricted by MISRA-C Rule 18.4 bu
uint32_t remote_device_mode : 1; // bit 6 (v8.1.0.9) - SetOption88 - PWM Dimmer Buttons control remote devices
uint32_t zigbee_distinct_topics : 1; // bit 7 (v8.1.0.10) - SetOption89 - Distinct MQTT topics per device for Zigbee (#7835)
uint32_t only_json_message : 1; // bit 8 (v8.2.0.3) - SetOption90 - Disable non-json MQTT response
- uint32_t spare09 : 1;
+ uint32_t fade_at_startup : 1; // bit 9 (v8.2.0.3) - SetOption91 - Enable light fading at start/power on
uint32_t spare10 : 1;
uint32_t spare11 : 1;
uint32_t spare12 : 1;
diff --git a/tasmota/support_command.ino b/tasmota/support_command.ino
index 64fd45997..9898b5044 100644
--- a/tasmota/support_command.ino
+++ b/tasmota/support_command.ino
@@ -32,7 +32,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
#endif
#ifdef USE_DEVICE_GROUPS
- D_CMND_DEVGROUP_SHARE "|"
+ D_CMND_DEVGROUP_NAME "|" D_CMND_DEVGROUP_SHARE "|"
#endif // USE_DEVICE_GROUPS
D_CMND_SENSOR "|" D_CMND_DRIVER;
@@ -51,7 +51,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndI2cScan, CmndI2cDriver,
#endif
#ifdef USE_DEVICE_GROUPS
- &CmndDevGroupShare,
+ &CmndDevGroupName, &CmndDevGroupShare,
#endif // USE_DEVICE_GROUPS
&CmndSensor, &CmndDriver };
@@ -1707,6 +1707,21 @@ void CmndI2cDriver(void)
#endif // USE_I2C
#ifdef USE_DEVICE_GROUPS
+void CmndDevGroupName(void)
+{
+ if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DEV_GROUP_NAMES)) {
+ if (XdrvMailbox.data_len > 0) {
+ if (XdrvMailbox.data_len > TOPSZ)
+ XdrvMailbox.data[TOPSZ - 1] = 0;
+ else if (1 == XdrvMailbox.data_len && ('"' == XdrvMailbox.data[0] || '0' == XdrvMailbox.data[0]))
+ XdrvMailbox.data[0] = 0;
+ SettingsUpdateText(SET_DEV_GROUP_NAME1 + XdrvMailbox.index - 1, XdrvMailbox.data);
+ restart_flag = 2;
+ }
+ ResponseCmndAll(SET_DEV_GROUP_NAME1, MAX_DEV_GROUP_NAMES);
+ }
+}
+
void CmndDevGroupShare(void)
{
uint32_t parm[2] = { Settings.device_group_share_in, Settings.device_group_share_out };
diff --git a/tasmota/support_device_groups.ino b/tasmota/support_device_groups.ino
index 4e8b48041..fd9c03be9 100644
--- a/tasmota/support_device_groups.ino
+++ b/tasmota/support_device_groups.ino
@@ -62,7 +62,7 @@ bool udp_was_connected = false;
void DeviceGroupsInit(void)
{
- // Initialize the device information for each device group. The group name is the MQTT group topic.
+ // Initialize the device information for each device group.
device_groups = (struct device_group *)calloc(device_group_count, sizeof(struct device_group));
if (device_groups == nullptr) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error allocating %u-element device group array"), device_group_count);
@@ -72,7 +72,18 @@ void DeviceGroupsInit(void)
for (uint32_t device_group_index = 0; device_group_index < device_group_count; device_group_index++) {
struct device_group * device_group = &device_groups[device_group_index];
- strcpy(device_group->group_name, SettingsText((device_group_index == 0 ? SET_MQTT_GRP_TOPIC : SET_MQTT_GRP_TOPIC2 + device_group_index - 1)));
+ strcpy(device_group->group_name, SettingsText(SET_DEV_GROUP_NAME1 + device_group_index));
+
+ // If the device group name is not set, use the MQTT group topic (with the device group index +
+ // 1 appended for device group indices > 0).
+ if (!device_group->group_name[0]) {
+ strcpy(device_group->group_name, SettingsText(SET_MQTT_GRP_TOPIC));
+ if (device_group_index) {
+ char str[10];
+ sprintf_P(str, PSTR("%u"), device_group_index + 1);
+ strcat(device_group->group_name, str);
+ }
+ }
device_group->message_header_length = sprintf_P(device_group->message, PSTR("%s%s HTTP/1.1\n\n"), kDeviceGroupMessage, device_group->group_name);
device_group->last_full_status_sequence = -1;
}
@@ -106,7 +117,7 @@ char * BeginDeviceGroupMessage(struct device_group * device_group, uint16_t flag
}
// Return true if we're configured to share the specified item.
-bool DeviceGroupItemShared(bool incoming, uint8_t item)
+bool DevGroupItemShared(bool incoming, uint8_t item)
{
uint8_t mask = 0;
switch (item) {
@@ -149,7 +160,7 @@ void SendDeviceGroupPacket(IPAddress ip, char * packet, int len, const char * la
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DGR: error sending %s packet"), label);
}
-void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType message_type, ...)
+void _SendDeviceGroupMessage(uint8_t device_group_index, DevGroupMessageType message_type, ...)
{
// If device groups are not enabled, ignore this request.
if (!Settings.flag4.device_groups_enabled) return;
@@ -184,6 +195,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
device_group->message_length = 0;
SendDeviceGroupMessage(device_group_index, DGR_MSGTYP_PARTIAL_UPDATE, DGR_ITEM_POWER, power);
XdrvMailbox.command_code = DGR_ITEM_STATUS;
+ XdrvMailbox.topic = (char *)&device_group_index;
XdrvCall(FUNC_DEVICE_GROUP_ITEM);
building_status_message = false;
@@ -319,7 +331,7 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
// Itertate through the passed items adding them and their values to the message.
va_start(ap, message_type);
while ((item = va_arg(ap, int))) {
- shared = DeviceGroupItemShared(false, item);
+ shared = DevGroupItemShared(false, item);
if (shared) *message_ptr++ = item;
if (item <= DGR_ITEM_MAX_32BIT) {
value = va_arg(ap, int);
@@ -384,10 +396,8 @@ void _SendDeviceGroupMessage(uint8_t device_group_index, DeviceGroupMessageType
uint32_t now = millis();
if (message_type == DGR_MSGTYP_UPDATE_MORE_TO_COME) {
+ device_group->message_length = 0;
device_group->next_ack_check_time = 0;
-// for (struct device_group_member * device_group_member = device_group->device_group_members; device_group_member != nullptr; device_group_member = device_group_member->flink) {
-// device_group_member->acked_sequence = outgoing_sequence;
-// }
}
else {
device_group->ack_check_interval = 100;
@@ -410,7 +420,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
// Search for a device group with the target group name. If one isn't found, return.
struct device_group * device_group;
- uint32_t device_group_index = 0;
+ uint8_t device_group_index = 0;
for (;;) {
device_group = &device_groups[device_group_index];
if (!strcmp(message_group_name, device_group->group_name)) break;
@@ -518,15 +528,16 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
bool grpflg
bool usridx
uint16_t command_code Item code
- uint32_t index 0:15 Flags, 16:23 Device group index
+ uint32_t index 0:15 Flags, 16:31 Message sequence
uint32_t data_len String item value length
int32_t payload Integer item value
- char *topic
+ char *topic Pointer to device group index
char *data Pointer to non-integer item value
char *command nullptr
*/
XdrvMailbox.command = nullptr; // Indicates the source is a device group update
- XdrvMailbox.index = flags | device_group_index << 16;
+ XdrvMailbox.index = flags | message_sequence << 16;
+ XdrvMailbox.topic = (char *)&device_group_index;
if (flags & (DGR_FLAG_MORE_TO_COME | DGR_FLAG_DIRECT)) skip_light_fade = true;
for (;;) {
@@ -589,7 +600,7 @@ void ProcessDeviceGroupMessage(char * packet, int packet_length)
}
}
- if (DeviceGroupItemShared(true, item)) {
+ if (DevGroupItemShared(true, item)) {
if (item == DGR_ITEM_POWER) {
if (device_group->local) {
uint8_t mask_devices = value >> 24;
@@ -744,7 +755,7 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
if (device_group->next_ack_check_time < next_check_time) next_check_time = device_group->next_ack_check_time;
}
- // If it's time to send multicast announcement for this group, send it. This is to
+ // If it's time to send a multicast announcement for this group, send it. This is to
// announcement ourself to any members that have somehow not heard about us. We send it at
// the announcement interval plus a random number of milliseconds so that even if all the
// devices booted at the same time, they don't all multicast their announcements at the same
@@ -753,11 +764,10 @@ AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: Ckecking next_check_time=%u, now=%u"), nex
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: next_announcement_time=%u, now=%u"), device_group->next_announcement_time, now);
#endif // DEVICE_GROUPS_DEBUG
if (device_group->next_announcement_time <= now) {
- device_group->message_length = BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT) - device_group->message;
#ifdef DEVICE_GROUPS_DEBUG
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("DGR: sending %u-byte device group %s announcement"), device_group->message_length, device_group->group_name);
#endif // DEVICE_GROUPS_DEBUG
- SendDeviceGroupPacket(0, device_group->message, device_group->message_length, PSTR("Announcement"));
+ SendDeviceGroupPacket(0, device_group->message, BeginDeviceGroupMessage(device_group, DGR_FLAG_ANNOUNCEMENT, true) - device_group->message, PSTR("Announcement"));
device_group->next_announcement_time = now + DGR_ANNOUNCEMENT_INTERVAL + random(10000);
}
if (device_group->next_announcement_time < next_check_time) next_check_time = device_group->next_announcement_time;
diff --git a/tasmota/tasmota.h b/tasmota/tasmota.h
index 48a853891..431a116ec 100644
--- a/tasmota/tasmota.h
+++ b/tasmota/tasmota.h
@@ -82,6 +82,7 @@ const uint8_t MAX_RULE_MEMS = 16; // Max number of saved vars
const uint8_t MAX_FRIENDLYNAMES = 8; // Max number of Friendly names
const uint8_t MAX_BUTTON_TEXT = 16; // Max number of GUI button labels
const uint8_t MAX_GROUP_TOPICS = 4; // Max number of Group Topics
+const uint8_t MAX_DEV_GROUP_NAMES = 4; // Max number of Device Group names
const uint8_t MAX_HUE_DEVICES = 15; // Max number of Philips Hue device per emulation
@@ -302,30 +303,30 @@ enum SettingsTextIndex { SET_OTAURL,
SET_BUTTON1, SET_BUTTON2, SET_BUTTON3, SET_BUTTON4, SET_BUTTON5, SET_BUTTON6, SET_BUTTON7, SET_BUTTON8,
SET_BUTTON9, SET_BUTTON10, SET_BUTTON11, SET_BUTTON12, SET_BUTTON13, SET_BUTTON14, SET_BUTTON15, SET_BUTTON16,
SET_MQTT_GRP_TOPIC2, SET_MQTT_GRP_TOPIC3, SET_MQTT_GRP_TOPIC4,
- SET_TEMPLATE_NAME,
+ SET_TEMPLATE_NAME, SET_DEV_GROUP_NAME1, SET_DEV_GROUP_NAME2, SET_DEV_GROUP_NAME3, SET_DEV_GROUP_NAME4,
SET_MAX };
-enum DeviceGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYP_REUPDATE };
+enum DevGroupMessageType { DGR_MSGTYP_FULL_STATUS, DGR_MSGTYP_PARTIAL_UPDATE, DGR_MSGTYP_UPDATE, DGR_MSGTYP_UPDATE_MORE_TO_COME, DGR_MSGTYP_UPDATE_DIRECT, DGR_MSGTYP_REUPDATE };
-enum DeviceGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32, DGR_FLAG_ANNOUNCEMENT = 64 };
+enum DevGroupMessageFlag { DGR_FLAG_RESET = 1, DGR_FLAG_STATUS_REQUEST = 2, DGR_FLAG_FULL_STATUS = 4, DGR_FLAG_ACK = 8, DGR_FLAG_MORE_TO_COME = 16, DGR_FLAG_DIRECT = 32, DGR_FLAG_ANNOUNCEMENT = 64 };
-enum DeviceGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS,
- DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR,
- DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON,
- // Add new 8-bit items before this line
- DGR_ITEM_LAST_8BIT, DGR_ITEM_MAX_8BIT = 63,
- DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5,
- // Add new 16-bit items before this line
- DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127,
- DGR_ITEM_POWER, DGR_ITEM_DIMMER_RANGE,
- // Add new 32-bit items before this line
- DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191,
- // Add new string items before this line
- DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223,
- DGR_ITEM_LIGHT_CHANNELS };
+enum DevGroupItem { DGR_ITEM_EOL, DGR_ITEM_STATUS,
+ DGR_ITEM_LIGHT_FADE, DGR_ITEM_LIGHT_SPEED, DGR_ITEM_LIGHT_BRI, DGR_ITEM_LIGHT_SCHEME, DGR_ITEM_LIGHT_FIXED_COLOR,
+ DGR_ITEM_BRI_PRESET_LOW, DGR_ITEM_BRI_PRESET_HIGH, DGR_ITEM_BRI_POWER_ON,
+ // Add new 8-bit items before this line
+ DGR_ITEM_LAST_8BIT, DGR_ITEM_MAX_8BIT = 63,
+ DGR_ITEM_ANALOG1, DGR_ITEM_ANALOG2, DGR_ITEM_ANALOG3, DGR_ITEM_ANALOG4, DGR_ITEM_ANALOG5,
+ // Add new 16-bit items before this line
+ DGR_ITEM_LAST_16BIT, DGR_ITEM_MAX_16BIT = 127,
+ DGR_ITEM_POWER, DGR_ITEM_DIMMER_RANGE,
+ // Add new 32-bit items before this line
+ DGR_ITEM_LAST_32BIT, DGR_ITEM_MAX_32BIT = 191,
+ // Add new string items before this line
+ DGR_ITEM_LAST_STRING, DGR_ITEM_MAX_STRING = 223,
+ DGR_ITEM_LIGHT_CHANNELS };
-enum DeviceGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8,
- DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_SETTINGS = 32 };
+enum DevGroupShareItem { DGR_SHARE_POWER = 1, DGR_SHARE_LIGHT_BRI = 2, DGR_SHARE_LIGHT_FADE = 4, DGR_SHARE_LIGHT_SCHEME = 8,
+ DGR_SHARE_LIGHT_COLOR = 16, DGR_SHARE_DIMMER_SETTINGS = 32 };
enum CommandSource { SRC_IGNORE, SRC_MQTT, SRC_RESTART, SRC_BUTTON, SRC_SWITCH, SRC_BACKLOG, SRC_SERIAL, SRC_WEBGUI, SRC_WEBCOMMAND, SRC_WEBCONSOLE, SRC_PULSETIMER,
SRC_TIMER, SRC_RULE, SRC_MAXPOWER, SRC_MAXENERGY, SRC_OVERTEMP, SRC_LIGHT, SRC_KNX, SRC_DISPLAY, SRC_WEMO, SRC_HUE, SRC_RETRY, SRC_REMOTE, SRC_SHUTTER,
diff --git a/tasmota/xdrv_04_light.ino b/tasmota/xdrv_04_light.ino
index f5cb2e84a..9b83a6879 100644
--- a/tasmota/xdrv_04_light.ino
+++ b/tasmota/xdrv_04_light.ino
@@ -1310,6 +1310,9 @@ void LightInit(void)
Light.power = 0;
Light.update = true;
Light.wakeup_active = 0;
+ if (Settings.flag4.fade_at_startup) {
+ Light.fade_initialized = true; // consider fade intialized starting from black
+ }
LightUpdateColorMapping();
}
@@ -2128,14 +2131,14 @@ void LightSendDeviceGroupStatus(bool force)
}
}
-void LightHandleDeviceGroupItem(void)
+void LightHandleDevGroupItem(void)
{
static bool send_state = false;
static bool restore_power = false;
bool more_to_come;
uint32_t value = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER_REMOTE
- if (XdrvMailbox.index & 0xff0000) return; // Ignore updates from other device groups
+ if (*XdrvMailbox.topic) return; // Ignore updates from other device groups
#endif // USE_PWM_DIMMER_REMOTE
switch (XdrvMailbox.command_code) {
case DGR_ITEM_EOL:
@@ -2771,7 +2774,7 @@ bool Xdrv04(uint8_t function)
break;
#ifdef USE_DEVICE_GROUPS
case FUNC_DEVICE_GROUP_ITEM:
- LightHandleDeviceGroupItem();
+ LightHandleDevGroupItem();
break;
#endif // USE_DEVICE_GROUPS
case FUNC_SET_POWER:
diff --git a/tasmota/xdrv_35_pwm_dimmer.ino b/tasmota/xdrv_35_pwm_dimmer.ino
index 0e0594a8b..24195a080 100644
--- a/tasmota/xdrv_35_pwm_dimmer.ino
+++ b/tasmota/xdrv_35_pwm_dimmer.ino
@@ -101,6 +101,7 @@ void PWMModulePreInit(void)
if (Settings.flag4.remote_device_mode) {
Settings.flag4.device_groups_enabled = true;
+ device_group_count = 0;
for (uint32_t button_index = 0; button_index < MAX_KEYS; button_index++) {
if (pin[GPIO_KEY1 + button_index] < 99) device_group_count++;
}
@@ -169,11 +170,11 @@ void PWMDimmerSetPower(void)
}
#ifdef USE_DEVICE_GROUPS
-void PWMDimmerHandleDeviceGroupItem(void)
+void PWMDimmerHandleDevGroupItem(void)
{
uint32_t value = XdrvMailbox.payload;
#ifdef USE_PWM_DIMMER_REMOTE
- uint8_t device_group_index = XdrvMailbox.index >> 16 & 0xff;
+ uint8_t device_group_index = *(uint8_t *)XdrvMailbox.topic;
bool device_is_local = device_groups[device_group_index].local;
struct remote_pwm_dimmer * remote_pwm_dimmer = &remote_pwm_dimmers[device_group_index];
#endif // USE_PWM_DIMMER_REMOTE
@@ -763,7 +764,7 @@ bool Xdrv35(uint8_t function)
#ifdef USE_DEVICE_GROUPS
case FUNC_DEVICE_GROUP_ITEM:
- PWMDimmerHandleDeviceGroupItem();
+ PWMDimmerHandleDevGroupItem();
break;
#endif // USE_DEVICE_GROUPS
diff --git a/tasmota/xsns_60_GPS.ino b/tasmota/xsns_60_GPS.ino
index b0ee69fae..69b13aedd 100644
--- a/tasmota/xsns_60_GPS.ino
+++ b/tasmota/xsns_60_GPS.ino
@@ -129,6 +129,7 @@ const char kUBXTypes[] PROGMEM = "UBX";
#define UBX_SERIAL_BUFFER_SIZE 256
#define UBX_TCP_PORT 1234
+#define NTP_MILLIS_OFFSET 50 // estimated latency in milliseconds
/********************************************************************************************\
| *globals
@@ -251,7 +252,8 @@ struct UBX_t {
uint32_t last_vAcc;
uint8_t gpsFix;
uint8_t non_empty_loops; // in case of an unintended reset of the GPS, the serial interface will get flooded with NMEA
- uint16_t log_interval; // in tenth of seconds
+ uint16_t log_interval; // in tenth of seconds
+ int32_t timeOffset; // roughly computed offset millis() - iTOW
} state;
struct {
@@ -260,6 +262,7 @@ struct UBX_t {
uint32_t send_when_new:1; // no teleinterval
uint32_t send_UI_only:1;
uint32_t runningNTP:1;
+ // uint32_t blockedNTP:1;
uint32_t forceUTCupdate:1;
uint32_t runningVPort:1;
// TODO: more to come
@@ -322,6 +325,15 @@ void UBXinitCFG(void)
DEBUG_SENSOR_LOG(PSTR("UBX: turn off NMEA"));
}
+void UBXsendCFGLine(uint8_t _line)
+{
+ if (_line>sizeof(UBLOX_INIT)/16) return;
+ for (uint32_t i = 0; i < 16; i++) {
+ UBXSerial->write( pgm_read_byte(UBLOX_INIT+i+(_line*16)) );
+ }
+ DEBUG_SENSOR_LOG(PSTR("UBX: send line %u of UBLOX_INIT"), _line);
+}
+
void UBXTriggerTele(void)
{
mqtt_data[0] = '\0';
@@ -583,6 +595,8 @@ void UBXSelectMode(uint16_t mode)
break;
case 10:
UBX.mode.runningNTP = false;
+ UBXsendCFGLine(10); //NAV-POSLLH on
+ UBXsendCFGLine(11); //NAV-STATUS on
break;
case 11:
UBX.mode.forceUTCupdate = true;
@@ -604,7 +618,6 @@ void UBXSelectMode(uint16_t mode)
break;
default:
if (mode>1000 && mode <1066) {
- // UBXSetRate(mode-1000); // min. 1001 = 0.001 Hz, but will be converted to 1/65535 anyway ~0.015 Hz, max. 2000 = 1.000 Hz
UBXSetRate(mode-1000); // set interval between measurements in seconds from 1 to 65
}
break;
@@ -629,13 +642,16 @@ bool UBXHandlePOSLLH()
UBX.rec_buffer.values.lon = UBX.Message.navPosllh.lon;
DEBUG_SENSOR_LOG(PSTR("UBX: lat/lon: %i / %i"), UBX.rec_buffer.values.lat, UBX.rec_buffer.values.lon);
DEBUG_SENSOR_LOG(PSTR("UBX: hAcc: %d"), UBX.Message.navPosllh.hAcc);
- UBX.state.last_iTOW = UBX.Message.navPosllh.iTOW;
UBX.state.last_alt = UBX.Message.navPosllh.alt;
UBX.state.last_vAcc = UBX.Message.navPosllh.vAcc;
UBX.state.last_hAcc = UBX.Message.navPosllh.hAcc;
if (UBX.mode.send_when_new) {
UBXTriggerTele();
}
+ if (UBX.mode.runningNTP){ // after receiving pos-data at least once -> go to pure NTP-mode
+ UBXsendCFGLine(7); //NAV-POSLLH off
+ UBXsendCFGLine(8); //NAV-STATUS off
+ }
return true; // new position
} else {
DEBUG_SENSOR_LOG(PSTR("UBX: no valid position data"));
@@ -657,9 +673,9 @@ void UBXHandleTIME()
{
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time: %u-%u-%u %u:%u:%u"), UBX.Message.navTime.year, UBX.Message.navTime.month ,UBX.Message.navTime.day,UBX.Message.navTime.hour,UBX.Message.navTime.min,UBX.Message.navTime.sec);
if (UBX.Message.navTime.valid.UTC == 1) {
+ UBX.state.timeOffset = millis(); // iTOW%1000 should be 0 here, when NTP-server is enabled and in "pure mode"
DEBUG_SENSOR_LOG(PSTR("UBX: UTC-Time is valid"));
- if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate) {
- AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
+ if (Rtc.user_time_entry == false || UBX.mode.forceUTCupdate || UBX.mode.runningNTP) {
TIME_T gpsTime;
gpsTime.year = UBX.Message.navTime.year - 1970;
gpsTime.month = UBX.Message.navTime.month;
@@ -667,7 +683,11 @@ void UBXHandleTIME()
gpsTime.hour = UBX.Message.navTime.hour;
gpsTime.minute = UBX.Message.navTime.min;
gpsTime.second = UBX.Message.navTime.sec;
- Rtc.utc_time = MakeTime(gpsTime);
+ UBX.rec_buffer.values.time = MakeTime(gpsTime);
+ if (UBX.mode.forceUTCupdate || Rtc.user_time_entry == false){
+ AddLog_P(LOG_LEVEL_INFO, PSTR("UBX: UTC-Time is valid, set system time"));
+ Rtc.utc_time = UBX.rec_buffer.values.time;
+ }
Rtc.user_time_entry = true;
}
}
@@ -705,7 +725,7 @@ void UBXLoop50msec(void)
}
// handle NTP-server
if(UBX.mode.runningNTP){
- timeServer.processOneRequest(Rtc.utc_time, UBX.state.last_iTOW%1000);
+ timeServer.processOneRequest(UBX.rec_buffer.values.time, UBX.state.timeOffset - NTP_MILLIS_OFFSET);
}
}
diff --git a/tasmota/xsns_61_MI_NRF24.ino b/tasmota/xsns_61_MI_NRF24.ino
index 69a99cb08..d21f9e7e1 100644
--- a/tasmota/xsns_61_MI_NRF24.ino
+++ b/tasmota/xsns_61_MI_NRF24.ino
@@ -21,6 +21,9 @@
Version yyyymmdd Action Description
--------------------------------------------------------------------------------------------
+ 0.9.5.0 20200328 integrate - add dew point, multi-page-web ui, refactoring, command interface,
+ simple beacon
+ ---
0.9.4.0 20200304 integrate - sensor types can be ignored (default for LYWSD03),
add CGD1 (Alarm clock), correct PDU-types for LYWSD02
---
@@ -67,10 +70,19 @@
#define CGG1 5
#define CGD1 6
-/* define sensors to ignore, which can improve performance
- pattern: #define IGNORE_sensorname
-*/
-#define IGNORE_LYWSD03
+#define D_CMND_NRF "NRF"
+
+const char S_JSON_NRF_COMMAND_NVALUE[] PROGMEM = "{\"" D_CMND_NRF "%s\":%d}";
+const char S_JSON_NRF_COMMAND[] PROGMEM = "{\"" D_CMND_NRF "%s\":\"%s\"}";
+const char kNRF_Commands[] PROGMEM = "Ignore|Page|Scan|Beacon|Chan";
+
+enum NRF_Commands { // commands useable in console or rules
+ CMND_NRF_IGNORE, // ignore specific sensor type (1-6)
+ CMND_NRF_PAGE, // sensor entries per web page, which will be shown alternated
+ CMND_NRF_SCAN, // simplified passive BLE adv scan
+ CMND_NRF_BEACON, // even more simplified Beacon, reports time since last sighting
+ CMND_NRF_CHAN // ignore channel 0-2 (translates to 37-39)
+ };
const uint16_t kMINRFSlaveID[6]={ 0x0098, // Flora
0x01aa, // MJ_HT_V1
@@ -103,178 +115,49 @@ const uint8_t kMINRFlsfrList_B[3] = {0x21,0x72,0x43}; // MJ_HT_V1, LYWSD03, CGx
#pragma pack(1) // important!!
-struct MJ_HT_V1Header_t {// related to the payload
- uint8_t padding[3];
- uint8_t mesSize; // 3
- uint8_t padding2;
- uint16_t uuid; // 5,6 -> 0xFE95
- uint16_t type; // 7,8 -> 0x2050 MI-TH-V1
- uint8_t padding3[2];
- uint8_t counter; // 11 - counts up with every sent record
- uint8_t serial[6]; // 12 - 17
- uint8_t mode; // 18
- uint8_t padding5;
- uint8_t effectiveDataLength;
- };
-
-struct FlowerHeader_t { // related to the payload
- uint8_t padding[4];
- uint8_t padding2;
- uint16_t uuid; // 5,6 -> 0xFE95
- uint8_t mesSize;
- uint8_t padding22;
- uint16_t uuid2; // 9,10 -> 0xFE95
- uint16_t type; // 11,12 -> 0x7120 Flowercare
- uint8_t padding3[2];
- uint8_t counter; // 15 - counts up with every sent record
- uint8_t serial[6]; // 16 - 21
- uint8_t padding4; //22
- uint8_t mode; // 23
- };
-
-union floraPacket_t { // related to the whole 32-byte-packet/buffer
- struct {
- uint16_t idWord;
- uint8_t padding;
- uint8_t serial[6];
- uint8_t padding4;
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 1
- uint16_t data;
- } T; // mode 04
- struct {
- uint16_t idWord;
- uint8_t padding;
- uint8_t serial[6];
- uint8_t padding4;
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 3
- uint32_t data:24; // it is probably a real uint24_t
- } L; // mode 07
- struct {
- uint8_t padding[3];
- uint8_t serial[6];
- uint8_t padding4;
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 1
- uint8_t data;
- } M; // mode 08
- struct {
- uint8_t padding[3];
- uint8_t serial[6];
- uint8_t padding4;
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 2
- uint16_t data;
- } F; // mode 09
-};
-
-union MJ_HT_V1Packet_t { // related to the whole 32-byte-packet/buffer
- struct {
- uint16_t idWord;
- uint8_t padding;
- uint8_t serial[6];
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 4
- uint16_t temp;
+struct mi_beacon_t{
+ uint16_t productID;
+ uint8_t counter;
+ uint8_t Mac[6];
+ uint8_t spare; // not on MJ_HT_V1 and CGG1
+ uint8_t type;
+ uint8_t ten;
+ uint8_t size;
+ union {
+ struct{ //0d
+ int16_t temp;
uint16_t hum;
- } TH; // mode 0d
- struct {
- uint8_t padding[3];
- uint8_t serial[6];
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength; // 1
- uint8_t battery;
- } B; // mode 0a
- // We do NOT need the isolated T and H packet
+ }HT;
+ uint8_t bat; //0a
+ uint16_t temp; //04
+ uint16_t hum; //06
+ uint32_t lux:24; //07
+ uint8_t moist; //08
+ uint16_t fert; //09
+ };
};
-union LYWSD02Packet_t { // related to the whole 32-byte-packet/buffer
- struct {
- uint16_t idWord;
- uint8_t padding;
- uint8_t serial[6];
- uint8_t padding4;
- uint8_t mode;
- uint8_t valueTen;
- uint8_t effectiveDataLength;
- uint16_t data;
- } TH; // mode 04 or 06
-};
-
-union CGDPacket_t { // related to the whole 32-byte-packet/buffer
- struct {
- uint8_t serial[6];
- uint16_t mode;
- int16_t temp; // -9 - 59 °C
- uint16_t hum;
- } TH; // This is no MiBeacon
+struct CGDPacket_t { // related to the whole 32-byte-packet/buffer
+ uint8_t serial[6];
+ uint16_t mode;
+ union {
+ struct {
+ int16_t temp; // -9 - 59 °C
+ uint16_t hum;
+ };
+ uint8_t bat;
+ };
};
struct bleAdvPacket_t { // for nRF24L01 max 32 bytes = 2+6+24
uint8_t pduType;
uint8_t payloadSize;
uint8_t mac[6];
- union {
- uint8_t payload[24];
- MJ_HT_V1Header_t header;
- FlowerHeader_t flowerHeader;
- struct {
- uint8_t padding[21];
- uint16_t temp;
- uint8_t hum_lb; // the high byte does not fit into the RX_buffer
- } TH; // mode 0d
- struct {
- uint8_t padding[21];
- uint16_t temp;
- } T; // mode 04
- struct {
- uint8_t padding[21];
- uint16_t hum;
- } H; // mode 06
- struct {
- uint8_t padding[21];
- uint8_t battery;
- } B; // mode 0a
- struct {
- uint8_t padding[2];
- uint8_t mode;
- uint16_t size; // 2
- uint16_t data;
- } F_T; // mode 04
- struct {
- uint8_t padding[2];
- uint8_t mode;
- uint16_t size; // 3
- uint16_t data;
- uint8_t data2; // unknown meaning, maybe it is a real uint24_t (data with data2)
- } F_L; // mode 07
- struct {
- uint8_t padding[2];
- uint8_t mode;
- uint16_t size; // 1
- uint8_t data;
- } F_M; // mode 08
- struct {
- uint8_t padding[2];
- uint8_t mode;
- uint16_t size; // 2
- uint16_t data;
- } F_F; // mode 09
- };
};
union FIFO_t{
bleAdvPacket_t bleAdv;
- floraPacket_t floraPacket;
- MJ_HT_V1Packet_t MJ_HT_V1Packet;
- LYWSD02Packet_t LYWSD02Packet;
+ mi_beacon_t miBeacon;
CGDPacket_t CGDPacket;
uint8_t raw[32];
};
@@ -287,8 +170,23 @@ struct {
uint16_t timer;
uint8_t currentChan=0;
- FIFO_t buffer;
+ uint8_t ignore = 0; //bitfield: 2^sensor type
+ uint8_t channelIgnore = 0; //bitfield: 2^channel (0=37,1=38,2=39)
+ uint8_t confirmedSensors = 0;
uint8_t packetMode; // 0 - normal BLE-advertisements, 1 - 6 "special" sensor packets
+ uint8_t perPage = 4;
+ uint8_t firstUsedPacketMode = 1;
+
+ FIFO_t buffer;
+
+ struct {
+ uint8_t mac[6];
+ uint32_t time;
+ uint32_t PDU[3];
+ bool active = false;
+ } beacon;
+ bool activeScan = false;
+ bool stopScan = false;
#ifdef DEBUG_TASMOTA_SENSOR
uint8_t streamBuffer[sizeof(buffer)]; // raw data stream bytes
@@ -315,11 +213,31 @@ struct mi_sensor_t{
};
};
+struct scan_entry_t {
+ uint8_t mac[6];
+ uint16_t cid;
+ uint16_t svc;
+ uint16_t uuid;
+ uint8_t showedUp;
+};
+
std::vector MIBLEsensors;
+std::vector MINRFscanResult;
+
+static union{
+ scan_entry_t MINRFdummyEntry;
+ uint8_t MINRFtempBuf[23];
+};
/********************************************************************************************/
-
+/**
+ * @brief
+ *
+ * @param _mode Packet mode 0-6
+ * @return true If no error occured
+ * @return false If NRF24L01 is not connected
+ */
bool MINRFinitBLE(uint8_t _mode)
{
if (MINRF.timer%1000 == 0){ // only re-init every 20 seconds
@@ -344,11 +262,20 @@ bool MINRFinitBLE(uint8_t _mode)
return false;
}
+/**
+ * @brief cycle through the channels 37-39, skip ignored channel
+ *
+ */
void MINRFhopChannel()
{
- MINRF.currentChan++;
- if(MINRF.currentChan >= sizeof(MINRF.channel)) {
- MINRF.currentChan = 0;
+ for (uint32_t i = 0; i<3;i++){
+ MINRF.currentChan++;
+ if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue;
+ if(MINRF.currentChan >= sizeof(MINRF.channel)) {
+ MINRF.currentChan = 0;
+ if(bitRead(MINRF.channelIgnore,MINRF.currentChan)) continue;
+ }
+ break;
}
NRF24radio.setChannel( MINRF.frequency[MINRF.currentChan] );
}
@@ -371,7 +298,7 @@ bool MINRFreceivePacket(void)
#ifdef DEBUG_TASMOTA_SENSOR
memcpy(&MINRF.streamBuffer, &MINRF.buffer, sizeof(MINRF.buffer));
#endif // DEBUG_TASMOTA_SENSOR
- MINRFswapbuf( sizeof(MINRF.buffer) );
+ MINRFswapbuf((uint8_t*)&MINRF.buffer, sizeof(MINRF.buffer) );
// MINRF_LOG_BUFFER();
// AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: _lsfrlist: %x, chan: %u, mode: %u"),_lsfrlist[MINRF.currentChan],MINRF.currentChan, MINRF.packetMode);
@@ -427,9 +354,9 @@ void MINRFshowBuffer(uint8_t (&buf)[32]){ // we use this only for the 32-byte-FI
*
* @param len Buffer lenght (could be hardcoded to 32)
*/
-void MINRFswapbuf(uint8_t len)
+void MINRFswapbuf(uint8_t *buf, uint8_t len)
{
- uint8_t* buf = (uint8_t*)&MINRF.buffer;
+ // uint8_t* buf = (uint8_t*)&MINRF.buffer;
while(len--) {
uint8_t a = *buf;
uint8_t v = 0;
@@ -471,6 +398,181 @@ void MINRFwhiten(uint8_t *buf, uint8_t len, uint8_t lfsr)
}
}
+/*********************************************************************************************\
+ * Beacon functions
+\*********************************************************************************************/
+bool MINRFhandleBeacon(scan_entry_t * entry, uint32_t offset);
+
+/**
+ * @brief handle a generic BLE-packet in the scan process
+ *
+ */
+void MINRFhandleScan(void){
+ if(MINRFscanResult.size()>20 || MINRF.stopScan) {
+ MINRF.activeScan=false;
+ MINRFcomputefirstUsedPacketMode();
+ uint32_t i = 0; // pass counter as reference to lambda
+ MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(),
+ MINRFscanResult.end(),
+ [&i](scan_entry_t e) {
+ if(e.showedUp>2) AddLog_P2(LOG_LEVEL_INFO,PSTR("MINRF: Beacon %02u: %02X%02X%02X%02X%02X%02X Cid: %04X Svc: %04X UUID: %04X"),i,e.mac[0],e.mac[1],e.mac[2],e.mac[3],e.mac[4],e.mac[5],e.cid,e.svc,e.uuid);
+ i++;
+ return ((e.showedUp < 3));
+ }),
+ MINRFscanResult.end());
+ MINRF.stopScan=false;
+ return;
+ }
+
+ MINRFreverseMAC(MINRF.buffer.bleAdv.mac);
+ for(uint32_t i=0; iregular BLE-ADV, 6->"cutted" BLE-ADV with MAC as PDU
+ * @return true - when name, cid, uuid or svc is found with any value
+ * @return false - name, cid, uuid and svc are not found
+ */
+bool MINRFhandleBeacon(scan_entry_t * entry, uint32_t offset){
+ bool success = false;
+ uint8_t _buf[32+offset];
+ MINRFwhiten((uint8_t *)&MINRF.buffer, sizeof(MINRF.buffer), MINRF.channel[MINRF.currentChan] | 0x40);
+ MINRFswapbuf((uint8_t*)&MINRF.buffer,sizeof(MINRF.buffer));
+ memcpy((uint8_t*)&_buf+offset,MINRF.buffer.raw,32);
+ MINRFswapbuf((uint8_t*)&_buf,sizeof(_buf));
+ MINRFwhiten((uint8_t *)&_buf, sizeof(_buf), MINRF.channel[MINRF.currentChan] | 0x40);
+ if (offset == 6) MINRFreverseMAC((uint8_t*)&_buf[2]);
+
+ if(memcmp((uint8_t*)&_buf[2],MINRF.beacon.mac,2)==0){ // always at least 2 undestroyed bytes left
+ if(_buf[8]!=2 && _buf[9]!=1){
+ DEBUG_SENSOR_LOG(PSTR("MINRF: unsupported ADV %02x %02x"), _buf[8],_buf[9]);
+ return success;
+ }
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Beacon:____________"));
+ for (uint32_t i = 8; i<32+offset;i++){
+ uint32_t size = _buf[i];
+ if (size>30) break;
+ uint32_t ADtype = _buf[i+1];
+ // AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Size: %u AD: %x i:%u"), size, ADtype,i);
+ if (size+i>32+offset) size=32-i+offset-2;
+ if (size>30) break;
+ char _stemp[(size*2)];
+ uint32_t backupSize;
+ switch(ADtype){
+ case 0x01:
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Flags: %02x"), _buf[i+2]);
+ break;
+ case 0x02: case 0x03:
+ entry->uuid = _buf[i+3]*256 + _buf[i+2];
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: UUID: %04x"), entry->uuid);
+ success = true;
+ break;
+ case 0x08: case 0x09:
+ backupSize = _buf[i+size+1];
+ _buf[i+size+1] = 0;
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Name: %s"), (char*)&_buf[i+2]);
+ success = true;
+ _buf[i+size+1] = backupSize;
+ break;
+ case 0x0a:
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: TxPow: %02u"), _buf[i+2]);
+ break;
+ case 0xff:
+ entry->cid = _buf[i+3]*256 + _buf[i+2];
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Cid: %04x"), entry->cid);
+ ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2));
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp);
+ success = true;
+ break;
+ case 0x16:
+ entry->svc = _buf[i+3]*256 + _buf[i+2];
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("MINRF: Svc: %04x"), entry->svc);
+ ToHex_P((unsigned char*)&_buf+i+4,size-3,_stemp,(size*2));
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp);
+ success = true;
+ break;
+ default:
+ ToHex_P((unsigned char*)&_buf+i+2,size-1,_stemp,(size*2));
+ AddLog_P2(LOG_LEVEL_DEBUG,PSTR("%s"),_stemp);
+ }
+ i+=size;
+ }
+ MINRF.beacon.time = 0;
+ }
+ return success;
+}
+
+/**
+ * @brief increase beacon timer every second and process the result
+ *
+ */
+void MINRFbeaconCounter(void){
+ if(MINRF.beacon.active) {
+ MINRF.beacon.time++;
+ char stemp[20];
+ snprintf_P(stemp, sizeof(stemp),PSTR("{%s:{\"Beacon\": %u}}"),D_CMND_NRF, MINRF.beacon.time);
+ AddLog_P2(LOG_LEVEL_DEBUG, stemp);
+ RulesProcessEvent(stemp);
+ }
+}
+
+/**
+ * @brief compute "PDU" from MAC for each possible channel and store it globally
+ *
+ */
+void MINRFcomputeBeaconPDU(void){
+ for (uint32_t i = 0; i<3; i++){
+ bleAdvPacket_t packet;
+ memcpy((uint8_t *)&packet.mac, (uint8_t *)&MINRF.beacon.mac, sizeof(packet.mac));
+ MINRFreverseMAC(packet.mac);
+ MINRFwhiten((uint8_t *)&packet, sizeof(packet), MINRF.channel[i] | 0x40);
+ MINRFswapbuf((uint8_t*)&packet,sizeof(packet));
+ uint32_t pdu = packet.mac[0]<<24 | packet.mac[1]<<16 | packet.mac[2]<<8 | packet.mac[3];
+ MINRF.beacon.PDU[i] = pdu;
+ }
+}
+
+/*********************************************************************************************\
+ * helper functions
+\*********************************************************************************************/
+
+/**
+ * @brief reverse 6-byte-array, hard-coded size of 6
+ *
+ * @param _mac pass an uint_t[6]
+ */
void MINRFreverseMAC(uint8_t _mac[]){
uint8_t _reversedMAC[6];
for (uint8_t i=0; i<6; i++){
@@ -479,6 +581,42 @@ void MINRFreverseMAC(uint8_t _mac[]){
memcpy(_mac,_reversedMAC, sizeof(_reversedMAC));
}
+/**
+ * @brief
+ *
+ * @param _string input string in format: AABBCCDDEEFF (upper case!)
+ * @param _mac target byte array with fixed size of 6
+ */
+void MINRFMACStringToBytes(char* _string, uint8_t _mac[]) { //uppercase
+ uint32_t index = 0;
+ while (index < 12) {
+ char c = _string[index];
+ uint8_t value = 0;
+ if(c >= '0' && c <= '9')
+ value = (c - '0');
+ else if (c >= 'A' && c <= 'F')
+ value = (10 + (c - 'A'));
+ _mac[(index/2)] += value << (((index + 1) % 2) * 4);
+ index++;
+ }
+ // DEBUG_SENSOR_LOG(PSTR("MINRF: %s to MAC-array: %02X%02X%02X%02X%02X%02X"),_string,_mac[0],_mac[1],_mac[2],_mac[3],_mac[4],_mac[5]);
+}
+
+/**
+ * @brief helper function, to avoid to start with an ignored sensor type
+ *
+ */
+void MINRFcomputefirstUsedPacketMode(void){
+ for (uint32_t i = 0; iCGD1) MINRF.firstUsedPacketMode=0;
+ break;
+ }
+ }
+}
+
/**
* @brief Set packet mode and fitting PDU-type of the NRF24L01
*
@@ -502,7 +640,6 @@ void MINRFchangePacketModeTo(uint8_t _mode) {
NRF24radio.openReadingPipe(0,kMINRFL2PDU[_nextchannel]);// 95 fe 70 20 -> LYWSD02
break;
case 4: // special LYWSD03 packet
- if(kMINRFL3PDU[_nextchannel]==0xffffffff) break;
NRF24radio.openReadingPipe(0,kMINRFL3PDU[_nextchannel]);// 95 fe 58 30 -> LYWSD03 (= no data message)
break;
case 5: // special CGG1 packet
@@ -541,39 +678,42 @@ uint32_t MINRFgetSensorSlot(uint8_t (&_serial)[6], uint16_t _type){
DEBUG_SENSOR_LOG(PSTR("MINRF: vector size %u"), MIBLEsensors.size());
for(uint32_t i=0; i 2){
+ MINRF.confirmedSensors++;
}
}
}
-
-void MINRFhandleFloraPacket(void){
- if(MINRF.buffer.floraPacket.T.valueTen!=0x10){
- DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected Flora packet"));
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- return;
- }
- MINRFreverseMAC(MINRF.buffer.floraPacket.T.serial);
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.floraPacket.T.serial, MINRF.buffer.floraPacket.T.idWord); // T is not specific, any struct would be possible to use
- DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
+/**
+ * @brief generic MiBeacon parser
+ *
+ */
+void MINRFhandleMiBeaconPacket(void){
+ MINRFreverseMAC(MINRF.buffer.miBeacon.Mac);
+ uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID);
if(_slot==0xff) return;
+ DEBUG_SENSOR_LOG(PSTR("MINRF: slot %u, size vector: %u %u"),_slot,MIBLEsensors.size());
+ mi_sensor_t *_sensorVec = &MIBLEsensors.at(_slot);
float _tempFloat;
- switch(MINRF.buffer.floraPacket.L.mode) { // we can use any struct with a mode, they are all same at this point
- case 4:
- _tempFloat=(float)(MINRF.buffer.floraPacket.T.data)/10.0f;
+
+ if (_sensorVec->type==MJ_HT_V1 || _sensorVec->type==CGG1){
+ memcpy(MINRFtempBuf,(uint8_t*)&MINRF.buffer.miBeacon.spare, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1
+ memcpy((uint8_t*)&MINRF.buffer.miBeacon.type,MINRFtempBuf, 32-9); // shift by one byte for the MJ_HT_V1 and CGG1
+ }
+
+ DEBUG_SENSOR_LOG(PSTR("%s at slot %u"), kNRFSlaveType[_sensorVec->type-1],_slot);
+ switch(MINRF.buffer.miBeacon.type){
+ case 0x04:
+ _tempFloat=(float)(MINRF.buffer.miBeacon.temp)/10.0f;
if(_tempFloat<60){
- MIBLEsensors.at(_slot).temp=_tempFloat;
+ _sensorVec->temp=_tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode 4: temp updated"));
}
- DEBUG_SENSOR_LOG(PSTR("Flora: Mode 4: U16: %x Temp"), MINRF.buffer.floraPacket.T.data );
+ DEBUG_SENSOR_LOG(PSTR("Mode 4: U16: %u Temp"), MINRF.buffer.miBeacon.temp );
break;
- case 7:
- if(true){
- MIBLEsensors.at(_slot).lux=MINRF.buffer.floraPacket.L.data;
+ case 0x06:
+ _tempFloat=(float)(MINRF.buffer.miBeacon.hum)/10.0f;
+ if(_tempFloat<101){
+ _sensorVec->hum=_tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode 6: hum updated"));
}
- DEBUG_SENSOR_LOG(PSTR("Flora: Mode 7: U24: %x Lux"), MINRF.buffer.floraPacket.L.data);
+ DEBUG_SENSOR_LOG(PSTR("Mode 6: U16: %u Hum"), MINRF.buffer.miBeacon.hum);
break;
- case 8:
- _tempFloat =(float)MINRF.buffer.floraPacket.M.data;
+ case 0x07:
+ _sensorVec->lux=MINRF.buffer.miBeacon.lux & 0x00ffffff;
+ DEBUG_SENSOR_LOG(PSTR("Mode 7: U24: %u Lux"), MINRF.buffer.miBeacon.lux & 0x00ffffff);
+ break;
+ case 0x08:
+ _tempFloat =(float)MINRF.buffer.miBeacon.moist;
if(_tempFloat<100){
- MIBLEsensors.at(_slot).moisture=_tempFloat;
+ _sensorVec->moisture=_tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode 8: moisture updated"));
}
- DEBUG_SENSOR_LOG(PSTR("Flora: Mode 8: U8: %x Moisture"), MINRF.buffer.floraPacket.M.data);
+ DEBUG_SENSOR_LOG(PSTR("Mode 8: U8: %u Moisture"), MINRF.buffer.miBeacon.moist);
break;
- case 9:
- _tempFloat=(float)(MINRF.buffer.floraPacket.F.data);
+ case 0x09:
+ _tempFloat=(float)(MINRF.buffer.miBeacon.fert);
if(_tempFloat<65535){ // ???
- MIBLEsensors.at(_slot).fertility=_tempFloat;
+ _sensorVec->fertility=_tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode 9: fertility updated"));
}
- DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %x Fertility"), MINRF.buffer.floraPacket.F.data);
- break;
- }
-}
-
-void MINRFhandleMJ_HT_V1Packet(void){
- if(MINRF.buffer.MJ_HT_V1Packet.TH.valueTen!=0x10){
- DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected MJ_HT_V1-packet"));
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- return;
- }
- MINRFreverseMAC(MINRF.buffer.MJ_HT_V1Packet.TH.serial);
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.MJ_HT_V1Packet.TH.serial, MINRF.buffer.MJ_HT_V1Packet.TH.idWord); // B would be possible too
- DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
- if(_slot==0xff) return;
-
- float _tempFloat;
- switch(MINRF.buffer.MJ_HT_V1Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point
- case 0x0d:
- _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.temp)/10.0f;
- if(_tempFloat<60){
- MIBLEsensors.at(_slot).temp = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: temp updated"));
- }
- _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.hum)/10.0f;
- if(_tempFloat<100){
- MIBLEsensors.at(_slot).hum = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: hum updated"));
- }
- DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1 mode:0x0d: U16: %x Temp U16: %x Hum"), MINRF.buffer.MJ_HT_V1Packet.TH.temp, MINRF.buffer.MJ_HT_V1Packet.TH.hum);
+ DEBUG_SENSOR_LOG(PSTR("Mode 9: U16: %u Fertility"), MINRF.buffer.miBeacon.fert);
break;
case 0x0a:
- if(MINRF.buffer.MJ_HT_V1Packet.B.battery<101){
- MIBLEsensors.at(_slot).bat = MINRF.buffer.MJ_HT_V1Packet.B.battery;
- DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1: bat updated"));
- }
- DEBUG_SENSOR_LOG(PSTR("MJ_HT_V1 mode:0x0a: U8: %x %%"), MINRF.buffer.MJ_HT_V1Packet.B.battery);
+ if(MINRF.buffer.miBeacon.bat<101){
+ _sensorVec->bat = MINRF.buffer.miBeacon.bat;
+ DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated"));
+ }
+ DEBUG_SENSOR_LOG(PSTR("Mode a: U8: %u %%"), MINRF.buffer.miBeacon.bat);
break;
- }
-}
-
-void MINRFhandleLYWSD02Packet(void){
- if(MINRF.buffer.LYWSD02Packet.TH.valueTen!=0x10){
- DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected LYWSD02-packet"));
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- return;
- }
- MINRFreverseMAC(MINRF.buffer.LYWSD02Packet.TH.serial);
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.LYWSD02Packet.TH.serial, MINRF.buffer.LYWSD02Packet.TH.idWord); // H would be possible too
- DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
- if(_slot==0xff) return;
-
- float _tempFloat;
- switch(MINRF.buffer.LYWSD02Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point
- case 4:
- _tempFloat=(float)(MINRF.buffer.LYWSD02Packet.TH.data)/10.0f;
+ case 0x0d:
+ _tempFloat=(float)(MINRF.buffer.miBeacon.HT.temp)/10.0f;
if(_tempFloat<60){
- MIBLEsensors.at(_slot).temp=_tempFloat;
+ _sensorVec->temp = _tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode d: temp updated"));
+ }
+ _tempFloat=(float)(MINRF.buffer.miBeacon.HT.hum)/10.0f;
+ if(_tempFloat<100){
+ _sensorVec->hum = _tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("Mode d: hum updated"));
}
- DEBUG_SENSOR_LOG(PSTR("LYWSD02: Mode 4: U16: %x Temp"), MINRF.buffer.LYWSD02Packet.TH.data );
- break;
- case 6:
- _tempFloat=(float)(MINRF.buffer.LYWSD02Packet.TH.data)/10.0f;
- if(_tempFloat<101){
- MIBLEsensors.at(_slot).hum=_tempFloat;
- }
- DEBUG_SENSOR_LOG(PSTR("LYWSD02: Mode 6: U16: %x Hum"), MINRF.buffer.LYWSD02Packet.TH.data );
+ DEBUG_SENSOR_LOG(PSTR("Mode d: U16: %x Temp U16: %x Hum"), MINRF.buffer.miBeacon.HT.temp, MINRF.buffer.miBeacon.HT.hum);
break;
}
}
-
+/**
+ * @brief more or less a placeholder, at least it is technically possible to really decrypt data, but
+ * the bind_key must be retrieved with 3rd-party-tools -> TODO
+ */
void MINRFhandleLYWSD03Packet(void){
// not much to do ATM, just show the sensor without data
- MINRFreverseMAC(MINRF.buffer.LYWSD02Packet.TH.serial); //the beginning is equal to the LYWSD02-packet
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.LYWSD02Packet.TH.serial, MINRF.buffer.LYWSD02Packet.TH.idWord);
+ MINRFreverseMAC(MINRF.buffer.miBeacon.Mac);
+ uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.miBeacon.Mac, MINRF.buffer.miBeacon.productID);
DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
if(_slot==0xff) return;
@@ -712,67 +839,43 @@ void MINRFhandleLYWSD03Packet(void){
MINRF_LOG_BUFFER(MINRF.buffer.raw);
}
-void MINRFhandleCGG1Packet(void){ // we assume, that the packet structure is equal to the MJ_HT_V1
- if(MINRF.buffer.MJ_HT_V1Packet.TH.valueTen!=0x10){
- DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected CGG1-packet"));
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- return;
- }
- MINRFreverseMAC(MINRF.buffer.MJ_HT_V1Packet.TH.serial);
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.MJ_HT_V1Packet.TH.serial, MINRF.buffer.MJ_HT_V1Packet.TH.idWord); // B would be possible too
+/**
+ * @brief parse the Cleargrass-packet
+ * Note: battery section is based on "internet data" -> not confirmed yet
+ */
+void MINRFhandleCGD1Packet(void){ // no MiBeacon
+ MINRFreverseMAC(MINRF.buffer.CGDPacket.serial);
+ uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.CGDPacket.serial, 0x0576); // This must be hard-coded, no object-id in Cleargrass-packet
DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
if(_slot==0xff) return;
- float _tempFloat;
- switch(MINRF.buffer.MJ_HT_V1Packet.TH.mode) { // we can use any struct with a mode, they are all same at this point
- case 0x0d:
- _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.temp)/10.0f;
- if(_tempFloat<60){
- MIBLEsensors.at(_slot).temp = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("CGG1: temp updated"));
- }
- _tempFloat=(float)(MINRF.buffer.MJ_HT_V1Packet.TH.hum)/10.0f;
- if(_tempFloat<100){
- MIBLEsensors.at(_slot).hum = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("CGG1: hum updated"));
- }
- DEBUG_SENSOR_LOG(PSTR("CGG1 mode:0x0d: U16: %x Temp U16: %x Hum"), MINRF.buffer.MJ_HT_V1Packet.TH.temp, MINRF.buffer.MJ_HT_V1Packet.TH.hum);
- break;
- case 0x0a:
- if(MINRF.buffer.MJ_HT_V1Packet.B.battery<101){
- MIBLEsensors.at(_slot).bat = MINRF.buffer.MJ_HT_V1Packet.B.battery;
- DEBUG_SENSOR_LOG(PSTR("CGG1: bat updated"));
- }
- DEBUG_SENSOR_LOG(PSTR("CGG1 mode:0x0a: U8: %x %%"), MINRF.buffer.MJ_HT_V1Packet.B.battery);
- break;
+ switch (MINRF.buffer.CGDPacket.mode){
+ case 0x0401:
+ float _tempFloat;
+ _tempFloat=(float)(MINRF.buffer.CGDPacket.temp)/10.0f;
+ if(_tempFloat<60){
+ MIBLEsensors.at(_slot).temp = _tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated"));
+ }
+ _tempFloat=(float)(MINRF.buffer.CGDPacket.hum)/10.0f;
+ if(_tempFloat<100){
+ MIBLEsensors.at(_slot).hum = _tempFloat;
+ DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated"));
+ }
+ DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), MINRF.buffer.CGDPacket.temp, MINRF.buffer.CGDPacket.hum);
+ break;
+ case 0x0102:
+ if(MINRF.buffer.CGDPacket.bat<101){
+ MIBLEsensors.at(_slot).bat = MINRF.buffer.CGDPacket.bat;
+ DEBUG_SENSOR_LOG(PSTR("Mode a: bat updated"));
+ }
+ break;
+ default:
+ DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected CGD1-packet"));
+ MINRF_LOG_BUFFER(MINRF.buffer.raw);
}
}
-void MINRFhandleCGD1Packet(void){ //
- if(MINRF.buffer.CGDPacket.TH.mode!=0x0401){ // not really a mode
- DEBUG_SENSOR_LOG(PSTR("MINRF: unexpected CGD1-packet"));
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- return;
- }
- MINRFreverseMAC(MINRF.buffer.CGDPacket.TH.serial);
- uint32_t _slot = MINRFgetSensorSlot(MINRF.buffer.CGDPacket.TH.serial, 0x0576); // This must be hard-coded, no object-id in Cleargrass-packet
- DEBUG_SENSOR_LOG(PSTR("MINRF: Sensor slot: %u"), _slot);
- if(_slot==0xff) return;
-
- float _tempFloat;
- _tempFloat=(float)(MINRF.buffer.CGDPacket.TH.temp)/10.0f;
- if(_tempFloat<60){
- MIBLEsensors.at(_slot).temp = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("CGD1: temp updated"));
- }
- _tempFloat=(float)(MINRF.buffer.CGDPacket.TH.hum)/10.0f;
- if(_tempFloat<100){
- MIBLEsensors.at(_slot).hum = _tempFloat;
- DEBUG_SENSOR_LOG(PSTR("CGD1: hum updated"));
- }
- DEBUG_SENSOR_LOG(PSTR("CGD1: U16: %x Temp U16: %x Hum"), MINRF.buffer.CGDPacket.TH.temp, MINRF.buffer.CGDPacket.TH.hum);
-}
-
/*********************************************************************************************\
* Main loop of the driver
\*********************************************************************************************/
@@ -790,163 +893,262 @@ void MINRF_EVERY_50_MSECOND() { // Every 50mseconds
// DEBUG_SENSOR_LOG(PSTR("MINRF: nothing received"));
}
- else if(MINRF.buffer.bleAdv.header.uuid==0xfe95){ // XIAOMI-BLE-Packet
- MINRF_LOG_BUFFER(MINRF.streamBuffer);
- MINRF_LOG_BUFFER(MINRF.lsfrBuffer);
- MINRF_LOG_BUFFER(MINRF.buffer.raw);
- DEBUG_SENSOR_LOG(PSTR("MINRF: Type: %x"), MINRF.buffer.bleAdv.header.type);
- switch(MINRF.buffer.bleAdv.header.type){
- case 0x2050:
- DEBUG_SENSOR_LOG(PSTR("MINRF: MJ_HT_V1 Packet"));
- break;
- case 0x1613:case 0x1614:case 0x1615:
- DEBUG_SENSOR_LOG(PSTR("MINRF: Flora Packet"));
- break;
+ else {
+ switch (MINRF.packetMode) {
+ case 0:
+ if (MINRF.beacon.active){
+ MINRFhandleBeacon(&MINRFdummyEntry,6);
+ }
+ else MINRFhandleScan();
+ break;
+ case FLORA: case MJ_HT_V1: case LYWSD02: case CGG1:
+ MINRFhandleMiBeaconPacket();
+ break;
+ case LYWSD03:
+ MINRFhandleLYWSD03Packet();
+ break;
+ case CGD1:
+ MINRFhandleCGD1Packet();
+ break;
default:
- DEBUG_SENSOR_LOG(PSTR("MINRF: unknown Packet"));
- break;
+ break;
}
}
- else if (MINRF.packetMode == FLORA){
- MINRFhandleFloraPacket();
- }
- else if (MINRF.packetMode == MJ_HT_V1){
- MINRFhandleMJ_HT_V1Packet();
- }
- else if (MINRF.packetMode == LYWSD02){
- MINRFhandleLYWSD02Packet();
- }
- else if (MINRF.packetMode == LYWSD03){
- MINRFhandleLYWSD03Packet();
- }
- else if (MINRF.packetMode == CGG1){
- MINRFhandleCGG1Packet();
- }
- else if (MINRF.packetMode == CGD1){
- MINRFhandleCGD1Packet();
+ if (MINRF.beacon.active || MINRF.activeScan) {
+ MINRF.firstUsedPacketMode=0;
}
-#ifdef IGNORE_FLORA
- if (MINRF.packetMode+1 == FLORA) MINRF.packetMode++;
-#endif // IGNORE_LYWSD03
-#ifdef IGNORE_MJ_HT_V1
- if (MINRF.packetMode+1 == MJ_HT_V1) MINRF.packetMode++;
-#endif //IGNORE_MJ_HT_V1
-#ifdef IGNORE_LYWSD02
- if (MINRF.packetMode+1 == LYWSD02) MINRF.packetMode++;
-#endif // IGNORE_LYWSD02
-#ifdef IGNORE_LYWSD03
- if (MINRF.packetMode+1 == LYWSD03) MINRF.packetMode++;
-#endif // IGNORE_LYWSD03
-#ifdef IGNORE_CGG1
- if (MINRF.packetMode+1 == CGG1) MINRF.packetMode++;
-#endif // IGNORE_CGG1
-#ifdef IGNORE_CGD1
- if (MINRF.packetMode+1 == CGD1) MINRF.packetMode=0;
-#endif // IGNORE_CGD1
- MINRFinitBLE(++MINRF.packetMode);
-
-if (MINRF.packetMode > CGD1){
- MINRFinitBLE(1); // no real ble packets in release mode, otherwise for developing use 0
+ MINRF.packetMode = (MINRF.packetMode+1>CGD1) ? MINRF.firstUsedPacketMode : MINRF.packetMode+1;
+ for (uint32_t i = MINRF.packetMode; i 0) {
+ if (XdrvMailbox.payload == 0) XdrvMailbox.payload = MINRF.perPage; // ignore 0
+ MINRF.perPage = XdrvMailbox.payload;
+ }
+ else XdrvMailbox.payload = MINRF.perPage;
+ Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload);
+ break;
+ case CMND_NRF_IGNORE:
+ if (XdrvMailbox.data_len > 0) {
+ if (XdrvMailbox.payload == 0){
+ MINRF.ignore = 0;
+ }
+ else if (XdrvMailbox.payload < CGD1+1) {
+ bitSet(MINRF.ignore,XdrvMailbox.payload);
+ MINRFcomputefirstUsedPacketMode();
+ MINRF.timer = 5900;
+ Response_P(S_JSON_NRF_COMMAND, command, kMINRFSlaveType[XdrvMailbox.payload-1]);
+ }
+ else if (XdrvMailbox.payload == 255) {
+ MINRF.ignore = 255;
+ }
+ }
+ Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.ignore);
+ break;
+ case CMND_NRF_SCAN:
+ if (XdrvMailbox.data_len > 0) {
+ MINRF.beacon.active = false;
+ switch(XdrvMailbox.payload){
+ case 0: // new scan
+ MINRF.activeScan = true;
+ MINRF.stopScan = false;
+ MINRFscanResult.erase(std::remove_if(MINRFscanResult.begin(),
+ MINRFscanResult.end(),
+ [](scan_entry_t&) { return true; }),
+ MINRFscanResult.end());
+ break;
+ case 1: // append scan
+ MINRF.activeScan = true;
+ MINRF.stopScan = false;
+ break;
+ case 2: // stop scan
+ MINRF.stopScan = true;
+ break;
+ }
+ Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload);
+ }
+ break;
+ case CMND_NRF_BEACON:
+ if (XdrvMailbox.data_len > 0) {
+ if(XdrvMailbox.data_len<3){ // a list entry
+ if (XdrvMailbox.payload < MINRFscanResult.size()) {
+ MINRFstartBeacon(XdrvMailbox.payload);
+ Response_P(S_JSON_NRF_COMMAND_NVALUE, command, XdrvMailbox.payload);
+ }
+ }
+ if (XdrvMailbox.data_len==12){ // a MAC-string
+ memset(MINRF.beacon.mac,0,sizeof(MINRF.beacon.mac));
+ MINRFMACStringToBytes(XdrvMailbox.data, MINRF.beacon.mac);
+ MINRF.beacon.time=0;
+ MINRF.beacon.active=true;
+ Response_P(S_JSON_NRF_COMMAND, command, XdrvMailbox.data);
+ }
+ MINRFcomputeBeaconPDU();
+ }
+ break;
+ case CMND_NRF_CHAN:
+ if (XdrvMailbox.data_len == 1) {
+ switch(XdrvMailbox.payload){
+ case 0: case 1: case 2:
+ bitRead(MINRF.channelIgnore,XdrvMailbox.payload) == 0 ? bitSet(MINRF.channelIgnore,XdrvMailbox.payload) : bitClear(MINRF.channelIgnore,XdrvMailbox.payload);
+ break;
+ }
+ }
+ Response_P(S_JSON_NRF_COMMAND_NVALUE, command, MINRF.channelIgnore);
+ break;
+ default:
+ // else for Unknown command
+ serviced = false;
+ break;
+ }
+ } else {
+ return false;
+ }
+ return serviced;
+}
+
/*********************************************************************************************\
* Presentation
\*********************************************************************************************/
const char HTTP_BATTERY[] PROGMEM = "{s}%s" " Battery" "{m}%u%%{e}";
const char HTTP_MINRF_MAC[] PROGMEM = "{s}%s %s{m}%02x:%02x:%02x:%02x:%02x:%02x%{e}";
-const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%sus/cm{e}";
+const char HTTP_MINRF_FLORA_DATA[] PROGMEM = "{s}%s" " Fertility" "{m}%dus/cm{e}";
const char HTTP_MINRF_HL[] PROGMEM = "{s}
{m}
{e}";
+const char HTTP_NRF24NEW[] PROGMEM = "{s}%sL01%c{m}%u%s / %u{e}";
void MINRFShow(bool json)
{
if (json) {
for (uint32_t i = 0; i < MIBLEsensors.size(); i++) {
- if(MIBLEsensors.at(i).showedUp < 3){
+ if(MIBLEsensors[i].showedUp < 3){
DEBUG_SENSOR_LOG(PSTR("MINRF: sensor not fully registered yet"));
break;
}
- char slave[33];
- sprintf_P(slave,"%s-%02x%02x%02x",kMINRFSlaveType[MIBLEsensors.at(i).type-1],MIBLEsensors.at(i).serial[3],MIBLEsensors.at(i).serial[4],MIBLEsensors.at(i).serial[5]);
- char temperature[33]; // all sensors have temperature
- dtostrfd(MIBLEsensors.at(i).temp, Settings.flag2.temperature_resolution, temperature);
+ ResponseAppend_P(PSTR(",\"%s-%02x%02x%02x\":{"),kMINRFSlaveType[MIBLEsensors[i].type-1],MIBLEsensors[i].serial[3],MIBLEsensors[i].serial[4],MIBLEsensors[i].serial[5]);
+ if (MIBLEsensors[i].type==FLORA && !isnan(MIBLEsensors[i].temp)){
+ char stemp[FLOATSZ];
+ dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, stemp);
+ ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), stemp);
- ResponseAppend_P(PSTR(",\"%s\":{"),slave);
- if(MIBLEsensors.at(i).temp!=-1000.0f){ // this is the error code -> no temperature
- ResponseAppend_P(PSTR("\"" D_JSON_TEMPERATURE "\":%s"), temperature);
+ if(MIBLEsensors[i].lux!=0xffffffff){ // this is the error code -> no lux
+ ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%u"), MIBLEsensors[i].lux);
}
- if (MIBLEsensors.at(i).type==FLORA){
- char lux[33];
- char moisture[33];
- char fertility[33];
- dtostrfd((float)MIBLEsensors.at(i).lux, 0, lux);
- dtostrfd(MIBLEsensors.at(i).moisture, 0, moisture);
- dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility);
- if(MIBLEsensors.at(i).lux!=0xffff){ // this is the error code -> no temperature
- ResponseAppend_P(PSTR(",\"" D_JSON_ILLUMINANCE "\":%s"), lux);
- }
- if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no moisture
- ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), moisture);
- }
- if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no fertility
- ResponseAppend_P(PSTR(",\"Fertility\":%s"), fertility);
- }
+ if(!isnan(MIBLEsensors[i].moisture)){
+ dtostrfd(MIBLEsensors[i].moisture, 0, stemp);
+ ResponseAppend_P(PSTR(",\"" D_JSON_MOISTURE "\":%s"), stemp);
}
- if (MIBLEsensors.at(i).type>FLORA){
- char humidity[33];
- dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity);
- if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity
- ResponseAppend_P(PSTR(",\"" D_JSON_HUMIDITY "\":%s"), humidity);
- }
- if(MIBLEsensors.at(i).bat!=0x00){ // this is the error code -> no battery
- ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors.at(i).bat);
- }
+ if(!isnan(MIBLEsensors[i].fertility)){
+ dtostrfd(MIBLEsensors[i].fertility, 0, stemp);
+ ResponseAppend_P(PSTR(",\"Fertility\":%s"), stemp);
}
- ResponseAppend_P(PSTR("}"));
+ ResponseJsonEnd();
+ }
+ if (MIBLEsensors[i].type>FLORA){
+ if(!isnan(MIBLEsensors[i].temp) && !isnan(MIBLEsensors[i].hum)){
+ ResponseAppendTHD(MIBLEsensors[i].temp,MIBLEsensors[i].hum);
+ }
+ if(MIBLEsensors[i].bat!=0x00){ // this is the error code -> no battery
+ ResponseAppend_P(PSTR(",\"Battery\":%u"), MIBLEsensors[i].bat);
+ }
+ ResponseJsonEnd();
+ }
}
+ if(MINRF.beacon.active){
+ ResponseAppend_P(PSTR(",\"Beacon\":{\"Timer\":%u}"),MINRF.beacon.time);
+ }
+ // ResponseJsonEnd();
#ifdef USE_WEBSERVER
} else {
- WSContentSend_PD(HTTP_NRF24, NRF24type, NRF24.chipType);
- for (uint32_t i = 0; i < MIBLEsensors.size(); i++) {
- if(MIBLEsensors.at(i).showedUp < 3){
+ static uint32_t _page = 0;
+ static uint32_t counter = 0;
+ int32_t i = _page * MINRF.perPage;
+ uint32_t j = i + MINRF.perPage;
+
+ if (j+1>MINRF.confirmedSensors){
+ j = MINRF.confirmedSensors;
+ }
+ char stemp[5] ={0};
+ if (MINRF.confirmedSensors-(_page*MINRF.perPage)>1 && MINRF.perPage!=1) {
+ sprintf_P(stemp,"-%u",j);
+ }
+ if (MINRF.confirmedSensors==0) i=-1; // only for the GUI
+
+ WSContentSend_PD(HTTP_NRF24NEW, NRF24type, NRF24.chipType, i+1,stemp,MINRF.confirmedSensors);
+ for (i ; i no valid value
- WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).lux);
+ WSContentSend_PD(HTTP_MINRF_MAC, kMINRFSlaveType[MIBLEsensors[i].type-1], D_MAC_ADDRESS, MIBLEsensors[i].serial[0], MIBLEsensors[i].serial[1],MIBLEsensors[i].serial[2],MIBLEsensors[i].serial[3],MIBLEsensors[i].serial[4],MIBLEsensors[i].serial[5]);
+ if (MIBLEsensors[i].type==FLORA){
+ if(!isnan(MIBLEsensors[i].temp)){
+ char temperature[FLOATSZ];
+ dtostrfd(MIBLEsensors[i].temp, Settings.flag2.temperature_resolution, temperature);
+ WSContentSend_PD(HTTP_SNS_TEMP, kMINRFSlaveType[MIBLEsensors[i].type-1], temperature, TempUnit());
}
- if(MIBLEsensors.at(i).moisture!=-1000.0f){ // this is the error code -> no valid value
- WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).moisture);
+ if(MIBLEsensors[i].lux!=0xffffffff){ // this is the error code -> no valid value
+ WSContentSend_PD(HTTP_SNS_ILLUMINANCE, kMINRFSlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].lux);
}
- if(MIBLEsensors.at(i).fertility!=-1000.0f){ // this is the error code -> no valid value
- char fertility[33];
- dtostrfd(MIBLEsensors.at(i).fertility, 0, fertility);
- WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors.at(i).type-1], fertility);
+ if(!isnan(MIBLEsensors[i].moisture)){ // this is the error code -> no valid value
+ WSContentSend_PD(HTTP_SNS_MOISTURE, kMINRFSlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].moisture);
+ }
+ if(!isnan(MIBLEsensors[i].fertility)){ // this is the error code -> no valid value
+ WSContentSend_PD(HTTP_MINRF_FLORA_DATA, kMINRFSlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].fertility);
}
}
- if (MIBLEsensors.at(i).type>FLORA){ // everything "above" Flora
- if(MIBLEsensors.at(i).hum!=-1.0f){ // this is the error code -> no humidity
- char humidity[33];
- dtostrfd(MIBLEsensors.at(i).hum, Settings.flag2.humidity_resolution, humidity);
- WSContentSend_PD(HTTP_SNS_HUM, kMINRFSlaveType[MIBLEsensors.at(i).type-1], humidity);
- }
- if(MIBLEsensors.at(i).bat!=0x00){ // without "juice" nothing can be done
- WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors.at(i).type-1], MIBLEsensors.at(i).bat);
+ if (MIBLEsensors[i].type>FLORA){ // everything "above" Flora
+ WSContentSend_THD(kMINRFSlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].temp, MIBLEsensors[i].hum);
+ if(MIBLEsensors[i].bat!=0x00){ // without "juice" nothing can be done
+ WSContentSend_PD(HTTP_BATTERY, kMINRFSlaveType[MIBLEsensors[i].type-1], MIBLEsensors[i].bat);
}
}
}
+ if(MINRF.beacon.active){
+ WSContentSend_PD(HTTP_MINRF_HL);
+ WSContentSend_PD(HTTP_MINRF_HL);
+ WSContentSend_PD(HTTP_MINRF_MAC, F("Beacon"), D_MAC_ADDRESS, MINRF.beacon.mac[0], MINRF.beacon.mac[1],MINRF.beacon.mac[2],MINRF.beacon.mac[3],MINRF.beacon.mac[4],MINRF.beacon.mac[5]);
+ WSContentSend_PD(PSTR("{s}Beacon Time{m}%u seconds{e}"),MINRF.beacon.time);
+ }
+ if(counter>3) {
+ _page++;
+ counter = 0;
+ }
+ counter++;
+ if(MINRF.confirmedSensors%MINRF.perPage==0 && _page==MINRF.confirmedSensors/MINRF.perPage) _page=0;
+ if(_page>MINRF.confirmedSensors/MINRF.perPage) _page=0;
#endif // USE_WEBSERVER
}
}
@@ -958,7 +1160,6 @@ void MINRFShow(bool json)
bool Xsns61(uint8_t function)
{
bool result = false;
-
if (NRF24.chipType) {
switch (function) {
case FUNC_INIT:
@@ -968,6 +1169,12 @@ bool Xsns61(uint8_t function)
case FUNC_EVERY_50_MSECOND:
MINRF_EVERY_50_MSECOND();
break;
+ case FUNC_EVERY_SECOND:
+ MINRFbeaconCounter();
+ break;
+ case FUNC_COMMAND:
+ result = NRFCmd();
+ break;
case FUNC_JSON_APPEND:
MINRFShow(1);
break;