Auteur Sujet: [Résolu] Script python dans Slic3r  (Lu 32 fois)

BrunoBellamy

  • Hero Member
  • *****
  • Messages: 2104
    • Voir le profil
    • Bellaminettes Blog
[Résolu] Script python dans Slic3r
« le: 09 juillet, 2018, 06:29:47 pm »
Hello les smartpotes ! :)

J'utilise Slic3r 1.2.9 sous Mac OS X, et l'idée (probablement pas originale, mais j'aime bien réinventer l'eau chaude) m'est venue d'écrire un petit script de post-processing pour que la ligne :

M117 printing layer [layer_num]

qui doit s'exécuter à chaque changement de layer s'accompagne aussi d'un ' of xxx' où xxx serait le nombre total de layers (afin d'obtenir sur le LCD de ma BunnyCore, à chaque changement de layer, un truc du genre 'Printing layer 42 of 199'), chose qu'on ne peut pas réaliser en utilisant une variable de Slic3r puisque, à ma connaissance, aucune variable du programmer ne permet de connaître ce nombre.

J'ai donc écrit le script python ci-dessous :

#! /usr/bin/python

# Gcode post processing script       #
# to add total layers number to each #
# 'M117 printing layer [layer_num]'  #
# in your custom G-code before layer #
# change in Slic3r                   #
# by Bruno Bellamy 07/2018 :)        #

import os
import sys

gcode_file = sys.argv[1]
counter = 0
strtofind = 'M117 printing layer'

file = open(gcode_file,"r")
lines = file.readlines()
for line in lines:
    if line[0] != ';' and strtofind in line:
        counter += 1
file.close()

maxlayer = str(counter)

file = open(gcode_file,"w")
for line in lines:
    if line[0] != ';' and strtofind in line:
        line = line.rstrip('\n\r ')
        layernum_pos = line.rfind(' ')+1
        layernum = str(int(line[layernum_pos:]) + 1)
        line = strtofind + ' ' + layernum + ' of ' + maxlayer
    file.write(line)
file.close()


Je l'ai bien sûr testé hors Slic3r, dans une fenêtre de terminal, en lui passant en argument (comme est supposé faire Slic3r, si j'ai bien compris) le chemin du fichier G-code généré, et… ça marche !

Ça fait exactement ce que c'est supposé faire : lire le G-code, compter les changements de layers, ajouter à chaque affichage du n° de layer le ' of xxx' et réécrire le fichier.

J'ai donc ajouté le chemin absolu menant à ce script dans la section Print Settings > Output options > Post-processing scripts de Slicer, sauvegardé cette config, chargé un .stl, exporté le G-code, et… rien.

Mon G-code n'a pas du tout été modifié, tout s'est passé comme si Slic3r avait ignoré mon script.  :'(

J'ai ajouté un '/usr/bin/python ' avant le chemin menant au script, mais Slic3r m'a alors annoncé que ça lui posait un problème de permissions, et de plus il me semble avoir lu qq part que de toute façon Slic3r ne veut pas de ce genre de trucs, par sécurité.

Donc là, je sèche.

Si quelqu'un a une idée… ;)

BrunoBellamy

  • Hero Member
  • *****
  • Messages: 2104
    • Voir le profil
    • Bellaminettes Blog
Re : [Résolu] Script python dans Slic3r
« Rponse #1 le: 09 juillet, 2018, 07:04:01 pm »
Eh bien ça n'aura pas duré longtemps…

Je remercie BrunoBellamy pour sa solution aussi rapide qu'efficace ;) ;) ;)

Or donc, je viens de trouver tout seul comme un grand la clé du mystère :

quand je testais mon script en ligne de commande ça marchait impec, parce que ma ligne de commande invoquait python :
$ python gcode_maxlayernum.py

Si j'avais fait ./gcode_maxlayernum.py ça aurait d'abord foiré parce que le script n'était déjà pas exécutable. Pour ça pas de souci, il suffit d'un chmod +x gcode_maxlayernum.py

Mais ça ne s'arrête pas là…

Ça n'aurait toujours pas marché parce que ce n'est pas /usr/bin/python que le script invoque dans sa première ligne, juste après #!, mais /usr/bin/python^M

Eh oui, les sauts de ligne de Mac OS X ne lui plaisent pas, à cette andouille.

Un :
$ tr -d '\r' < gcode_maxlayernum.py > gcode_maxlayernum

a eu tôt fait d'y remédier, à partir de quoi la ligne :
#! /usr/bin/python

est en fait tout à fait valide ! :)

Du coup, Slic3r a bien voulu considérer que le script, non précédé d'un appel à Python (puisque cet appel est invoqué dans le script lui-même) était exécutable, et maintenant j'ai du G-code qui inclut l'affichage, à chaque changement de layer, du n° du layer en cours et du nombre total de layers.

Cool. Merci moi. :)

BrunoBellamy

  • Hero Member
  • *****
  • Messages: 2104
    • Voir le profil
    • Bellaminettes Blog
Re : Script python dans Slic3r
« Rponse #2 le: 10 juillet, 2018, 07:59:29 am »
Saperlipopette !

Je me suis réjoui un peu vite…

L'astuce fonctionne, et le script modifie effectivement le G-code (c'est un progrès), mais il se passe des trucs bizarres à l'impression, vu que ça n'imprime plus : tout s'arrête après la fin de la mise en chauffe du plateau.

Faut que j'étudie ça de plus près…

Accessoirement, ma ligne de code pour virer les retours charriot qui empêchent le #! /usr/bin/python de faire son job est foireuse, il ne faut apparemment pas directement envoyer le contnue du fichier vers lui-même, mais vers un autre fichier, quitte à supprimer l'ancien pour ensuite renommer le nouveau :

$ tr -d '\r' < gcode_maxlayernum.py > gcode_maxlayernum2.py
$ rm gcode_maxlayernum.py
$ mv gcode_maxlayernum2.py gcode_maxlayernum.py

Sinon, ça efface le script purement et simplement, ce qui serait dommage. ;)

BrunoBellamy

  • Hero Member
  • *****
  • Messages: 2104
    • Voir le profil
    • Bellaminettes Blog
Re : [Résolu] Script python dans Slic3r
« Rponse #3 le: 10 juillet, 2018, 08:35:37 am »
Bon, cette fois ça marche. :)

C'était, encore une fois (décidément…) un souci de saut de ligne.

Voici la version du script qui marche impec :

#! /usr/bin/python

# Gcode post processing script       #
# to add total layers number to each #
# 'M117 printing layer [layer_num]'  #
# in your custom G-code before layer #
# change in Slic3r                   #
# by Bruno Bellamy 07/2018 :)        #

import os
import sys

gcode_file = sys.argv[1]
counter = 0
strtofind = 'M117 Layer'

file = open(gcode_file,"r")
lines = file.readlines()
for line in lines:
    if line[0] != ';' and strtofind in line:
        counter += 1
file.close()

maxlayer = str(counter)

file = open(gcode_file,"w")
for line in lines:
    if line[0] != ';' and strtofind in line:
        line = line.rstrip('\n\r ')
        layernum_pos = line.rfind(' ')+1
        layernum = str(int(line[layernum_pos:]) + 1)
        line = strtofind + ' ' + layernum + ' / ' + maxlayer + '\n'
    file.write(line)
file.close()


Il est à noter que sur l'afficheur LCD (le mien en tout cas) il n'y a pas la place pour afficher en entier une ligne telle que 'Printing layer nnn / ttt', j'ai donc réduit Le texte à 'Layer nnn / ttt'.

Il faudra donc bien indiquer à Slic3r que la ligne à insérer à chaque changement de layer est :

M117 Layer [layer_num]

Sinon ça marche pô… ;)