#!/usr/bin/env python # coding: utf-8 # deux trucs à installer (pip install serial) import serial import time from hexbyte import * def readbytes(number): buf = '' for i in range(number): byte = ser.read() buf += byte return buf # Ouvrir le port série à 960 bauds, 8 bits, 1 stop bit, parity even # Remplacez /dev/tty.USA28X23P1.1 par le nom de votre adaptateur série ser = serial.Serial('/dev/tty.USA28X23P1.1', 9600, bytesize=serial.EIGHTBITS, parity=serial.PARITY_EVEN, timeout=4) # Envoyer un 05. Si l'appareil fonctionne il répond 06 (sinon le programme quitte) ser.write(HexToByte('05')) response1 = ByteToHex(readbytes(1)) assert response1 == '06' print ("Réponse de l'appareil photo") # -- Passage à 57600 -------------------------------------------------------------- # La commande force la liaison vers un débit plus élevé. # 10 02 01 07 01 00 07 10 03 03 (57600) # 10 02 01 07 01 00 06 10 03 02 (38400) # 10 02 01 07 01 00 04 10 03 00 (19200) init2 = '10 02 01 07 01 00 07 10 03 03' ser.write(HexToByte(init2)) # Le 04 indique à l'appareil qu'on a terminé. On attend 0,3 secondes, on passe la liaison à 57600 bauds. # Une fois que c'est fait, on envoie 05, on attend le 06 de l'appareil photo ser.write(HexToByte('04')) time.sleep (0.3) ser.baudrate = 57600 ser.write(HexToByte('05')) response1 = ByteToHex(readbytes(1)) assert response1 == '06' print ("Passage à 57600 : OK") # -- Modèle de l'appareil -------------------------------------------------------------- print ("\nModèle de l'appareil photo : ") # La commande demande une info à l'appareil photo. # Il répond avec une chaîne qui termine par 10 03 (suivi du checksum ignoré ici) # La réponse (dans data) est une chaîne avec des infos sur le modèle. init2 = '10 02 00 09 00 00 10 03 0A' ser.write(HexToByte(init2)) data='' while data[-4:] != '1003': testvalue = ByteToHex(readbytes(1)) data = data + testvalue data=data[2:] print (data.decode("hex")) # -- Récupération du nombre de photos---------------------------------------------------- # La commande demande le nombre de photos print ("\nNombre de photos :") init2 = '10 02 00 0B 00 00 10 03 08' ser.write(HexToByte(init2)) # La réponse commence par 10 02, se termine par 10 03 (et le checksum) et contient le nombre de photos en hexadécimal. # On l'affiche simplement en décimal après conversion data='' while data[-4:] != '1003': testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Récupérer juste le nombre de photos data = data[16:18] print (int(data, 16)) # --- Récupération des miniatures ------------------------------------------------------ # La boucle commence à 1 et va jusqu'au nombre de photos CompteurImage=1 CompteurImageMax=int(data,16) print ("\nRécupération des miniatures en cours") while CompteurImage <= CompteurImageMax: # la commande pour récupérer le nom du fichier est 10 02 00 0A 02 00 xx 00 10 03 yy # xx est le numéro de la photo en hexa. Si c'est la photo 10 (en hexa) faut doubler le 10 # yy est le checksum. C'est un xor de toutes les valeurs de la commande sauf le 10 02 du début et le 10 de la fin. # Pour 10 02 00 0A 02 00 01 00 10 03, il faut donc xor 0A + xor 02 + xor 01 + xor 03 (0A) init2 = '10 02 00 0A 02 00 ' init3='' CompteurImageHex=hex(CompteurImage) if CompteurImage < 16: init3='0' init3 = init3 + str(CompteurImageHex[2:]) if str(CompteurImageHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='8' Xor04='3' CalculXor = int(Xor01) ^ int(CompteurImage) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor # L'appareil renvoie une commande avec le nom du fichier complet. ser.write(HexToByte(init2)) data='' while data[-4:] != '1003' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Récupérer juste la partie avec le nom de fichiers en 8.3. remplacement du JPG par TIF # J'ouvre le fichier à écrire. data=data[16:34] ImageName=HexToByte(data) ImageName=ImageName + 'TIF' Image=open(ImageName, "w") Image.close # Récupération de la miniature. 10 02 00 00 02 00 xx 00 10 03 yy init2 = '10 02 00 00 02 00 ' init3='' CompteurImageHex=hex(CompteurImage) if CompteurImage < 16: init3='0' init3 = init3 + str(CompteurImageHex[2:]) if str(CompteurImageHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='2' Xor04='3' CalculXor = int(Xor01) ^ int(CompteurImage) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor print ("Début du téléchargement de " + ImageName) ser.write(HexToByte(init2)) data='' fichierjpg='' CompteurDoublonFin=0 # L'appareil va envoyer les données en plusieurs fois. Chaque fin de bloc contient 10 17 et doit être suivie d'un 06 (qui indique que tout va bien) par le client # Le code ne vérifie pas le checksum et assume que tout va bien # La fin de la transmission se termine par 10 03 # Attention, les données peuvent contenir 10 17 ou 10 03. L'appareil double donc les 10 pour l'indiquer. Une donnée 10 03 va donc être encodée 10 10 03. Il faut enlever les doublons avant d'enregistrer. while True: testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Truc tordu pour détecter la présence de doublon # Compte le nombre de 10 *avant* le 1017 DetectDoublon=6 DetectDoublon2=4 CompteurDoublon=0 if data[-4:] == '1017': while data[-DetectDoublon:-DetectDoublon2] == '10': CompteurDoublon += 1 DetectDoublon2 += 2 DetectDoublon += 2 # Truc tordu pour détecter la présence de doublon # Compte le nombre de 10 *avant* le 1003 DetectDoublonFin=6 DetectDoublonFin2=4 CompteurDoublonFin=0 if data[-4:] == '1003': while data[-DetectDoublonFin:-DetectDoublonFin2] == '10': CompteurDoublonFin += 1 DetectDoublonFin2 += 2 DetectDoublonFin += 2 # Si un doublon : pas 1017. Si deux doublons : 1017 if data[-4:] == '1017' and CompteurDoublon%2 == 0: #if CompteurImage == 3: data=data[14:] data=data[:-4] fichierjpg = fichierjpg + data data='' ser.write(HexToByte('06')) # Si un doublon : pas 1003. Si deux doublons : 1003, on quitte if data[-4:] == '1003' and CompteurDoublonFin%2 == 0: #if CompteurImage == 3: break data=data[14:] fichierjpg = fichierjpg + data fichierjpg = fichierjpg[2:] # Enlever 24 octets : un TIFF commence par 49h 49h 2Ah 00h # La structure du QuickTake 200 est basique : 24 octets de données, puis un TIFF. fichierjpg = fichierjpg[24:] ser.write(HexToByte('06')) # Une boucle qui va supprimer les doublons 10 10 pour les transformer en 10 LongueurString=len(fichierjpg) CompteurString=0 while CompteurString <= LongueurString: #print (CompteurString) #print (LongueurString) CompteurString1=CompteurString+4 CompteurString2=CompteurString+2 CompteurString3=CompteurString+8 if fichierjpg[CompteurString:CompteurString1] == ('1010'): #print (fichierjpg[CompteurString:CompteurString3]) fichierjpg2 = fichierjpg[:CompteurString2] fichierjpg2 = fichierjpg2 + fichierjpg[CompteurString1:LongueurString] fichierjpg = fichierjpg2 #print (fichierjpg[CompteurString:CompteurString1]) CompteurString = CompteurString + 2 # Le fichier est rempli, on passe à la photo suivante Image=open(ImageName, "w") fichierjpg=HexToByte(fichierjpg) Image.write(fichierjpg) Image.close CompteurImage += 1 ChoixUser='0' while ChoixUser != 'o' and ChoixUser != 'n': print ("Miniatures récupérées. Voulez-vous récupérer les JPG de l'appareil ?") ChoixUser = raw_input("(o/n)") if ChoixUser == 'n': print ("Au revoir !") # --- Récupération des miniatures ------------------------------------------------------ if ChoixUser == 'o': CompteurImage=1 print ("\nRécupération des fichiers en cours") while CompteurImage <= CompteurImageMax: # idem plus haut, récupération du nom de fichier init2 = '10 02 00 0A 02 00 ' init3='' CompteurImageHex=hex(CompteurImage) if CompteurImage < 16: init3='0' init3 = init3 + str(CompteurImageHex[2:]) if str(CompteurImageHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='8' Xor04='3' CalculXor = int(Xor01) ^ int(CompteurImage) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor ser.write(HexToByte(init2)) data='' while data[-4:] != '1003' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Récupérer juste la partie avec le nom de fichiers en 8.3 data=data[16:40] ImageName=HexToByte(data) Image=open(ImageName, "w") Image.close # Mesure du temps. A 57 600, Comptez 20 secondes par photo # La commande pour lire une image précise est 10 02 00 02 02 00 xx 00 10 03 start = time.time() init2 = '10 02 00 02 02 00 ' init3='' CompteurImageHex=hex(CompteurImage) if CompteurImage < 16: init3='0' init3 = init3 + str(CompteurImageHex[2:]) if str(CompteurImageHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='0' Xor04='3' CalculXor = int(Xor01) ^ int(CompteurImage) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor print ("Début du téléchargement de " + ImageName) ser.write(HexToByte(init2)) data='' fichierjpg='' # Pour éviter de gérer les doublons, on lit tant qu'on n'a pas la fin d'un fichier JPEG (FFD9) # Le code va enlever directement la signalisation sur le bus série while data[-4:] != 'FFD9' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Truc tordu pour détecter la présence de doublon # Compte le nombre de 10 *avant* le 1017 DetectDoublon=6 DetectDoublon2=4 CompteurDoublon=0 if data[-4:] == '1017': while data[-DetectDoublon:-DetectDoublon2] == '10': CompteurDoublon += 1 DetectDoublon2 += 2 DetectDoublon += 2 # Si un doublon : pas 1017. Si deux doublons : 1017 if data[-4:] == '1017' and CompteurDoublon%2 == 0: #if CompteurImage == 3: # print (data) data=data[14:] data=data[:-4] fichierjpg = fichierjpg + data data='' ser.write(HexToByte('06')) data=data[14:] fichierjpg = fichierjpg + data fichierjpg = fichierjpg[2:] ser.write(HexToByte('06')) # Juste pour éviter de faire une boucle reloue data='' while data[-4:] != '1003' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue # Suppression des 10 10 LongueurString=len(fichierjpg) CompteurString=0 while CompteurString <= LongueurString: #print (CompteurString) #print (LongueurString) CompteurString1=CompteurString+4 CompteurString2=CompteurString+2 CompteurString3=CompteurString+8 if fichierjpg[CompteurString:CompteurString1] == ('1010'): #print (fichierjpg[CompteurString:CompteurString3]) fichierjpg2 = fichierjpg[:CompteurString2] fichierjpg2 = fichierjpg2 + fichierjpg[CompteurString1:LongueurString] fichierjpg = fichierjpg2 #print (fichierjpg[CompteurString:CompteurString1]) CompteurString = CompteurString + 2 # Le fichier est enregistré Image=open(ImageName, "w") fichierjpg=HexToByte(fichierjpg) Image.write(fichierjpg) Image.close # Affichage du temps print ("Temps de chargement de l'image") end = time.time() start=int(start) end=int(end) print(end - start) CompteurImage += 1 # --- Effacement des images ------------------------------------------------------------- ChoixUser='0' while ChoixUser != 'o' and ChoixUser != 'n': print ("Images récupérées. Voulez-vous effacer les images de l'appareil ?") ChoixUser = raw_input("(o/n)") if ChoixUser == 'n': print ("Au revoir !") if ChoixUser == 'o': CompteurImage=1 ImageDelete=CompteurImageMax # Commencer par effacer la dernière et ensuite descendre vers zero print ("\nEffacement des fichiers en cours") while CompteurImage <= CompteurImageMax: # On affiche le nom de la photo effacée (par utile, mais visuellement plus sympa) init2 = '10 02 00 0A 02 00 ' init3='' ImageDeleteHex=hex(ImageDelete) if ImageDelete < 16: init3='0' init3 = init3 + str(ImageDeleteHex[2:]) if str(ImageDeleteHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='8' Xor04='3' CalculXor = int(Xor01) ^ int(ImageDelete) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor ser.write(HexToByte(init2)) data='' while data[-4:] != '1003' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue data=data[16:40] ImageName=HexToByte(data) print ("Effacement de " + ImageName) # Effacement 10 02 00 19 00 xx 00 10 03 yy init2 = '10 02 00 19 02 00 ' init3='' ImageDeleteHex=hex(ImageDelete) if ImageDelete < 16: init3='0' init3 = init3 + str(ImageDeleteHex[2:]) if str(ImageDeleteHex[2:]) == '10': init2 = init2 + '10 ' init2 = init2 + init3 init2 = init2 + ' 00 10 03 ' Xor01='1B' Xor04='3' CalculXor = int(Xor01,16) ^ int(ImageDelete) CalculXor = int(CalculXor) ^ int(Xor04) if CalculXor < 16: CalculXor0 = '0' else: CalculXor0 = '' CalculXor = hex(CalculXor) CalculXor = CalculXor[2:] CalculXor = CalculXor0 + CalculXor init2 = init2 + CalculXor ser.write(HexToByte(init2)) ser.write(HexToByte('06')) # Juste pour éviter de faire une boucle reloue data='' while data[-4:] != '1003' : testvalue = ByteToHex(readbytes(1)) data = data + testvalue ImageDelete -= 1 CompteurImage += 1