IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Utilisation d'un Datetime.TimeDelta en incrustation d'image pour un minuteur [Python 3.X]


Sujet :

Python

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Par défaut Utilisation d'un Datetime.TimeDelta en incrustation d'image pour un minuteur
    Bonjour,
    je n'arrive pas à intégrer une valeur de temps < Datetime.TimeDelta> dans une chaine de caractère ?
    En détail :
    J'utilise un RPI 3 + une camera avec Jessie et Python comme soft pour surveiller le déroulement d'impression 3D d'une machine qui se trouve 3 pièces plus loin,
    J'ai utilisé un temps OCTOPRINT mais je loupais pas mal de pièces à cause de la liaison entre la carte mère de cette imprimante 3D(une Velleman K8400) et le RPI qui pourtant a sa propre source d'alimentation, donc j'ai déconnecter et je n'utilise plus que la camera,
    Comme on peut le voir sur une image j'affiche l'heure en incrustation dans l'image (et aussi la température du RPI, mais pas quand j'ai pris la photo
    Nom : incrustation.jpg
Affichages : 426
Taille : 73,3 Ko
    j'ai imprimé, câbler et relier au RPI quatre roues codeuse sur lesquelles j'affiche la durée d'impression( qui vient du trancheur REPETIER quand je compile mon objet 3D à imprimer en GCODE),
    les Roues en question(Je ne résiste pas à l'envie de partager mon œuvre avec vous ) :
    Nom : Roues_codeuses1.jpg
Affichages : 430
Taille : 372,5 Ko
    En Python j'additionne ce qui est sur les roues codeuses à l'heure courante, c'est à dire au moment où je débute l'impression , ce qui me donne l'heure de fin de la tâche et ensuite je soustrais l'heure de fin de tâche avec l'heure courante, ce qui me donne le temps restant à imprimer
    Tous ceci fonctionne parfaitement et pour faire les additions/soustraction j'utilise la fonction TIMEDELTA,
    Mais je n'arrive pas à intègre mon résultat dans mon incrustation d'image de ma camera, J'ai déjà quelques valeurs dans cette chaine et il me faut rajouter ce TIMEDLTA ?
    Voici ou devrai se trouver ma valeur récalcitrante, juste après temps restant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    camera.annotate_text = dt.datetime.now().strftime('%d-%B-%Y %H:%M:%S\n') + ('temps restant : ') + ('Temperature RPI %0.1f' % chaleur)
    Merci par avance de votre aide SI VOUS AVEZ UNE SOLUTION ou d'autres suggestions.
    Henri

  2. #2
    Membre chevronné
    Homme Profil pro
    Développeur banc de test
    Inscrit en
    Mai 2014
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur banc de test
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Mai 2014
    Messages : 199
    Par défaut
    Bonsoir,

    sacré projet que vous avez là !

    Pour calculer le temps restant il y a deux méthodes, soit avec time soit avec datetime.

    avec timedelta il suffit d'appeler la méthode .total_seconds() pour récupérer le delta en secondes.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    # Duration, convert datetime.timedelta into duration
    start = datetime.datetime(2014, 10, 22, 15, 15, 37, 343957)
    stop = datetime.datetime(2014, 10, 23, 15, 21, 53, 74262)
    duration = stop - start
     
    # Convert datetime.timedelta into [HH]:MM:SS, hours can be > 24
    hours, remainder = divmod(round(duration.total_seconds()), 3600) # round to avoid 60s
    minutes, seconds = divmod(remainder, 60)
    print("{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)) # "24:06:16"

    Avec time tout les calculs se font en secondes, c'est souvent le plus simple pour calculer une durée.

    voici un code d'exemple : Progression avec temps restant

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    import time # Time access and conversions
     
    def format_duration(total_seconds): # {
        """Convert seconds into [HH]:MM:SS, hours can be > 24
     
        Example: format_duration(7281) -> "02:01:21"
        """
        hours, remainder = divmod(round(total_seconds), 3600) # round to avoid 60s
        minutes, seconds = divmod(remainder, 60)
        return "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
    # } format_duration
     
    nb_tasks = 60
    time_m_ref = time.monotonic()
    for i in range(nb_tasks): # {
        time.sleep(1)
        tasks_done = (i + 1)
        progression = tasks_done / nb_tasks
        time_spent = (time.monotonic() - time_m_ref)
        print("Progression : {:4.0%}, temps écoulé : {}, temps restant : {}, vitesse : {} / étape".format(
            progression,
            format_duration(time_spent),
            format_duration((time_spent / tasks_done) * (nb_tasks - tasks_done)),
            format_duration(time_spent / tasks_done)
        ))
    # } for

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Par défaut Timedelta et variable globale
    Bonjours,

    J'ai résolus mon problème, il s'agissait de la porté d'une variable mal renseigné, mais n'oubliez pas que je suis un newbie avec Python, bien plus habitué à DELPHI,C, C#, PLSQL,
    Voici le code complet de cette application camera avec roue codeuse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    # http://picamera.readthedocs.io/en/release-1.0/index.html
    #*********************************************************
    #*            CARTE de SAUVEGARGE 26/04/2019             * 
    #*********************************************************
    #!usr/bin/sudo python3 pour le demarage auto
    # ATTENTION pour demarrer : python3 simple_cam.py
    # ctrl + c pour quitter
    # ps -ef | grep simple_cam.py pour avoir son numero et le killer
    # sudo kill -9 son numero
    # sudo chmod 777 rc.local pour avoir les droit
    # sudo python3 /home/pi/henri/simple_cam.py dans RC.local
    # apt-mark showauto | grep gpio recherche de paquets installé automatiquement
    # apt-mark showmanual |grep pio recherche de paquets installé manuelement
    # FING applic portable S3 pour détecter les IP utilisé
    # liste des HSB : lsusb
    # /opt/vc/bin/vcgencmd measure_temp //Temperarure interne du RPI
    # history -c Clear History
    # which vcgencmd ou n'importe quoi
    # sudo find / -name NOM DU FICHIER
    # sudo apt rem
     
    import io
    import picamera
    import itertools
    import datetime as dt
    import time
    import logging
    import socketserver
    from threading import Condition 
    from http import server
    from picamera import Color
    # gestion Temperature du RPI
    import threading
    import time
    from subprocess import getoutput
    # Librairies de lecture des roues codeuses etde l'horloge
    import RPi.GPIO as GPIO                                               # Importation des librairies qui gerent les ports
    import time                                                           # Importation de la librairie temps
    # Librairies des calculs des heures 
    from datetime import timedelta
    from datetime import datetime
     
    # ****************  Fonctions du GPIO ****************************** 
    GPIO.setmode(GPIO.BCM)                                                # BCM : Numero des GPIO / BOARD : Numero du connecteur
    # GPIO.setwarnIN,(False) 
     
    # **********  
    GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # DOWN , pull_up_down=GPIO.PUD_UP
    GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
    GPIO.setup(27, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
    GPIO.setup(22, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 
    # **********  
    GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(13, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    # **********  
    GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(21, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(20, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(16, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    # **********  
    GPIO.setup(12, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(25, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(24, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
     
    # **************** Appele de Fonctions du GPIO ****************************** 
    tempo1 = 0 # global variable
     
    def roue(): # https://pythonbasics.org/multiple-return/
        global tempo1
        status4 = GPIO.input(4)
        unitee = status4
        status17= GPIO.input(17)
        unitee = unitee + (status17 * 2)
        status27 = GPIO.input(27)
        unitee = unitee + (status27 * 4)
        status22 = GPIO.input(22)
        unitee = unitee + (status22 * 8)    
        status5 = GPIO.input(5)
        dizaine = status5
        status6= GPIO.input(6)
        dizaine = dizaine + (status6 * 2)
        status13 = GPIO.input(13)
        dizaine = dizaine + (status13 * 4)
        status19 = GPIO.input(19)
        dizaine = dizaine + (status19 * 8)    
        status26 = GPIO.input(26)
        centaine = status26
        status21= GPIO.input(21)
        centaine = centaine + (status21 * 2)
        status20 = GPIO.input(20)
        centaine = centaine + (status20 * 4)
        status16 = GPIO.input(16)
        centaine = centaine + (status16 * 8)
        millier = 0
        status12 = GPIO.input(12)
        millier = status12
        status25= GPIO.input(25)
        millier = millier + (status25 * 2)    
        status24 = GPIO.input(24)
        millier = millier + (status24 * 4) 
        status23 = GPIO.input(23)
        millier = millier + (status23 * 8) 
        tempo = str(millier) + str(centaine) + str(dizaine) + str(unitee) 
        if (tempo1 != tempo):
            tempo1 = tempo
            boulet = 1
        else:
            boulet = 0
        # print("___Boulet ____ : ", boulet)
        return (unitee,dizaine,centaine,millier,boulet) 
     
    # ********************** Fonction Horloge ********************
    t4 = 0
    # while True:
    def horloge():
        global tempo
        global t4
        global t3
        global t2
        global t1
        # t3 = datetime.now() # pour le singer
        unitee,dizaine,centaine,millier,boulet = roue() # roue(unitee,dizaine,centaine,millier)
        time.sleep(1)
        tempo = str(millier) + str(centaine) + str(dizaine) + str(unitee)  
        print("Boulet =", boulet) # Flag pour distinguer si il y à un changement sur les roues codeuses
     
        if (boulet == 1):
            now = datetime.now()
            t1 = timedelta(hours = int(now.strftime("%H")),minutes  = int(now.strftime("%M")), seconds = int(now.strftime("%S")))     
            t2 = timedelta(hours = (millier * 10 + centaine),minutes  = (dizaine *10 + unitee) , seconds = 0)
            t3 = t1 + t2  
            print("t1 =", t1) # heure courante
            print("t2 =", t2) # heure roue codeuse
            print("t3 =", t3) # heure de Fin
        else:
            now = datetime.now()
            t1 = timedelta(hours = int(now.strftime("%H")),minutes  = int(now.strftime("%M")), seconds = int(now.strftime("%S")))
            t4 = t3 - t1 # t4 = t3 - t1
            print("t1_B =", t1) # heure courante
            # print("t2_B =", t2) # heure roue codeuse
            print("t3_B =", t3) # heure de Fin        
            print("Temps restant(t4_B) =",t4) #Temps restant
            print("type of t4 =", type(t4))
            # return(t4) # inutile
    # ********************* Page serveur Camera ************************
    PAGE="""
    <html>
    <head>
    <title>picamera MJPEG streaming demo</title>
    </head>
    <body>
    <center>
    <h1>PiCamera MJPEG Streaming Demo de HENRI</h1>
    <h1>CARTE de SAUVEGARGE 26/04/2019</h1>
    <img src="stream.mjpg" width="640" height="480" />
    </center>
    </body>
    </html>
    """
     
    # gestion Temperature
    chaleur= 0 
     
    def rien():
    	while True:
    		global chaleur
    		time.sleep(1) # 5 0.3
    		chaleur = float(getoutput('/opt/vc/bin/vcgencmd measure_temp')[5:-2])
    		horloge() #  Appele de la fonction Horloge
    		# print( chaleur )
    		print("Horloge T4",t4) 
     
    class StreamingOutput(object):
        def __init__(self):
            self.frame = None
            self.buffer = io.BytesIO()
            self.condition = Condition()
     
        def write(self, buf):
            if buf.startswith(b'\xff\xd8'):
                self.buffer.truncate()
                with self.condition:
                    # print("de visu : " + t4)
                    self.frame = self.buffer.getvalue() 
                    self.condition.notify_all()
                    # camera.annotate_text = 'Date & Heure\n' + dt.datetime.now().strftime('%d-%m-%Y %H:%M:%S\n') + 'cal' # OK
                    camera.annotate_text = dt.datetime.now().strftime('%d-%B-%Y %H:%M:%S\n') + ("Temps restant :" + str(t4))+ ('\n Temperature RPI %0.1f ' % chaleur)
                    # camera.annotate_text = 'Chaleur : ' + float(chaleur)
                    self.buffer.seek(0)
            return self.buffer.write(buf)
     
    class StreamingHandler(server.BaseHTTPRequestHandler):
        def do_GET(self):
            if self.path == '/':
                self.send_response(301)
                self.send_header('Location', '/index.html')
                self.end_headers()
            elif self.path == '/index.html':
                content = PAGE.encode('utf-8')
                self.send_response(200)
                self.send_header('Content-Type', 'text/html')
                self.send_header('Content-Length', len(content))
                self.end_headers()
                self.wfile.write(content)
                # threading.Thread(target=horloge().start) # Démmare le Thread de l'Horloge            
                threading.Thread(target=rien().start)  # Démmare le Thread de temperature
            elif self.path == '/stream.mjpg':
                self.send_response(200)
                self.send_header('Age', 0)
                self.send_header('Cache-Control', 'no-cache, private')
                self.send_header('Pragma', 'no-cache')
                self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
                self.end_headers()
                try:
                    while True:
                        with output.condition:
                            output.condition.wait()
                            frame = output.frame
                        self.wfile.write(b'--FRAME\r\n')
                        self.send_header('Content-Type', 'image/jpeg')
                        self.send_header('Content-Length', len(frame))
                        self.end_headers()
                        self.wfile.write(frame)
                        self.wfile.write(b'\r\n')
                except Exception as e:
                    logging.warning(
                        'Removed streaming client %s: %s',
                        self.client_address, str(e))                      
            else:
                self.send_error(404)
                self.end_headers()
     
    class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
        allow_reuse_address = True    
        daemon_threads = True
     
     
    with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
        camera.rotation='180'    # pour donner une oriantation de seulement 90° à l'image : 0/90/180/270
        # camera.hflip=False     # Retournement à 180 droite/gauche
        # camera.vflip=False     # Retournement à 180 haut/bas
        # camera.start_preview()
        camera.annotate_text_size = 15
        camera.annotate_foreground = Color('black')
        camera.annotate_background = Color('white')    
        # camera.annotate_text = dt.datetime.now().strftime('%d-%m-%Y %H:%M:%S')                 #"Visu"
        output = StreamingOutput()
        camera.start_recording(output, format='mjpeg')   
        try: 
            address = ('', 8000)
            server = StreamingServer(address, StreamingHandler)
            server.serve_forever()
            # gestion Temperature
            # threading.Thread(target=rien().start)
            # print(chaleur)
        finally:
            camera.stop_recording()
     
     
    GPIO.cleanup
    Ne me donnez pas trop de coup de trique mais plutôt des conseils et suggestions,
    En tous cas mon code fonctionne et ça me va,

    La prochaine étape va être d'ajouter/intégrer le son à ce bout de code et Là j'ai pas du tout idée MAIS ! je reviendrai certainement vers vous
    j'aimerai l'intègre sur ce PI ZERO bien pratique et que je balade au gré de mes besoins(humble et surtout ludique) :
    Nom : cam_pi_zero_1.jpg
Affichages : 340
Taille : 248,0 Ko

    Henri

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    237
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 237
    Par défaut Une fois installé et opérationne
    Une fois installé et opérationnel pendant l'impression d'un collet ER16 pour cet outil en parti de ma création : https://www.thingiverse.com/thing:3427173
    Le tout réalisé avec OPENSCAD,

    le temps de l'impression attendu :
    Nom : K8400.jpg
Affichages : 345
Taille : 316,3 Ko

    et l'évolution de son affichage en incrustation :
    Nom : RC_Collet.jpg
Affichages : 334
Taille : 315,7 Ko

    Plus deux commandes bien utiles que j'ai codé aussi avec ces roues codeuses, 9900 : shutdown et 9800 : reboot du RPI(je n'imprime jamais au delà de 48H) ainsi que la température du RPI et l'heure.
    Comme ceci je peux me tenir à distance des émanations et du bruit,
    Henri

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Convertir une durée en minute avec datetime.timedelta
    Par www.rubis dans le forum Général Python
    Réponses: 4
    Dernier message: 13/05/2016, 14h18
  2. Pb variable avec datetime.timedelta
    Par www.rubis dans le forum Général Python
    Réponses: 3
    Dernier message: 10/05/2016, 19h37
  3. [V8] Retard de 2h sur une date après utilisation du widget datetime
    Par guidono2 dans le forum Odoo (ex-OpenERP)
    Réponses: 2
    Dernier message: 04/05/2015, 12h10
  4. python, datetime,timedelta , conversion
    Par koreimy dans le forum Général Python
    Réponses: 1
    Dernier message: 24/09/2013, 18h40
  5. Comment utiliser la classe DateTime ?
    Par Regis0122 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 28/06/2009, 17h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo