[Gelöst] Mi Flora mit Tasmota empfangen

Begonnen von OppiM, 14 Juli 2020, 11:06:30

Vorheriges Thema - Nächstes Thema

OppiM

Hi,

bisher empfange ich meine MiFlora-Sensoren über verschiedene OpenMQTTGateways. Nachdem ich jetzt gesehen habe, dass Tasmota auch den ESP32 mit Bluetooth und die MiFlora-Sensoren unterstützt, versuche ich jetzt, diesen Weg an FHEM anzubinden, vor allem, weil Tasmota auch Batterie und Firmware mit auslesen kann.

Folgendes sendet ein Tasmota-ESP32:
10:58:25 MQT: tele/ESP32_01/SENSOR = {"Time":"2020-07-14T10:58:25","Flora-66b349":{"Temperature":29.9,"Illuminance":112630,"Moisture":29.000000,"Fertility":91.000000,"Battery":98,"Firmware":"3.1.9"},"Flora-666c1a":{"Temperature":28.4,"Illuminance":13700,"Moisture":0.000000,"Fertility":431.000000,"Battery":100,"Firmware":"3.2.2"},"Flora-66e87c":{"Temperature":32.5,"Illuminance":90736,"Moisture":17.000000,"Fertility":104.000000},"TempUnit":"C"}

In dem Tasmota-Device in FHEM sieht es dann so aus:
Internals:
   CID        ESP32_01
   DEF        ESP32_01
   DEVICETOPIC Tasmota_ESP32_01
   IODev      m2s
   LASTInputDev m2s
   MSGCNT     1047
   NAME       Tasmota_ESP32_01
   NR         60
   STATE      Online
   TYPE       MQTT2_DEVICE
   m2s_MSGCNT 1047
   m2s_TIME   2020-07-14 10:58:25
   READINGS:
     2020-07-12 09:51:19   FallbackTopic   cmnd/ESP32_01_fb/
     2020-07-14 10:58:25   Flora-666c1a_Battery 100
     2020-07-14 10:58:25   Flora-666c1a_Fertility 431.000000
     2020-07-14 10:58:25   Flora-666c1a_Firmware 3.2.2
     2020-07-14 10:58:25   Flora-666c1a_Illuminance 13700
     2020-07-14 10:58:25   Flora-666c1a_Moisture 0.000000
     2020-07-14 10:58:25   Flora-666c1a_Temperature 28.4
     2020-07-14 10:58:25   Flora-66b349_Battery 98
     2020-07-14 10:58:25   Flora-66b349_Fertility 91.000000
     2020-07-14 10:58:25   Flora-66b349_Firmware 3.1.9
     2020-07-14 10:58:25   Flora-66b349_Illuminance 112630
     2020-07-14 10:58:25   Flora-66b349_Moisture 29.000000
     2020-07-14 10:58:25   Flora-66b349_Temperature 29.9
     2020-07-14 10:58:25   Flora-66e87c_Fertility 104.000000
     2020-07-14 10:58:25   Flora-66e87c_Illuminance 90736
     2020-07-14 10:58:25   Flora-66e87c_Moisture 17.000000
     2020-07-14 10:58:25   Flora-66e87c_Temperature 32.5
     2020-07-12 09:51:19   GroupTopic      cmnd/tasmotas/
     2020-07-12 09:51:19   Hostname        ESP32_01
     2020-07-14 10:58:25   LWT             Online
     2020-07-12 09:51:19   Module          ESP32-DevKit
     2020-07-11 18:18:21   TempUnit        C
     2020-07-14 10:58:25   Time            2020-07-14T10:58:25
     2020-07-12 09:51:19   Version         8.4.0(sensors)
     2020-07-12 08:59:12   subscriptions   cmnd/ESP32_01/# cmnd/ESP32_01_fb/# cmnd/tasmotas/#
Attributes:
   DbLogExclude .*
   IODev      m2s
   event-on-change-reading .*
   readingList ESP32_01:tele/ESP32_01/LWT:.* LWT
ESP32_01:cmnd/ESP32_01/POWER:.* POWER
ESP32_01:tele/ESP32_01/INFO1:.* { json2nameValue($EVENT) }
ESP32_01:tele/ESP32_01/INFO2:.* { json2nameValue($EVENT) }
ESP32_01:tele/ESP32_01/INFO3:.* { json2nameValue($EVENT) }
ESP32_01:tele/ESP32_01/STATE:.* { json2nameValue($EVENT) }
ESP32_01:tele/ESP32_01/SENSOR:.* { json2nameValue($EVENT) }
ESP32_01:stat/ESP32_01/RESULT:.* { json2nameValue($EVENT) }
ESP32_01:stat/ESP32_01/UPGRADE:.* { json2nameValue($EVENT) }
   room       MQTT2_DEVICE
   stateFormat LWT


Wie bekomme ich dies jetzt pro Sensor am elegantesten in FHEM abgebildet? Wie beim OpenMQTTGateway kann hier natürlich ein Sensor von verschiedenen Tasmota-ESP32 empfangen werden.

Zur Zeit habe ich pro MiFlora-Sensor folgendes definiert:
defmod Flora_666C1A MQTT2_DEVICE ESP32_01
attr Flora_666C1A DbLogExclude .*
attr Flora_666C1A IODev m2s
attr Flora_666C1A event-on-change-reading .*
attr Flora_666C1A icon temperature_humidity
attr Flora_666C1A jsonMap Flora-666c1a_Temperature:temperature\
Flora-666c1a_Battery:battery\
Flora-666c1a_Fertility:fertility\
Flora-666c1a_Illuminance:lux\
Flora-666c1a_Moisture:moisture\
Flora-666c1a_Firmware:firmware\
Flora-662e96_Temperature:0\
Flora-66ace7_Temperature:0\
Flora-66e87c_Temperature:0\
Flora-66b195_Temperature:0\
Flora-66b349_Temperature:0\
Flora-66b356_Temperature:0\
Flora-66b302_Temperature:0\
Flora-662e96_Battery:0\
Flora-66ace7_Battery:0\
Flora-66e87c_Battery:0\
Flora-66b195_Battery:0\
Flora-66b349_Battery:0\
Flora-66b356_Battery:0\
Flora-66b302_Battery:0\
Flora-662e96_Fertility:0\
Flora-66ace7_Fertility:0\
Flora-66e87c_Fertility:0\
Flora-66b195_Fertility:0\
Flora-66b349_Fertility:0\
Flora-66b356_Fertility:0\
Flora-66b302_Fertility:0\
Flora-662e96_Illuminance:0\
Flora-66ace7_Illuminance:0\
Flora-66e87c_Illuminance:0\
Flora-66b195_Illuminance:0\
Flora-66b349_Illuminance:0\
Flora-66b356_Illuminance:0\
Flora-66b302_Illuminance:0\
Flora-662e96_Moisture:0\
Flora-66ace7_Moisture:0\
Flora-66e87c_Moisture:0\
Flora-66b195_Moisture:0\
Flora-66b349_Moisture:0\
Flora-66b356_Moisture:0\
Flora-66b302_Moisture:0\
Flora-66b302_Firmware:0\
Flora-662e96_Firmware:0\
Flora-66ace7_Firmware:0\
Flora-66e87c_Firmware:0\
Flora-66b195_Firmware:0\
Flora-66b349_Firmware:0\
Flora-66b356_Firmware:0\
ANALOG_A0:0\
TempUnit:0\
Switch1:0
attr Flora_666C1A readingList ESP32_01:tele/ESP32_01/SENSOR:.* { json2nameValue($EVENT,'',$JSONMAP) }\
ESP32_02:tele/ESP32_02/SENSOR:.* { json2nameValue($EVENT,'',$JSONMAP) }\
ESP32_03:tele/ESP32_03/SENSOR:.* { json2nameValue($EVENT,'',$JSONMAP) }\
ESP8266_01:tele/ESP8266_01/SENSOR:.* { json2nameValue($EVENT,'',$JSONMAP) }\
Shelly1_02:tele/Shelly1_02/SENSOR:.* { json2nameValue($EVENT,'',$JSONMAP) }
attr Flora_666C1A room FlowerCare,MQTT2_DEVICE
attr Flora_666C1A stateFormat T: temperature°C, M: moisture%, L: lux, F: fertility, B: battery%


Ich abonniere also von allen Tasmota-BT-Geräten das Sensor-Topic, mappe pro Sensor per JSONMAP die benötigten Flora_xxxxxx-Readings auf temperature, battery, etc. und für die nicht benötigten Sensoren alles auf 0.

Zusätzlich habe ich noch 2 readingsChange's definiert, die die unnützen Nachkommastellen für Fertility und Moisture entfernen:
defmod rcFloraFertility readingsChange Flora.* fertility (\d+\.\d+) {sprintf("%d us\/cm", $1)}
defmod rcFloraMoisture readingsChange Flora.* moisture (\d+\.\d+) {sprintf("%d", $1)}


Das funktioniert zwar, ist aber bestimmt nicht der beste Weg, dies zu lösen... Vor allem die Pflege ist so sehr unübersichtlich (einen neuen Sensor muss man bei allen anderen Sensoren auf die Ausschlussliste setzen, und das mit 5 Readings...).

Hat jemand eine Idee, wie man das besser lösen kann?

Ach ja, wer es selbst ausprobieren will, in Tasmota 8.3.1 scheint noch ein Bug zu sein, da waren bei mir die Readings für Moisture und Fertility immer 0.00000000. In der Nightly-8.4.0 (bei mir vom 2020-07-11) war es für den ESP32 behoben, in der Version für den ESP8266 war der Fehler noch drin... Mehr Details zu Tasmota und Bluetooth gibt es unter https://tasmota.github.io/docs/Bluetooth/.

Gruß,
Michael


Beta-User

#1
Interessant, mit was sich Tasmota nicht neuerdings alles beschäftigt...

Also: Du könntest in jedem "Einzeldevice" die Payload analysieren und dann jeweils nur den zu einem Sensor gehörenden Datensatz an json2NameValue() übergeben, als regex sollte z.B. Flora-66b349.{[^}]+})passen (das ganze ähnlich wie tasmota_ir, aber statt $EVENT nur $1 an json2NameValue() übergeben).

Aber: Irgendwie ist diese ganze Konstruktion m.E. "suboptimal" und kommt mir insgesamt noch nicht durchdacht vor:
- Woher weiß man, wann welcher Sensor tatsächlich das letzte Mal gesendet hat? Es scheint immer "alles auf einmal" zu kommen...
- Na ja, die Topic-Struktur könnte auch so gestrickt werden, dass pro Sensor ein eigener Topic-Branch verwendet wird. So ist das vermutlich nicht nur für FHEM ein unübersichtlicher und schlecht zu sortierender Datenwust...  (das gilt sinngemäß auch für tasmota2zigbee)

EDIT: für z2t habe ich was interessantes gefunden: SetOption89. Scheint es für BT (noch) nicht zu geben; vielleicht könnte/sollte man das ja via github anregen?
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

OppiM

Hi,

ich bekomm die Syntax nicht so recht zusammen.

Hiermit bekomme ich ein Reading, aber der JSON wird nicht aufgelöst (was immerhin zeigt, das die Regex stimmen sollte...):
ESP32_01:tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:({[^}]+}), ? {"$1"=>$1} : { json2nameValue($1,'',$JSONMAP) } }

Reading:
__Temperature__29.9__Illuminance__13700__Moisture__0.000000__Fertility__446.000000__Battery__100__Firmware___3.2.2__ {"Temperature":29.9,"Illuminance":13700,"Moisture":0.000000,"Fertility":446.000000,"Battery":100,"Firmware":"3.2.2"}

Plus Perl warnings:
2020.07.14 13:23:26 1: PERL WARNING: Unescaped left brace in regex is deprecated here (and will be fatal in Perl 5.32), passed through in regex; marked by <-- HERE in m/Flora-666c1a.:({ <-- HERE [^}]+})/ at (eval 93655) line 1.
2020.07.14 13:23:26 3: eval: my $CID=   $evalSpecials->{'%CID'};my $DEVICETOPIC=   $evalSpecials->{'%DEVICETOPIC'};my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $JSONMAP=   $evalSpecials->{'%JSONMAP'};my $NAME=   $evalSpecials->{'%NAME'};my $TOPIC=   $evalSpecials->{'%TOPIC'};{ $EVENT =~ m,Flora-666c1a.:({[^}]+}), ? {"$1"=>$1} : { json2nameValue($1,'',$JSONMAP) } }


Hiermit passiert gar nichts:
ESP32_01:tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:({[^}]+}), ? { json2nameValue($1,'',$JSONMAP) } : undef }

Und das wird mit einem Fehler nicht akzeptiert:
ESP32_01:tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:({[^}]+}), { json2nameValue($1,'',$JSONMAP)} }

Fehlermeldung:
syntax error at (eval 93821) line 1, near "m,Flora-666c1a.:({[^}]+}), { "
syntax error at (eval 93821) line 1, near "}}"



Das mit dem SetOption89 sieht interessant aus, analog zu
tele/Zigbee/5ADF/SENSOR
sollte dann etwas wie
tele/Bluetooth/Flora-666c1a/SENSOR
gesendet werden? Und dann auch nur, wenn neue Daten vom Sensor empfangen wurden.

Mal sehen, ob ich das bei Tasmota anregen kann. Sollte ja eigentlich kein großer Aufwand sein, die Logik ist ja durch SetOption89 schon vorhanden.

Gruß,
Michael

Beta-User

Hmm, irgendwie war es naheliegend, dass die geschweiften Klammern Ärger machen. Versuch's mal mit:
tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? { json2nameValue($1,'',$JSONMAP) } : undef }

Bzgl. SetOption89:
Genau so hatte ich das verstanden; vielleicht testest du das mal aus? Könnte nämlich sein, dass da die Doku "hinterher" ist (ist aber nur ein diffuses, durch nichts zu rechtfertigendes Bauchgefühl, dass da eine sehr kleine Chance bestehen könnte)...
(Wenn das klappt, würde ich mir das vermutlich auch mal näher ansehen, ich habe noch ein paar LYWSD03MMC hier rumfliegen und warte drauf, dass die irgendwann mit OpenMQTTGateway ans fliegen kommen. Noch "spassiger" wäre die Sache, wenn man BT-Commands (wie mit gattool) versenden könnte; dann gingen darüber nämlich vermutlich auch BT-Thermostate von eQ-3).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

OppiM

Hi,

hat leider auch nicht funktioniert. Es werden keine Readings angelegt und im Log steht:
2020.07.14 14:28:26 4: MQTT2_DEVICE_Parse: Flora_666C1A_neu tele/ESP32_01/SENSOR => { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? { json2nameValue($1,'',$JSONMAP) } : undef }
2020.07.14 14:28:26 1: PERL WARNING: Odd number of elements in anonymous hash at (eval 95295) line 1.
2020.07.14 14:28:26 3: eval: my $CID=   $evalSpecials->{'%CID'};my $DEVICETOPIC=   $evalSpecials->{'%DEVICETOPIC'};my $EVENT=   $evalSpecials->{'%EVENT'};my $EVTPART0=   $evalSpecials->{'%EVTPART0'};my $JSONMAP=   $evalSpecials->{'%JSONMAP'};my $NAME=   $evalSpecials->{'%NAME'};my $TOPIC=   $evalSpecials->{'%TOPIC'};{ $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? { json2nameValue($1,'',$JSONMAP) } : undef }


SetOption89 macht derzeit leider keinen Unterschied:
14:12:04 MQT: tele/ESP32_02/SENSOR = {"Time":"2020-07-14T14:12:04","Flora-66b356":{"Temperature":28.1,"Illuminance":85574,"Moisture":58.000000,"Fertility":234.000000},"Flora-66ace7":{"Temperature":25.8,"Illuminance":8504,"Moisture":39.000000,"Fertility":238.000000},"Flora-666c1a":{"Temperature":29.3,"Illuminance":33773,"Moisture":0.000000,"Fertility":466.000000},"Flora-66b302":{"Temperature":26.2,"Illuminance":16,"Moisture":0.000000,"Fertility":0.000000},"TempUnit":"C"}
14:15:23 CMD: setoption89
14:15:23 MQT: stat/ESP32_02/RESULT = {"SetOption89":"OFF"}
14:15:37 CMD: setoption89 1
14:15:37 MQT: stat/ESP32_02/RESULT = {"SetOption89":"ON"}
14:17:04 MQT: tele/ESP32_02/SENSOR = {"Time":"2020-07-14T14:17:04","Flora-66b356":{"Temperature":30.0,"Illuminance":85574,"Moisture":58.000000,"Fertility":224.000000},"Flora-66ace7":{"Temperature":26.5,"Illuminance":8806,"Moisture":39.000000,"Fertility":238.000000},"Flora-666c1a":{"Temperature":30.0,"Illuminance":29137,"Moisture":0.000000,"Fertility":460.000000},"Flora-66b302":{"Temperature":26.2,"Illuminance":16,"Moisture":0.000000,"Fertility":0.000000},"TempUnit":"C"}


Gruß,
Michael

Beta-User

#5
Ähm, eine Klammer ist in jedem Fall noch zu viel drin, die könnte hinderlich sein:
tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }Sonst wird es langsam schwierig, dann müssen wir uns was ausdenken, was man statt "[^}]+" noch an Notationsmöglichkeiten hätte...

EDIT: Schade, dass es mit SetOption89 (noch) nicht zu klappen scheint. Danke für den Test!

EDIT 2:
(Da war oben noch ein Fehler drin...)
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

OppiM

#6
Hi,

das war es (fast...).

So geht es jetzt:
defmod Flora_666C1A MQTT2_DEVICE ESP32_01
attr Flora_666C1A DbLogExclude .*
attr Flora_666C1A IODev m2s
attr Flora_666C1A event-on-change-reading .*
attr Flora_666C1A jsonMap Temperature:temperature\
Battery:batteryPercent\
Fertility:fertility\
Illuminance:lux\
Moisture:moisture\
Firmware:firmware
attr Flora_666C1A readingList tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }\
tele/ESP32_02/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }\
tele/ESP32_03/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }
attr Flora_666C1A room FlowerCare
attr Flora_666C1A stateFormat T: temperature°C, M: moisture%, L: lux, F: fertility, B: batteryPercent%


Das ist schon deutlich übersichtlicher und leichter zu pflegen als mein Ansatz!

Danke für die Hilfe,
Michael

P.S.: Bzgl. SetOption89 hab ich einen Request aufgemacht https://github.com/arendst/Tasmota/issues/8902

Beta-User

 :)

Zwei Anmerkungen noch:
- Der dreifache Eintrag in readingList dürfte nicht erforderlich sein (ist ein Rest aus der Testerei, oder?).
- Das jsonMapping für Battery sollte besser batteryPercent sein, oder? (Das ist ein "verabredeter" Readingname) (OT: kommt denn da was sinnvolles? Auf der Tasmota-Seite waren mehrere Hinweise auf firmware-bugs...).
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

OppiM

Zitat von: Beta-User am 14 Juli 2020, 15:36:48
- Der dreifache Eintrag in readingList dürfte nicht erforderlich sein (ist ein Rest aus der Testerei, oder?).

Da ich 3 ESP32 zum Datensammeln einsetzte, muss ich (solange es nicht den SetOption89-Weg mit tele/Bluetooth/Flora-666c1a/SENSOR gibt) doch von jedem das SENSOR-Topic auswerten:
tele/ESP32_01/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }
tele/ESP32_02/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }
tele/ESP32_03/SENSOR:.* { $EVENT =~ m,Flora-666c1a.:(.[^}]+.), ? json2nameValue($1,'',$JSONMAP) : undef }

Zitat
- Das jsonMapping für Battery sollte besser batteryPercent sein, oder? (Das ist ein "verabredeter" Readingname) (OT: kommt denn da was sinnvolles? Auf der Tasmota-Seite waren mehrere Hinweise auf firmware-bugs...).

Stimmt, hab ich abgeändert. Bei mir stimmen die gesammelten Werte mit den Werten aus der FlowerCare-App überein. Und nicht alle stehen auf 100%.

Gruß,
Michael


Beta-User

Argh, das hatte ich übersehen. Kann man mit Wildcard lösen, hier gleich noch ein readingList-Vorschlag für eine Art "Sammeldevice", in dem dann nur die Sensornamen gelistet werden:
tele/ESP32_../SENSOR:.* { my @ret; while ($EVENT =~ m/"([^"]+)":[{]/g) { push @ret, $1; }; return {'sensorList'=>join',', @ret}; }
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Beta-User

Hatte erst gedacht, ich schau mal, ob sich das schon geschickt vertemplaten läßt und dabei gesehen, dass der Vorschlag auf github mit SetOption89 "in der Mache" zu sein scheint; macht vermutlich Sinn, da noch etwas zuzuwarten...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files