…here is the next part…
Way around the 255 bytes limit in homeassistant
I use mqtt to get a json string to homeassistant where this json than will be stored in attributes of a sensor. The result:
Here is the relating mqtt sensor in my configuration.yaml
mqtt:
# Wasserzähler mqtt Sensoren
sensor:
- name: "Wasser Zaehler 8Zxxxxxxxxxxxx - Daten"
unique_id: "wasser_zaehler_8zrxxxxxxxxxxxx_Daten"
state_topic: "water_meter/8zrxxxxxxxxxxxx/data"
value_template: "{{ 'Ultrasonic-Water-Meter: 8Zxxxxxxxxxxxx' }} "
json_attributes_topic: "water_meter/8zrxxxxxxxxxxxx/data"
# Wasserzähler mqtt Sensoren Ende
Deep Sleep - helping the pn532 to fire “on_tag”
As you can see as well, I use “deep sleep” in the esphome yaml to get the “on_tag” event to fire not only once…
I don’t know whether this is the best way to do it but the Water Meter reader is now giving me new data every few minutes (Sometimes it takes 12 to 15 minutes to get new data). This seems to depend on how often the Ultrasonic Meter is generating new input for the tag… I am not really sure how this thing works (and there is no manual i could find).
This is good enough for me in the moment…
There might be someone out there to help here??
The libraries…
First a words about my “solution”:
What i am going to show here is NOT a valid and thoroughly tested new version of the libraries. I was just looking to find a way to get the read of the tags done. It is just a hint to what might be necessary to work on the libraries. The libraries are just not intended to handle the current case.
What did i find:
- the on_tag event fired and i was able to see the id off the tag…
It showed me, that this is a mifare ultralight tag and it should have an ndef-record (which contains the information). - i used NFC Tools on my mobile to analyse the information which is on the tag
(The interesting thing is: the tool seems to see just the first 255 pages… beginning page 256 it shows the same data again??) - After trying to check whether there is an ndef message attached, the program stopped… Adding some debug-message showed the reason:
the program tried to read millions of bytes…
So, first i had to adjust my environment (esphome) to handle own libraries.
external_components:
# use all components from a local folder
- source:
type: local
path: components
components:
- nfc
- pn532_i2c
- pn532
I found the libraries in [ESPHome · GitHub] .I copied all libraries (just the libraries i needed) folder into my ha-environment in esphome/components… and populated them via the yaml file…
Here is how to do these things: External Components — ESPHome
My way to pass the barrier
- nfc.h
First thing I found:
Old:
static const uint8_t MIFARE_ULTRALIGHT_MAX_PAGE = 64;
MAX_PAGE = 64 results in 255 bytes!
- New
static const uint8_t MIFARE_ULTRALIGHT_MAX_PAGE = 255;
- 255 is the max. number with uint8_t - (has probably to be changed…) .
This results in max 1020 bytes (255 * 4 bytes/page)
- pn532.mifare_ultralight.cpp
Here the message length is going to be calculated:
bool PN532::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint8_t &message_length,
uint8_t &message_start_index) {
const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector
if (!(page_3_to_6.size() > p4_offset + 5)) {
return false;
}
if (page_3_to_6[p4_offset + 0] == 0x03) {
message_length = page_3_to_6[p4_offset + 1];
message_start_index = 2;
return true;
} else if (page_3_to_6[p4_offset + 5] == 0x03) {
message_length = page_3_to_6[p4_offset + 6];
message_start_index = 7;
return true;
}
return false;
}
Here lies the main problem:
Looking at the date coming from the UWM:
[ E1:10:EA:00 ] Sektor 03 : DATA
[ 03:FF:02:FC ] Sektor 04 : DATA
| | |
| | ------------------------2 byte length of ndef message: 2FCh= 764 bytes
| ------------------------------FF = Length: FF = 2 BYte Length Field
---------------------------------Data type: 03 = NDEF Record
[ C1:01:00:00 ] Sektor 05 : DATA
| | | |
| | | ------------------------Payload Length
| | ---------------------------Payload Length
| ------------------------------Type Length
---------------------------------1100 0001
|||| |---
|||| | |
|||| | ------------ TNF = 001 = well known
|||| -------------- IL = 0 (ID-Length = no)
|||---------------- SR = 0 (Kein Short Record)
||----------------- CF = 0 (Last Chunk Record)
|------------------ ME = 1 (Message End)
------------------- MB = 1 (Message Begin)
[ 02:F5:54:02 ] Sektor 06 : DATA
| | | |
| | | ------------------------Start of NDEF-Record: Status Code 02h This is UTF-8 and has a 2 byte language code
| | ---------------------------Type 54h = T
---------------------------------Payload Lendth 02F5h= 757 (ndef message length - 7 bytes von sector 5 und 6)
These are the pages (Sektoren) which are cúrrently in scope - the function works with:
[ 03:FF:02:FC ] Sektor 04 : DATA
In the “old” version the second byte 0xff is taken as the length (255). But 0xFF means, that there are two following bytes containing the length…
0x02FC = 512 + 240 + 12 = 764 bytes!
(The “old” version of the function returns length=255 and message_start_index = 2)
[ C1:01:00:00] Sektor 05 : DATA
[ 02:F5:54:02 ] Sektor 06 : DATA
Because the payload-length (payload = the information, we are after…) is starting 2 bytes after the length field, the library returns 0xC1010000 which is a huuuuuge number (3,238,068,224) instead of 0x000002F5 = 512 + 240 + 5 = 757 bytes!
(The “new” version of the function returns length=764 and message_start_index = 4)
remark: the numbers may be different in your case, because the length depends on the history data stored in the payload
I changed the code (but just for the given case):
bool PN532::find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint16_t &message_length,
uint8_t &message_start_index) {
const uint8_t p4_offset = nfc::MIFARE_ULTRALIGHT_PAGE_SIZE; // page 4 will begin 4 bytes into the vector
ESP_LOGD(TAG, "MALOG: find_mifare_ultralight_ndef_");
if (!(page_3_to_6.size() > p4_offset + 5)) {
return false;
}
if (page_3_to_6[p4_offset + 0] == 0x03) {
if (page_3_to_6[p4_offset + 1] == 0xFF) {
// dynamic length: byte 0 = 0x03; byte 1 = 0xFF; Length in byte 3 and 4
message_length = page_3_to_6[p4_offset + 2] * 256 + page_3_to_6[p4_offset + 3];
message_start_index = 4;
ESP_LOGD(TAG, "MALOG: find_mifare_ultralight_ndef_: TRUE1a");
} else {
// fixed length: byte 0 = 0x03; byte 1 = Length
message_length = page_3_to_6[p4_offset + 2];
message_start_index = 2;
ESP_LOGD(TAG, "MALOG: find_mifare_ultralight_ndef_: TRUE1b");
}
return true;
} else if (page_3_to_6[p4_offset + 5] == 0x03) {
message_length = page_3_to_6[p4_offset + 6];
message_start_index = 7;
ESP_LOGD(TAG, "MALOG: find_mifare_ultralight_ndef_: TRUE2");
return true;
}
ESP_LOGD(TAG, "MALOG: find_mifare_ultralight_ndef_: FALSE");
return false;
}
In the same file the function read_mifare_ultralight_tag_ has to be taken into account as well:
the line with
uint8_t message_length;
has to be changed to
uint16_t message_length;
- The PN532.h has to be changed as well to:
(just this entry…)
bool find_mifare_ultralight_ndef_(const std::vector<uint8_t> &page_3_to_6, uint16_t &message_length,
uint8_t &message_start_index);
I hope i havn’t forgot anything…
…and… this might not be the end of the story…
Thanks to you alll!!!
Most of the information 1 got here:
https://github.com/esphome
(Libraries)
NFC Text Record Type Definition:
NFC Type 2 Tag Operation Specification
(Type 2 Tag Operation Specification: here 6 NDEF Detection and Access)
chatgpt
Coding and clarifying errors
Simon42 youtube videos
helping me to understand Homeassistant
and from a lot of comments populated here and in other communities…