File Notification Component: Any way to dynamically create file name?

I found that this was asked before, but I don’t see an answer. Rather than dredge up a 10-month-old post, I’ll start a new one. I hope that’s proper forum etiquette.

I have an automation which saves information to a file using the file notification component:

notify:
  - platform: file
    name: burnerlog
    filename: burnerlog.txt
    timestamp: True

It works great, but I’d like to start a new file, say, monthly. Then I could occasionally off-load and archive the old data for future analysis, without taxing the storage on my HA system or creating a huge file.

Ideally, I’d like the file name to be “burnerlog_YYMM,” with YY and MM being the curreent year and month.

I’d also like to do it all in HA, since my UNIX skills are still somewhat weak and this is a clean OS with no custom chron jobs or bash scripts.

Any suggestions would be appreciated!

Seems you could just add the jinja templating to your filename?

I tried that:

  - platform: file
    name: testfile
    filename: testfile_{{ now().day }}.txt
    timestamp: True

And now I have a file named “testfile_{{ now().day }}.txt”

Maybe my syntax is wrong?

should it be:
"testfile_"{{ now().day }}".txt"

I’m not sure if it is possible. I use Node-Red for all my automations and notifications so I’m not much help, just thought you could inject jinja into the configuration.

That didn’t seem to work either:

Error loading /config/configuration.yaml: while parsing a block mapping in “/config/configuration.yaml”, line 158, column 5 expected <block end>, but found ‘{’ in “/config/configuration.yaml”, line 160, column 26

Line 158 is this one: " - platform: file".
Seems like it doesn’t like the quotes on the file name line (160.)

Sorry, I’m not sure then.

Try this:

"testfile_’{{ now().day }}’.txt"

Note they are the wrong sort of single quotes but I’m on my mobile and that’s all I have available.

You get the idea though. Single quotes inside double quotes. Otherwise your first set of double quotes only encloses “testfile”

1 Like

I had thought of that originally. Thanks for confirming I was on the right track.

No luck. The file it creates is named testfile_‘{{ now().day }}’.txt.

(Yes, I used proper single quotes.)

Just had a look at the docs. The filename is a string only (no templates).

1 Like

What if you keep the filename the same but you run an automation with a command line or a script that renames (mv) the file at the end of the month?

2 Likes

You beat me to it. I was just logging on to post what I ended up doing.

In my OP I showed the automation which creates the “burner log” file. This automation creates one entry (line in the file) every time the burner on my heating system comes on (fires) or goes off. Obviously, at some point this data has be be cleaned up. I don’t want to lose it, but I don’t want an enormous file building up month after month, either.

Ideally, each month should start a new file. But the file notification component can’t dynamically set the file name based on the current month. So instead I went with the Shell Command service to use the UNIX “mv” (move) command to rename it. (Unix doesn’t have a “rename file” command.)

# Shell Command Service to rename a file
shell_command:
  rename_burner_log: "mv -n burnerlog.txt {{ (as_timestamp(now()) - (60*60*24*27)) | timestamp_custom('burnerlog_%y_%m.txt') }}"

The mv command takes the switch “-n” which indicates not to move anything if the target exists.

Next are the two parameters, the “from” and “to” file names.

“From” is easy: burnerlog.txt.

“To” is a template:

{{ (as_timestamp(now()) - (60*60*24*27)) | timestamp_custom('burnerlog_%y_%m.txt') }}

First, the current time “now()” is converted from a string to a timestamp.

Next we calculate how many seconds there are in 27 days, and subtract that from the timestamp for “now.” This ensures the new timestamp is always in the previous month.

That new timestamp is piped (“|”) to timestamp_custom, which produces a string formatted as the literal “burnerlog_” followed by the current year, another “_,” the current month, and the file extension “.txt.”

Thus, since I’m writing this in April, my burnerlog.txt is renamed to burnerlog_19_3.txt.

Because of the “-n” switch, this can be run multiple times without worrying that a whole month’s worth of data will be wiped out.

Now all I have to do is trigger the service on the first of every month. Automations have a great “time” platform which lets you trigger an automation based on time of day. But I haven’t found anything which lets you trigger based on day of the month. So I came up with this:

- id: id_burner_rename
  alias: run_burner_rename
  trigger:
  - at: '00:01:00'
    platform: time
  condition:
    - condition: template
      value_template: "{{ now().day == 1 }}"
  action:
    service: shell_command.rename_burner_log

At 12:01 AM local time, every day, this automation is triggered. But the action only takes place if the condition is “true.” The condition looks to see if the day-of-month is currently “1”.

So on the first of every month, the “mv” command is issued and the file gets renamed.

It would be possible to schedule more time platform triggers in this one automation, in case HA is not running at midnight for some reason, or to schedule other automations for other days, in case it’s not running at all on the 1st. But presumably I’ll be checking in on things at least once a month, and I can always manually rename and/or edit the file, as needed.

3 Likes

I’m not sure what information you’re storing in your file, but if it’s just simple “on” and “off” state… why not map that to an, e.g, input_boolean entity? Then you can use the Home Assistant database to store it, or probably much more usefully, have that entity state stored in influxdb. Then you can use database techniques to manage the longevity as well as making queries against it to figure stuff out.

I have my well pump connected to my Elk alarm system, and that exposes the (non-alarm) zone as a sensor that get pushed into influxdb. Using grafana I can visualize how often the pump cycles on and off… just because I can!

Shows power measurements on the branch circuit to the well pump, and then a “discrete values” panel showing the state of the sensor connected to the dry relay contacts in the well pump controller. Hey, they pretty much line up like they should!

Or you can just make queries against the database directly

> select time,state from "sensor.zone017" limit 20;
name: sensor.zone017
time				state
----				-----
2019-01-05T17:18:32.730333952Z	Normal
2019-01-05T17:27:17.3221568Z	Violated
2019-01-05T17:27:43.818833152Z	Normal
2019-01-05T17:32:57.198503936Z	Violated
2019-01-05T17:33:21.963481856Z	Normal
2019-01-05T17:36:48.693284096Z	Violated
2019-01-05T17:37:57.365732864Z	Normal
2019-01-05T17:44:29.761414912Z	Violated
2019-01-05T17:44:30.980856064Z	Normal
2019-01-05T17:46:47.316454912Z	Violated
2019-01-05T17:46:52.90874496Z	Normal
2019-01-05T17:48:59.113383936Z	Violated
2019-01-05T17:54:01.540448Z	Normal
2019-01-05T17:58:53.461487104Z	Violated
2019-01-05T17:59:18.811291904Z	Normal
2019-01-05T18:06:32.924207872Z	Violated
2019-01-05T18:12:14.920012032Z	Normal
2019-01-05T18:16:23.799037952Z	Violated
2019-01-05T18:16:47.364993024Z	Normal
2019-01-05T18:35:54.689313024Z	Violated

Just a thought!

Your idea of monitoring the furnace run time is a good one; I suppose I can indirectly measure that with temperature sensors in the duct, but getting a direct indication via the thermostat control signal might be nice to add.

1 Like

I like what you’ve done with the pump data. Maybe some day. For now I’m more interested in getting it out of HA where I can do some analysis in Excel or whatever, using other data like degree-days and oil delivery amounts.

I went straight to the burner on my oil boiler. I don’t really have good thermostat data, since I’m using Honeywell WiFi stats which limit my ability to access them to about once every three minutes. Plus the burner only fires based on the temperature in the boiler, so it’s not directly related to thermostats calling for heat. That relationship is one of the things I’d like to learn more about. Next hardware project is to wire up a bunch of relays to give me on/off data for each zone valve and the air conditioner.

Had I been asked to elaborate on my idea, this is exactly how I would have written it up - word for word.

Just kidding, of course - maybe you want to change {{ now().month == 1 }} to {{ now().day == 1 }}
But thanks for the detailed write-up, very helpful
I have a sensor that counts how many times my sump pump runs every day and I pipe it into a csv-file at the end of the day.
I might steal some of your ideas and split the file by month.

It’s definitely not worth the effort of setting up a whole separate long-term database doohickey just for that one value that I want to track longer term - and I’m totally fine my RPi3-powered HA only keeping data for 3 days.

1 Like

Ooooo, good catch! Of course I did mean now().day! Unfortunately it allowed me to go back and edit where I’d posted it incorrectly, so nobody will know what you’re talking about :wink:

I promised myself I wouldn’t do the thing which frustrated me so much at first; find a solution but not fully explain it so a newbie could follow along. Thanks for noticing!

1 Like

It works! This morning (May 1st) at 12:01 AM the automation ran and renamed the file to “burnerlog_19_04.txt.”

All the pieces are in place; I get a log file entry every time the burner fires, and again when it stops firing. That log file builds up over the course of a month, then this automation renames it to append the year and month. This can go on almost forever without impacting performance or making the file sizes too unwieldy.

The process started with the hardware to get those on and off signals, explained here.

I also use the history_stats platform to summarize daily total burner “on” time:

  - platform: history_stats
    name: Burner on yesterday
    entity_id: binary_sensor.visonic_mct_340_e_0b1243b6_1_1280
    state: 'on'
    type: time
    end: '{{ now().replace(hour=0).replace(minute=0).replace(second=0) }}'
    duration:
      hours: 24

Another automation add this value to a file every day at 01:00. That file will take a while to grow too big, so I can deal with that manually.

I’ll be able to analyze both of these data sets to determine my boiler performance and fuel usage.