#```
1 messages Β· Page 1 of 1 (latest)
Ok... so just to make sure I understand, I would create a new sensor with this as a template?
Make a template sensor
Ok That I can figure out, I have a lot of example on this.
Thanks so much!! I'll let you know
This is what I've done. I must missing just something simple I guess....
- name: 3d_printer_thumbnails_path
unique_id: "293988e9be-c910-4634-8205-38d53170d5a7"
state: '{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = states('sensor.3d_printer_object_thumbnails') %}
{{ [dir.split('/')[0], img] | join('/') }}'
attributes:
friendly_name: "Object Thumbnails Final"
icon: mdi:image
but I'm getting an error "can not read a block mapping entry; a multiline key many not be an implicit key
No you have to use multiline notation
state: >
{% ....
Ok figured it out, thanks so much..
- name: 3d_printer_thumbnails_path
unique_id: "192.168.168.293988e9be-c910-4634-8205-38d53170d5a7"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = states('sensor.3d_printer_object_thumbnails') %}
{{ [dir.split('/')[0], img] | join('/') }}
attributes:
friendly_name: "Object Thumbnails Final"
icon: mdi:image
Hi
Hi
Does it let you edit your email comments on github?
Let me check
I just did not sure I did the right thing though. didn't have any preview
I think because it was originally through email it just keeps it br0ken π¦
(code tags)
I add another comment and make it right this time
Add the |urlencode fix as well
and for the current_layer and total_layer would you have a clue on how to extract the value from the print_stats query?
I tested the directory thing first with out the + in the file name and I was like what it's working fine... then I realized I already uploaded that stl so it already had a copy of the image in the main .thumbs folder for it and was just loading that one π
I've tried to based it on other sensors in the yaml file but nothing worked.
yes
Quite sure we could make the thumbnail one only one sensor not two like I did.
Can you explain more about it though where are you seeing it not update these values or it's just not accurate?
Yes that would be good.
In my picture in the readme I believe it's showing these values? https://user-images.githubusercontent.com/1906575/215313907-ba5221d9-6ccb-47f4-8656-ffac2d450bb8.png
In the one you have in the moonraker file, the current_layer is computed from the z height and the object_height and the layer_height where as with the gcode in the slicer sending the layer number at each layer change then the print_stats do have the exact layer number without needing any computation.
{"result": {"eventtime": 88572.403989076, "status": {"print_stats": {"filename": "Mobius/Mobius Extruder_Accent-Anycubic Mega X-Sparta 3D ABS+.gcode", "total_duration": 5227.189836756006, "print_duration": 3783.9447762640048, "filament_used": 5007.582759999996, "state": "printing", "message": "", "info": {"total_layer": 109, "current_layer": 12}}}}}
usually these values are null hence your check for unknow or unavailable
To populate those as I explained you need to add one Gcode in the start-gcode and one in the before each layer gcode in the printer settings
Ok I understand now lets try it give me a moment while I add that to SuperSlicer
I've tried this with no luck
- name: 3d_printer_current_layer
unique_id: "192.168.168.296a77acc1-8134-4354-b2f6-390adab81993"
state: '{{ states.printer_3d_layers.attributes["print_stats"]["info"][2] }}'
icon: mdi:counter
attributes:
friendly_name: "Current Layer"
For SS
Start
SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]
and before layer change:
SET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num]
Did you try to add those in your printer.cfg?
no because the SET_PRINT_STATS_INFO CURRENT_LAYER=[layer_num] get's inserted in the gcode file at each layer change. That wouldn't work in the printer.cfg. Maybe the total_layer count would but not the other
ok
Do you get values here before the print starts?
"info": {"total_layer": null, "current_layer": null}
You mean once you launched the print but before it actually reads the file or while the printer is idling
While it's warming up
If I recall, you should have the total_layer if I recall. I have a print running now so hard for me test..
Have you checked if the gcode file has the inserted tags
What is the gcode for it?
You should see this in the gcode file
M73 P0 R26
;TYPE:Custom
M104 S0 ; Stops PS/SS from sending temp waits separately
M140 S0
SET_PRINT_STATS_INFO TOTAL_LAYER=50
START_PRINT BED=105 HOTEND=245 CHAMBER=46 FILAMENT=ABS
M107
G21 ; set units to millimeters
G90 ; use absolute coordinates
M82 ; use absolute distances for extrusion
G92 E0
; Filament gcode
SET_PRESSURE_ADVANCE extruder=extruder advance=0.45
;_TOOLCHANGE 0
M107
;LAYER_CHANGE
;Z:0.25
;HEIGHT:0.25
;BEFORE_LAYER_CHANGE
SET_PRINT_STATS_INFO CURRENT_LAYER=0
TIMELAPSE_TAKE_FRAME
;0.25
G1 E-6 F3000
M73 P1 R26
G1 Z0.25 F10800
;AFTER_LAYER_CHANGE
;0.25
M104 S245 ; set temperature
G92 E0
G1 Z0.4
and so on at each layer change...
Ok so it's working... but I see that it won't show the values until after heating up
M107
M190 S55 ; set bed temperature and wait for it to be reached
M104 S215 ; set temperature
;TYPE:Custom
SET_PRINT_STATS_INFO TOTAL_LAYER=33
I'll modify that for now.
ok well depends where you put it in your GCode Start. Mine goes like this:
M104 S0 ; Stops PS/SS from sending temp waits separately
M140 S0
SET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]
START_PRINT BED=[first_layer_bed_temperature] HOTEND={first_layer_temperature[initial_extruder]+extruder_temperature_offset[initial_extruder]} CHAMBER=[chamber_temperature] FILAMENT={filament_type[1]}
so before actually starting the macro
My gcode file then shows:
M73 P0 R26
;TYPE:Custom
M104 S0 ; Stops PS/SS from sending temp waits separately
M140 S0
SET_PRINT_STATS_INFO TOTAL_LAYER=50
START_PRINT BED=105 HOTEND=245 CHAMBER=46 FILAMENT=ABS
M107
G21 ; set units to millimeters
G90 ; use absolute coordinates
M82 ; use absolute distances for extrusion
do you have multiple "CURRENT_LAYER" throughout the file or only at the end?
Where did you put it. you have to put it in the third section: Before layer change GCode
Ah yes that is where I went wrong.
Yay!
"info": {"total_layer": 26, "current_layer": 0}
Ok now lets check out home assistant
I added SET_PRINT_STATS_INFO CURRENT_LAYER=0 after TOTAL_LAYER is set in the start.
Cool!! I have a few for you after this one! π
I'm really curious to see how, I've tried some many ways. Sure it's something stupid I didn't do...
Just curious, Is it a Trident or a V0.1?
Well not sure what time zone you are but I'm on EDT and was up pretty early this morning. I'll catchup tomorrow .
V0.1 you?
Same
I would like to animate the icon of the layers but that's a lot of CSS for now.
I have all my parts printed for my Voron 2.4r2 which I will order Monday! Right now a highly modified Anycubic Mega X
Very nice! Hopefully they don't release r3 a week later like they did with the v0.2 to me haha π
At some point, we'd always be in a waiting state!!! If so it give me one more reason to upgrade it!
Did you test if that code works multiple directories deep?
No I havent
Hard to compute how every user is going to break something π
Will you be adding the details about the Start Gcode and before layer gcode in the Readme?
Oh yeah...
Yes
Whenever you need someone to test any of that stuff, let me know... I enjoy doing this...
Maybe @unborn void knows how to make it work with multiple directories deep? {{ [dir.split('/')[0], img] | join('/') }}
- name: 3d_printer_object_thumbnails_path
unique_id: "192.168.168.293988e9be-c910-4634-8205-38d53170d5a6"
state: '{{ states.sensor.printer_3d_file_metadata.attributes["thumbnails"][1]["relative_path"] }}'
attributes:
friendly_name: "Object Thumbnails Path"
- name: 3d_printer_thumbnail
unique_id: "192.168.168.293988e9be-c910-4634-8205-38d53170d5a7"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = states('sensor.3d_printer_object_thumbnails_path') %}
{{ [dir.split('/')[0], img] | join('/') }}
attributes:
friendly_name: "Object Thumbnail"
icon: mdi:image
look up how to slice lists
it depends on how many you have and what you want to trim, so every case will be different
What if its random amount for whatever the crazy user does?
e.g. dir.split('/')[0] just gives the first directory. dir.split('/')[-1] gives last. Random will not work because you need to know the actual number.
no direct, 1 directory, 1000 directories deep etc
if you want everything before the last... dir.split('/')[:-1]
There you go!! π
everything after the first dir.split('/')[1:]
I guess it would be everything before the last!!
Yes thank you very much!
Thanks
I guess we just need to change it to [:-1] instead of [0] and this should do the job
Lets hope so just wondering what it will do with no directory deep.
Hum, right... easy to test though it worked when it wasn't in a subdirectory.
Strange enough the Mainsail integration doesn't publish the current layer...!!
?
There is a mainsail integration already in HA
What else were you thinking?
I believe so, trying to trace it back.... Though when I click on documentation I get a 404 but looking in my custom-components, it comes from "cmroche" https://github.com/cmroche/OctoPrint-HomeAssistant
Probably the first one I installed and then I found one for Moonraker.
I had issues with Filament but it's working now !!! I was also trying to narrow down the ETA but I think your method is quite close. I was just wondering if you were taking into account the warmup time but I think you are
You have narrowed down pretty much everything... Great job!
Well if you think of anything toss it in the discussion or issue tracker on github. We can work on it hopefully. Thanks for your help. Just going to poke at the directory stuff then commit it.
Will do. Thanks again!!
@violet iron just launched a print and modified the thumbnail sensor with [:-1] . Seems to work but... the returned path is : ['Voron']/.thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+-400x300.png so not sure if it works or not because usually it caches the last path
I would say it doesn't. I don't see how the path would be valid with these characters
Ok I don't know why but my ETA seem to be in UTC time and not my localtime zone
I have yet to figure out how to get the RPi MainsailOS out of UTC mode my KlipperScreen shows UTC as well. I tried to do raspi-config on the terminal to change the TimeZone but I think it said it was missing files and couldn't change it. Have yet to look at it again.
Well on my raspi I've got the right timezone but not in HA. And I can confirm that replacing [0] with [:-1] screws up the path and doesn't work.
Question, why adding 2 hours to the as_timestamp(now)
state: '{{ (as_timestamp(now())**+2*60*60**+((states.sensor.printer_3d_sensor.attributes["print_stats"]["print_duration"]/states.sensor.printer_3d_sensor.attributes["display_status"]["progress"]- states.sensor.printer_3d_sensor.attributes["print_stats"]["print_duration"]) if states.sensor.printer_3d_sensor.attributes["display_status"]["progress"]>0 else 0)) | timestamp_custom("%H:%M:%S", 0)}}'
so even by adding the right timezone to /etc/timezone it doesn't work?
pi@mainsail:~ $ cat /etc/timezone
America/Montreal
Just got this working
- name: 3d_printer_object_thumbnails
unique_id: "IP59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = states.sensor.printer_3d_file_metadata.attributes["thumbnails"][2]["relative_path"] %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
Yes it shows the correct timezone there but KlipperScreen is still in UTC
I think KlipperScreen may ignore locals
Maybe the same is true for moonraker
commit uploaded to github hopefully I didn't forget anything.
well still have to update the readme
Nice let me replace mine...
All good. I think I found the way to convert to my timezone in HA for the ETA. It now displays the right ETA. In the timestamp_custom, changed 0 for 5. Not sure why 5 and not -5 but it works...
- name: 3d_printer_eta
unique_id: "<moonraker-ip-address>a2b57068-9a32-4d2c-8cc9-57d2389a9082"
state: '{{ (as_timestamp(now())+((states.sensor.printer_3d_sensor.attributes["print_stats"]["print_duration"]/states.sensor.printer_3d_sensor.attributes["display_status"]["progress"]- states.sensor.printer_3d_sensor.attributes["print_stats"]["print_duration"]) if states.sensor.printer_3d_sensor.attributes["display_status"]["progress"]>0 else 0)) | timestamp_custom("%H:%M:%S", 5)}}'
availability: >
{% set items = ['sensor.printer_3d_sensor'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:av-timer
attributes:
friendly_name: "ETA"
So just change the 0 to a 5 on the end of timestamp_custom?
yep
and I confirmed as I reverted to 0 and it went back to UTC time
oh and I removed the 2*60*60 right after the as_timestamp(now)
Good stuff why does that need to be removed? as_timestamp(now())+2*60*60+
Well was it there, it was adding 2 hours to time(now)
Could be if it wasn't you, the original developer was in UTC+2 zone
So basically they didn't know how to properly set the timezone at the end?
Most probably but I'm puzzled why 5 and not -5?? I'll try to dig why. I hate doing things and not understanding the logic
Haha yeah that's why I ask we are one in the same brute force and perseverance coding/discovery...
I found this | timestamp_local()
Maybe it will take from the system?
You want to avoid hardcoding if plausible
So here is an explanation from Petro on a thread I found.
{{ (now().strftime("%s") | int + (15*60)) | timestamp_custom("%H:%M", false) }}
Without the false, itβs based on unix_time not local time. Iβm guessing your timezone is +1? If not, youβre time is screwed up on your system and you need to make sure your OS time is set properly and your timezone is set properly in your config.
Strange a enough if I put False I get a wrong time but if I make it True I get the right time. I've checked and my HA Timezone is well set. So it worked with 5 because it was not "0" so declared True I guess
Maybe mention in the ReadMe that adding the GCode is valid for PrusaSlicer or SuperSlicer. Cura has a different way of doing this and the variables might be different.
My two cents... π
So should all these |timestamp_custom("%H:%M:%S", 0) => |timestamp_custom("%H:%M:%S", 1) ?
1 being true
no because the first one is actually a calculation of duration not a time per say
I thought the ETA was just how many hours it thinks it will take not what time it was going to finish at?
ETA is at what time it should finish and Time Remaining is the amount of time it thinks it take to complete the job
Just like planes!! LOL
And time remaining doesn't have a as_timestamp(now() at the start
I changed it to 1 and removed the math at the start
committed!
1 did the same as 5 as you discovered.
Do you have KlipperScreen?
Added the Prusa/Super to the readme
Yeah could have been True which, for me at least shows that it's not a number adding hours, but both works.
As for Klipper screen not yet but I will be testing it this afternoon on another RaspI I have on which I want to install Klipper and Klipper Screen I can report when I've done it if you want.
Ok thank you
@violet iron Just checking, are you sure the modified ObjectThumbnail sensor works? Were you checking the state of the sensor or the fact that you'd see the thumbnail in the custom-card?
I've just restarted my HA and the thumbnails is not displaying...
why are you using timestamps whne you can use timedeltas
now() + timedelta(minutes=15)
I believe this is code that @violet iron pulled from another project and he added some other features in the moonraker.yaml but those were already there I think . This is for our 3D printer HA dashboard. It calculates the remaining time and the ETA for the print to complete.
yeah but it just is over complicated
and you're using the states object
which will have errors when you restart
Here is the whole code for the api we are using; https://github.com/NonaSuomy/Moonraker-Home-Assistant/blob/main/moonraker.yaml
I'm also not sure why you're dividing the duration by the progress
yeah, all those templates use the states object
if the templates start before the print entity, you'll have errors in your logs
and the templates won't be added to the system, keeping them unavailable
Me neither LOL just know for now that it's working. What isn't working is the new sensor for the thumbnail based on your help yesterday with the directory stuff
- name: 3d_printer_object_thumbnails
unique_id: "IP59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = states.sensor.printer_3d_file_metadata.attributes["thumbnails"][2]["relative_path"] %}
{{ (dir.split('/')[0] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
Ok I get it but I guess that would be in the case we restart HA or I'm getting this wrong?
use state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path
For that you have to figure out the path you want
based on what you explained, the code will work
if it's not what you explained, π€·ββοΈ
if the relative path has a . on it, you need to remove that as well
the relative path is as such: ".thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.png"
and the file path is: "Voron/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.gcode"
and the resulting sensor needs to be: "Voron/.thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.png"
then the code above is all you need
you can test this yourself
works with zero or the -1
{% set dir = "Voron/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.gcode" %}
{% set img = ".thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.png" %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
use the template editor to test things
:-1 is the laziest way to keep it relative and a list
ok but the filename changes everytime
that shouldn't matter
I'm showing you it working
with your current filename
so you replace that with whatever gets the filename and whatever gets the dir
ok so now this
{% set img = states.sensor.printer_3d_file_metadata.attributes["thumbnails"][2]["relative_path"] %}
would become
{% set img = state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path %}
yep
Thank you and sorry for being a noob in this.
keep in mind, that grabs the 3rd item in thumbnails
so you need to have 3 items in your list for that to always work
if you don't have 3, that will fail
Ok so like we were saying this morning, if say the file name would Voron/subdir/filename.gcode that wouldn't work?
The relative path is always .thumbs/filename.gcode whether its 1, 2 or more directory deep..
then you should be also parsing the image directory
if you just want to get the filename then you need to parse both
not just the dir
yeah but the API always returns .thumbs/image.png even if the file has 2,3 or more subdirectory in front of it. It's relative to the gcode file itself and not relative to the main directory.
Not sure why the moonraker API doesn't return the right path.
You have to provide other examples, becuase what your'e saying doesn't make sense to me
so show me an example of a situation you think that won't work and the expected path you want out of it
So here is the results which gives us the file being printed:
and this is the result:
{"result": {"eventtime": 35728.016348297, "status": {"heater_bed": {"temperature": 99.95, "target": 100.0, "power": 0.8324215370599557}, "extruder": {"temperature": 239.87, "target": 240.0, "power": 0.455732523486926, "can_extrude": true, "pressure_advance": 0.45, "smooth_time": 0.04}, "print_stats": {"filename": "Voron/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.gcode", "total_duration": 14117.065496281, "print_duration": 11561.703145902004, "filament_used": 11818.283110000018, "state": "printing", "message": "", "info": {"total_layer": 210, "current_layer": 19}}, "toolhead": {"homed_axes": "xyz", "axis_minimum": [-5.0, 0.0, -5.0, 0.0], "axis_maximum": [300.0, 300.0, 288.0, 0.0], "print_time": 35714.14340374245, "stalls": 0, "estimated_print_time": 35711.84534275, "extruder": "extruder", "position": [83.827, 212.408, 3.9972802385648096, 11818.283110000018], "max_velocity": 300.0, "max_accel": 1250.0, "max_accel_to_decel": 1900.0, "square_corner_velocity": 5.0}, "display_status": {"progress": 0.31, "message": "Printing..."}, "virtual_sdcard": {"file_path": "/home/pi/gcode_files/Voron/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.gcode", "progress": 0.3241902194042416, "is_active": true, "file_position": 7038205, "file_size": 21710109}, "gcode_move": {"speed_factor": 1.0, "speed": 4500.0, "extrude_factor": 1.0, "absolute_coordinates": true, "absolute_extrude": true, "homing_origin": [0.0, 0.0, -0.015, 0.0], "position": [83.827, 212.408, 4.035, 11818.283110000018], "gcode_position": [83.827, 212.408, 4.05, 5.269580000000133]}, "filament_switch_sensor Filament": {"filament_detected": true, "enabled": true}, "temperature_sensor Chamber_Temp\"": {}}}}
the other call is :http://192.168.168.29:7125/server/files/metadata?filename=Voron%2Fz_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS%2B.gcode
and the result is:
{"result": {"size": 21710109, "modified": 1675521154.495122, "uuid": "61093ce6-1e17-45b4-81d2-bdffd0dbc12a", "slicer": "SuperSlicer", "slicer_version": "2.5.59", "gcode_start_byte": 53496, "gcode_end_byte": 21694499, "layer_count": 210, "object_height": 42.2, "estimated_time": 34020, "nozzle_diameter": 0.4, "layer_height": 0.2, "first_layer_height": 0.25, "first_layer_extr_temp": 245.0, "first_layer_bed_temp": 105.0, "chamber_temp": 46.0, "filament_name": "Sparta 3D ABS+", "filament_type": "ABS", "filament_total": 35228.06, "filament_weight_total": 87.28, "thumbnails": [{"width": 32, "height": 32, "size": 848, "relative_path": ".thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+-32x32.png"}, {"width": 400, "height": 300, "size": 25575, "relative_path": ".thumbs/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+-400x300.png"}], "print_start_time": 1675521155.121734, "job_id": "0002C0", "filename": "Voron/z_motor_mount_a_x2-Anycubic Mega X-Sparta 3D ABS+.gcode"}}
so what I'm saying is that in the second call relative with always be with .thumbs/<filename> .png
even if the filename in the first call would be subdir1/subdir2/subdir3/<filename>.gcode
I still don't see what you're saying
are you using filename correctly when responding? Did you mean directory?
Just installed KlipperScreen and I have the right time on it...
those examples show that they would work with the previous code
Yes this works. I'm not saying it not. Basically what I'm wondering and as you mentioned I'll test in the developer tools template is if it would work if the gcode file would be deeper than one subdirectory. For now yes should work. I will test it in a minute
Ok the parsing of the filename works well if I use the developer templates with pasted filenames
Voron/dir1/dir2/.thumbs/filename.png
but seems the sensor is not getting the filename from this:
state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path
the state of the sensor is still unavailable..
if the sensor is unavailable, then you need to look at errors in your logs or your availability template
And a dumb question... How can I paste a clipped image in discord?
I tried just ctrl V but with no success.
Please use imgur or other image sharing web sites, and share the link here.
Image posting is blocked in most channels to discourage people from sharing text as images. Sharing text as images assumes that everybody sees the world as you do, which isn't the case. Some people are colour blind, or have visual impairment that means they can't make sense of an image of text.
OK this doesn't seem to return the relative path as it was before:
state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path
if your last result is the same as now, you only have 2 items in your thumbnail list
which is why I said it would break if you didn't have 3 items
the [2] grabs the 3rd item
there will always be only 2. one is 32x32 png file and the other one is a 400x300 png file
then you should be using [1] for the 2nd item
ok
All good! Thanks so much for your patience...
So what I understand is that through all these sensor, would be better to use the state_attr instead of the states object when we need to pull from the metadata?
Or was it just in this particular case
@violet iron Here is the final sensor template which with the great help of @unborn void π will pull the right path for the thumbnail even if it's deep down in a few subdirectories.
- name: 3d_printer_object_thumbnails
unique_id: "IP59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[1].relative_path %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
This is where all the data is being used
There should always be 3 items. 0 is 32x32 image, 1 is 64x64 image, 2 is 400x300 image. Weird that it generated only 2 for that instance.
Basically the quality of the thumbnail, and the software always generates 3 for each gcode file.
Why mine was still working is because I generated my picture entity from the yaml code which is getting depreciate so that is why it worked π
So good that you tried it.
the weird thing is why it works maybe from the friendly name or something.
as when I break that thumbnail code directory it still breaks the prior yaml defined picture box
even though it's not pointed at object_thumbnail and just thumbnail
It's weird that it never purges it even though it's commented out you can see here it is grabbing the state from object_thumbnails it itself is called 3d printer thumbnail and that is why it was still working for me π
#camera:
# Loading generic IP camera via configuration.yaml is deprecated.
# - platform: generic
# name: "3D Printer Thumbnail"
# still_image_url: http://IP:7125/server/files/gcodes/{{ states("sensor.3d_printer_object_thumbnails") }}
# verify_ssl: false
{"result": {"size": 860653, "modified": 1673834382.0390553, "uuid": "4a46a45a-86b9-437b-9192-798e5eeccf0d", "slicer": "SuperSlicer", "slicer_version": "2.4", "gcode_start_byte": 268511, "gcode_end_byte": 846262, "layer_count": 247, "object_height": 12.5, "estimated_time": 2743, "nozzle_diameter": 0.4, "layer_height": 0.05, "first_layer_height": 0.2, "first_layer_extr_temp": 215.0, "first_layer_bed_temp": 55.0, "chamber_temp": 15.0, "filament_name": "Basic PLA @VORON", "filament_type": "PLA", "filament_total": 341.64, "filament_weight_total": 1.02, "thumbnails": [{"width": 32, "height": 24, "size": 1647, "relative_path": ".thumbs/2_Skirt_Clip-32x32.png"}, {"width": 64, "height": 64, "size": 6338, "relative_path": ".thumbs/2_Skirt_Clip-64x64.png"}, {"width": 400, "height": 300, "size": 186843, "relative_path": ".thumbs/2_Skirt_Clip-400x300.png"}], "print_start_time": 1674811761.6515377, "job_id": "000058", "filename": "2_Skirt_Clip.gcode"}}
"thumbnails": [{"width": 32, "height": 24, "size": 1647, "relative_path": ".thumbs/2_Skirt_Clip-32x32.png"}, {"width": 64, "height": 64, "size": 6338, "relative_path": ".thumbs/2_Skirt_Clip-64x64.png"}, {"width": 400, "height": 300, "size": 186843, "relative_path": ".thumbs/2_Skirt_Clip-400x300.png"}],
Gotta love nonstandard all over the board things...
So that may need more tweaking and check for if the higher quality image is in spot [1] or [2]
@sleek sedge why did it not generate the 64x64 image in slot 1 for that print?
What slicer do you use?
Were you getting this error:
No image source configured
show_state: false
show_name: false
camera_view: auto
type: picture-entity
entity: sensor.3d_printer_object_thumbnails
Guess you have to manually add the IP camera to that url now without the yaml depreciation code
http://IP:7125/server/files/gcodes/{{ states("sensor.3d_printer_object_thumbnails") }}
Technically could we just add the http to the sensor to do away with the manual webui entry of the camera or you already figured out this?
I never got 3 thumbnails in any of the API calls I tested. I checked in the directory and all my files have only 2 thumbnails.
I use SuperSlicer and in the PrinterSettings on the General Tab in Thumbnails there is only 2 choices of size, not sure where you get the 3rd one
There is no way to copy/paste pictures in the chat beside using imgur?
all 3
Are you using current versions?
I was using 2.4 of superslicer and 2.6 of prusa
I'm using 2.5.59.2 but even with the previous versions I've always had only 2.
So why do I have 3 π
where do you set that 64x64 size
I never set it default settings.
Definitely different in 2.5 as you can see
That's Prusa 2.6
I was thinking 32 is the standard one that it always does from what you were showing in your screenshot
and those are the extra two it adds
I've set it to 32x32 and 400x300 in the Thumbnails section of the Printer Settings
I've never used Prusa Slicer as I'm kind of new ( less than a year) and went from Cura/Marlin to Klipper/Slicer pretty much 1 week after getting my printer...
I was wondering why the original screenshots from the other repos had crystal clear thumbs on [1] where mine were all grainy...
That would a good reason... π
That's when I saw that [1] for me was 64x64
Maybe time to upgrade to the 2.5 version!! π
You could run them in parallel in case it doesn't work out
Ah that could very well be if you were always using Prusa
Still where does 32x32 come from...
Hum are you saying that even by using SS you are getting a 32x32 generated?
I only upload from the slicer but I will check now that we see this weirdness.
I would have to think that it would also do it as all my files have 3 as I just started playing with prusa 2.6alpha3 for the organic support, Ruler, Text generation.
Wonder if it's mainsail/klipper/ generating the 32x32
That was exactly what I was typing when you sent it!!! LOL
I bet it is because it uses those 32x32 icons for the file list.
Ah maybe it generates it if it doesn't have it....
Try changing your settings to 32x32, 400x300 and see if it does generate an additional one.
Getting late.....
fingers not following my brain...
Before you go how were you adding the thumbnail to homeassistant?
I'm not going yet. got some calibration going on... π I'll paste some snapshots...
I'm using the MJPEG integration.
https://imgur.com/a/6dy7pPp
Dah.. sorry LOL brain fart!
I wish they standardize those two plugins into one.
MJPEG IP Camera / Generic Camera
I have to use Generic Camera as it's the only one with a rotation option (which should be added to mjpeg ip camera)
when you use the card-mod to rotate it then puts the caption text at the bottom upside down.
Ok using the Generic Camera for the thumbnail with this as the call http://192.168.168.29:7125/server/files/gcodes/{{ states("sensor.3d_printer_object_thumbnails") }}
yeah just had to change the sensor name of course
but why did you have a different sensor name it was always named object_thumbnails
^
That first section of commented out code was how the thumbnail was originally set
Hum wasn't it printer_thumbnails originaly
Maybe not, we did some many tests that maybe when I did the one with the 2 different sensors I had changed it...
Ah right ok
Hopefully we can just put it all in the sensor field and not setup the camera manually but I doubt it π
Always nice to have some better goals!!!
Ok I'm done for tonight! Thanks for putting this together..
Have a good rest!
I'll check it out tomorrow morning
Thanks for the help
@unborn void how would I modify the picture entity to show the 3d_printer_current_print (gcode file name) in the caption instead of the generic defined name? Similar to this: https://community.home-assistant.io/t/using-a-template-to-show-as-a-title-name-in-a-picture-entity-card/140007/2
You'd have to use a card that allows templating any card
Or make a generic camera entity
and display the camera as yourpicture for the card
So I currently have this:
type: grid
square: false
columns: 1
cards:
- type: picture-entity
name: 3D Printer Thumbnail
show_state: true
show_name: true
camera_view: auto
entity: sensor.3d_printer_current_print
image: camera.3d_printer_thumbnail
#camera:
# Loading generic IP camera via configuration.yaml is deprecated, it will be automatically imported. Once you have confirmed correct operation, please remove 'generic' (IP camera) section(s) from configuration.yaml
# Directions in the README.md for how to add the Thumbnail now.
# - platform: generic
# name: "3D Printer Thumbnail"
# still_image_url: http://<moonraker-ip-address>:7125/server/files/gcodes/{{ states("sensor.3d_printer_object_thumbnails") }}
# verify_ssl: false
Which properly displays the code from this above:
- name: 3d_printer_object_thumbnails
unique_id: "<moonraker-ip-address>59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
Then I want this to show up at the bottom of that picture entity:
- name: 3d_printer_current_print
unique_id: "<moonraker-ip-address>3a0f3144-a801-422f-adb6-e2ed35796072"
state: '{{ states.sensor.printer_3d_sensor.attributes["print_stats"]["filename"]}}'
availability: >
{% set items = ['sensor.printer_3d_sensor'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:file
attributes:
friendly_name: "Current Print"
ie replacing the generic name or idle words (state)
well, your entity is wrong for picture-entity, should be sensor.3d_printer_current_print, not 3d_printer_current_print
other than that, it should work
keep in mind that non-live camera images only update once every 20 seconds
- type: picture-entity
name: 3D Printer Thumbnail
show_state: true
show_name: true
camera_view: auto
entity: camera.3d_printer_thumbnail
If ou want to put text on that, you might have to switch to picture elements instead.
Sorry typed too fast it's set like that just that it shows a broken image and unavailable at the bottom https://imgur.com/a/aGcvYYh
Yeah had some broken code above it
if you can get the camera working, then you can put that anywhere
you will most likely want to set camera_view to live as well for your card
The idle state now shows the gcode file name but the picture is still broken
I'll remove entity and see if the picture then works
Thank you it's working now https://imgur.com/a/QIBxMiA I had the camera feed in the image: spot while I was trouble shooting that idle state...
- show_state: true
show_name: true
camera_view: live
type: picture-entity
entity: sensor.3d_printer_current_print
name: Current Print
camera_image: camera.3d_printer_thumbnail
How difficult would it be to add some .js gcode viewer to then get fed by the template gcode path?
if you don't know coding, it'll be very hard
ok so scratch that I guess π
@unborn void How would I validate if thumbnail [2] doesn't exist in the json output then default to [1] or [0] etc?
- name: 3d_printer_object_thumbnails
unique_id: "<moonraker-ip-address>59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set img = state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[2].relative_path %}
{% if img is not defined %}
{% set img = state_attr('sensor.printer_3d_file_metadata', 'thumbnails')[1].relative_path %}
{% endif %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
UndefinedError: list object has no element 3
I set 2 to 3 to see what would happen...
When I set it back to 2 I get:
- name: 3d_printer_object_thumbnails
unique_id: "IP59b37837-b751-4d31-98c2-516a52edf833"
state: >
http://IP:7125/server/files/gcodes/some/directory1/directory2/.thumbs/pumpkaboo_print-400x300.png
availability: >
True
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
It's weird because it will complete if it's properly defined with 2 but if I put 3 it errors out and won't continue with the else.
- name: 3d_printer_object_thumbnails
unique_id: "<moonraker-ip-address>59b37837-b751-4d31-98c2-516a52edf833"
state: >
{% set dir = states('sensor.3d_printer_current_print') %}
{% set thumb = state_attr('sensor.printer_3d_file_metadata','thumbnails') %}
{% set img = (thumb | last).relative_path if thumb else 'not available' %}
{{ (dir.split('/')[:-1] + [img]) | join('/') }}
availability: >
{% set items = ['sensor.printer_3d_file_metadata'] %}
{{ expand(items)|rejectattr('state','in',['unknown','unavailable'])
|list|count == items|count }}
icon: mdi:image
attributes:
friendly_name: "Object Thumbnails"
it's not weird
indexes start at 0
0 being 1st item, 1 being 2nd, 2 being 3rd
I'm 90% sure I've mentioned this before in this thread
if you always want the last item, that would be [-1], second-to-last [-2], 3rd to last [-3]
if the list is always changing size, you need to figure out which item you want. You can base your selection of the start of the list with a postive number or the end of a list with a negative number.
I didn't realize in the start that you have to try to complete it in the same line so it was never testing being on the second line down from where it was setting the variable above the if statement.
Hi @violet iron , is it only me but seems since little while and after a Moonraker update on the printer, I can no longer fetch the thumbnails into HomeAssistant. The call for the metadata returns a 404
Hi You know about the moonraker integration now?
Yeah.. I saw ater and I think it screwed my original integration but I seem to have another issue which is on the printer side. Right now even though the [virtual sd_card] module is loaded I can't make a call to print_stats I have to wait until my print finishes.
But I guess then I can disable everything we had worked together right?
yes
https://discordapp.com/channels/330944238910963714/1070360235027468420/1071415899980038174 you said you would test stuff then kind of ghosted me after you got what you wanted working. Then that integration came out so I haven't really bothered much with it.
Just to note though I just tested it and have no problems
I think you were using your own modifications though so π https://imgur.com/a/FDy6RJ1
Hi Nona, my apologies, that was never my intention. Had you reached out here I would have responded for sure. That being said my issue seem to be on the klipper/moonraker side where even doing a simple http://serverip:7125/print_stats returns an error
{"error": {"code": 404, "message": "Not Found", "traceback": "Traceback (most recent call last):\n\n File \"/home/biqu/moonraker-env/lib/python3.9/site-packages/tornado/web.py\", line 1690, in _execute\n result = self.prepare()\n\n File \"/home/biqu/moonraker/moonraker/app.py\", line 968, in prepare\n raise tornado.web.HTTPError(404)\n\ntornado.web.HTTPError: HTTP 404: Not Found\n"}}
You need some more stuff in that url:
http://VoronIP:7125/printer/objects/query?print_stats
Have you played with spoolman?