Skip to content

Commit 4f76438

Browse files
author
Christian Holl
committed
Merge branch 'release/V1.0_a'
2 parents e577fe2 + acb5180 commit 4f76438

File tree

4 files changed

+278
-0
lines changed

4 files changed

+278
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.pyc

README.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
A downloader written in python for the Toshiba FlashAir Wifi SDHC Cards.
2+
3+
Currently using a setup of Hostname/IP, remote_folder and download directory requires a modification of the __init__.py.
4+
When started the script looks for the card on the given Host/IP if it is able to connect it, it gets the filelist by command.cgi
5+
and checks for every file inside the download directory, if a file is not present, it will be downloaded. This continues as
6+
long as the script is running, terminate it with CTRL-C.

src/PyFlashAero/__init__.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
'''
2+
Created on Jan 4, 2014
3+
4+
Licence: GNU AGPL
5+
6+
@author: Christian Holl
7+
'''
8+
from PyFlashAero import flashair
9+
import time
10+
11+
if __name__ == '__main__':
12+
# Host/IP Port Timeout
13+
a=flashair.connection('192.168.0.16', 80,1000)
14+
while True:
15+
# REMOTE_FOLDER DOWNLOAD DIRECTORY
16+
a.sync_folder_to_remote_folder('/DCIM/', '/downloaddir')
17+
pass

src/PyFlashAero/flashair.py

+254
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
'''
2+
Created on Jan 4, 2014
3+
4+
Licence: GNU AGPL
5+
6+
@author: Christian Holl
7+
'''
8+
9+
import os
10+
import http.client
11+
import datetime
12+
13+
class file_list_entry(object):
14+
file_name=''
15+
directory_name=''
16+
byte_size=-1
17+
attribute_Archive=False;
18+
attribute_Directly=False;
19+
attribute_Volume=False;
20+
attribute_System=False;
21+
attribute_Hidden=False;
22+
attribute_ReadOnly=False;
23+
date_human=()
24+
time_human=()
25+
time=0
26+
date=0
27+
def __init__(self, file_name, directory_name, size, attributes, date, time):
28+
self.file_name=file_name
29+
self.directory_name=directory_name
30+
self.byte_size=size
31+
32+
33+
34+
attributes=int(attributes)
35+
self.attribute_Archive= not not(attributes & 1<<5)
36+
self.attribute_Directly= not not(attributes & 1<<4)
37+
self.attribute_Volume= not not(attributes & 1<<3)
38+
self.attribute_System= not not(attributes & 1<<2)
39+
self.attribute_Hidden= not not(attributes & 1<<1)
40+
self.attribute_ReadOnly= not not(attributes & 1<<0)
41+
42+
time=int(time)
43+
self.time=time;
44+
self.time_human=(((time&(0x1F<<11))>>11),((time&(0x3F<<5))>>5),(time&(0x1F))*2)
45+
46+
date=int(date)
47+
self.date=date;
48+
self.date_human=(((date&(0x3F<<9))>>9)+1980,((date&(0x1F<<5))>>5),date&(0x1F))
49+
50+
51+
class command(object):
52+
'''OPCODE - DIR DATE ADDR LENGTH DATA REQUIRED FWVERSION (Bigger/Smaller)'''
53+
Get_file_list= (100,1,0,0,0,0,'1.00.03',True)
54+
Get_the_number_of_files= (101,1,0,0,0,0,'1.00.00',True)
55+
Get_update_status= (102,0,0,0,0,0,'1.00.00',True)
56+
Get_SSID= (104,0,0,0,0,0,'1.00.00',True)
57+
Get_network_password= (105,0,0,0,0,0,'1.00.00',True)
58+
Get_MAC_address= (106,0,0,0,0,0,'1.00.00',True)
59+
Set_browser_language= (107,0,0,0,0,0,'1.00.00',True)
60+
Get_the_firmware_version= (108,0,0,0,0,0,'' ,True)
61+
Get_the_control_image= (109,0,0,0,0,0,'2.00.00',True)
62+
Get_Wireless_LAN_mode= (110,0,0,0,0,0,'2.00.00',True)
63+
Set_Wireless_LAN_timeout_length= (111,0,0,0,0,0,'2.00.00',True)
64+
Get_application_unique_information= (117,0,0,0,0,0,'2.00.00',True)
65+
Get_CID= (120,0,0,0,0,0,'1.00.03',True)
66+
Get_data_from_shared_memory= (130,0,0,1,1,0,'2.00.00',True)
67+
Set_data_to_shared_memory= (131,0,0,0,0,0,'2.00.00',True)
68+
Get_the_number_of_empty_sectors= (140,0,0,0,0,0,'1.00.03',True)
69+
Enable_Photo_Share_mode= (200,0,0,0,0,0,'2.00.00',True)
70+
Disable_Photo_Share_mode= (201,0,0,0,0,0,'2.00.00',True)
71+
Get_Photo_Share_mode_status= (202,0,0,0,0,0,'2.00.00',True)
72+
Get_SSID_for_Photo_Share_mode= (203,0,0,0,0,0,'2.00.00',True)
73+
74+
class connection(object):
75+
'''
76+
classdocs
77+
'''
78+
79+
list_directory=100
80+
fwversion=''
81+
host=0
82+
port=0
83+
timeout=0
84+
def __init__(self, host, port, timeout):
85+
'''
86+
Constructor
87+
'''
88+
self.host=host
89+
self.port=port
90+
self.timeout=timeout
91+
92+
93+
def send_command(self, opcode, directory='', date=-1, addr=-1, data=(), length=-1):
94+
if(len(opcode)==8):
95+
url="/command.cgi?op=" + str(opcode[0])
96+
97+
if(opcode[1] and len(directory)==0 ):
98+
print("ERROR Oppcode " + str(opcode[0]) + " requires directory")
99+
return(-1,'')
100+
elif(opcode[1]):
101+
url += '&DIR=' + directory
102+
103+
if(opcode[2] and date<0 ):
104+
print("ERROR Oppcode " + str(opcode[0]) + " requires date")
105+
return(-1,'')
106+
elif(opcode[2]):
107+
url += '&DATE=' + date
108+
109+
if(opcode[3] and addr<0 ):
110+
print("ERROR Oppcode " + str(opcode[0]) + " requires addr")
111+
return(-1,'')
112+
elif(opcode[3]):
113+
url += '&ADDR=' + str(addr)
114+
115+
if(opcode[4] and length==0 ):
116+
print("ERROR Oppcode " + str(opcode[0]) + " requires length")
117+
return(-1,'')
118+
elif(opcode[4]):
119+
url += '&LEN=' + str(length)
120+
121+
if(opcode[5] and len(data)==0 ):
122+
print("ERROR Oppcode " + str(opcode[0]) + " requires data")
123+
return(-1,'')
124+
elif(opcode[5]):
125+
url += '&DATA=' + data
126+
127+
#Is it a firmware query?
128+
if(len(opcode[6])!=0):
129+
130+
if(len(self.fwversion)==0):
131+
132+
(ret, ver)=self.send_command(command.Get_the_firmware_version)
133+
if(not ret):
134+
self.fwversion=ver.decode("utf-8")[9:]
135+
print("Firmware is: ")
136+
print(self.fwversion)
137+
else:
138+
if(ret!=-2):
139+
print("ERROR: Could not determine firmware version!")
140+
return(-1,'')
141+
142+
if(opcode[7]): #must be bigger than or equal to firmware version
143+
if(opcode[6]<self.fwversion):
144+
print("ERROR Opcode " + str(opcode[0]) + " not supported in firmware!")
145+
return(-1,'')
146+
else:
147+
if(opcode[6]>self.fwversion):
148+
print("ERROR Opcode " + str(opcode[0]) + " not supported in firmware!")
149+
return(-1,'')
150+
151+
152+
#Connect
153+
connection = http.client.HTTPConnection(self.host, self.port, timeout=self.timeout)
154+
155+
try:
156+
connection.request("GET", url)
157+
response=connection.getresponse();
158+
return (response.status!=200,response.read())
159+
except:
160+
return (-2,'')
161+
pass
162+
163+
164+
def get_file_list(self,directory):
165+
(ret,lst)=self.send_command(command.Get_file_list,directory=directory)
166+
167+
if(ret==0):
168+
169+
lines=lst.decode("utf-8").split("\r\n")
170+
if(lines[0]=="WLANSD_FILELIST"):
171+
lines=lines[1:-1] #skip headline, and current dir at the end
172+
else:
173+
return (0,())
174+
175+
outlst=[]
176+
for file in lines:
177+
e=file.split(",")
178+
179+
if(len(e)!=6):
180+
print("Error file list entry has " +str(len(e)) +" entrie(s) instead of expected 6, skipping entry")
181+
continue;
182+
#(file_name, directory_name, size, attributes, date, time):
183+
f=file_list_entry(e[1],e[0],int(e[2]),int(e[3]),int(e[4]),int(e[5]))
184+
outlst.append(f)
185+
186+
return (0,outlst)
187+
else:
188+
return (1,())
189+
190+
def download_file(self, remote_location, local_path='', local_file_name=''):
191+
conn = http.client.HTTPConnection(self.host)
192+
if(len(local_file_name)==0):
193+
local_file_name = remote_location.split('/')[-1]
194+
file_size=0
195+
196+
197+
#does folder exist?
198+
if(not os.access(local_path, os.R_OK)):
199+
return (2,0,'')
200+
201+
#add / if it is not there already
202+
if(len(local_path)!=0 and local_path[-1]!='/'):
203+
local_path+='/'
204+
205+
#combine path and file
206+
local_path+=local_file_name
207+
208+
#does file exist already?
209+
if(os.path.isfile(local_path)):
210+
return (3,0,'')
211+
212+
print("Downloading:" + local_file_name)
213+
#get the stuff from the FlashAir
214+
conn.request("GET", remote_location)
215+
download = conn.getresponse()
216+
file = open(local_path, 'wb')
217+
if(download.status==200):
218+
219+
while True:
220+
buffer=download.read(1024*8)
221+
if not buffer:
222+
break;
223+
file_size += len(buffer)
224+
file.write(buffer)
225+
file.close()
226+
return (int(download.status!=200), file_size,local_path)
227+
228+
def download_file_list_entry(self, entry,local_path='', local_filename=''):
229+
(status,size,local_filename)=self.download_file(entry.directory_name + '/' + entry.file_name, local_path, local_filename)
230+
if(status):
231+
return(1)
232+
233+
234+
if(size!=entry.byte_size):
235+
os.remove(local_filename)
236+
return(2)
237+
238+
return(0)
239+
240+
def sync_folder_to_remote_folder(self,remote_path='',local_path='',extensions=['JPG']):
241+
#all extensions to upper case
242+
extensions=[x.upper() for x in extensions]
243+
244+
#get list of remote files
245+
(status, outlist)=self.get_file_list(remote_path)
246+
if(not status and len(outlist)):
247+
if(not os.access(local_path, os.R_OK)):
248+
return 2
249+
for entry in outlist:
250+
if ((entry.file_name.split('.')[-1].upper() in extensions) or len(extensions)==0):
251+
self.download_file_list_entry(entry, local_path)
252+
253+
254+

0 commit comments

Comments
 (0)