forked from sleemanj/FlashAirSync
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FlashAirSync.php
222 lines (182 loc) · 6.22 KB
/
FlashAirSync.php
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
#!/usr/bin/php
<?php
// Flash Air Auto Sync, copies all images from flash air card when it is available
// and drops them in a local folder.
// Default Settings override these by passing arguments at the command line
// eg. php FlashAirSync.php --syncto=/home/boffin/Documents/FlashAir
$defaults = [
'flashairip' => 'flashair.local',
'syncfrom' => '/DCIM',
'syncto' => getenv('HOME') . '/FlashAir',
'timezone' => 'GMT',
'pingtimeout' => '5'
];
$options = getopt('', ['flashairip::', 'syncfrom::', 'syncto::', 'timezone::', 'pingtimeout::']) + $defaults;
$FlashAirIP = $options['flashairip']; // IP address of the flashair card, if the card is running in the default host mode you could just use the hostname ("flashair")
$SyncFrom = $options['syncfrom']; // Path on the sdcard to copy from (recursive)
$SyncTo = $options['syncto']; // Full path where it will copy to (recursive)
$TZ = $options['timezone']; // Camera Timezone
// If the camera isn't online, it quits. If the camera goes offline during the processing, the next time it
// will do a full update.
// It only copies a file once.
// Deletions on the camera will NOT propogate to the target - camera space is tight so you are free
// to delete files there without losing the off-camera copy.
// If you delete a file from the target directory, that deletion WILL propogate to the camera
// because the assumption is, it's a junk image you don't want, so no need for it on camera either.
// Modifications on the camera will NOT propogate to the target - you're not modifying images on the camera
// in any meaningful way.
// Modifications in the target will NOT propogate to the camera - the camera will always have the "original".
// Sample config which puts card in wifi client mode (so it connects to your existing wifi router/access point), with upload enabled
// the config file is SD_WLAN/CONFIG on the sdcard, just edit then turn off and on the card to reload.
// For more info:
// https://flashair-developers.com/en/documents/
// https://flashair-developers.com/en/documents/api/
// http://www.extrud3d.com/flashair
/*
[Vendor]
CIPATH=/DCIM/100__TSB/FA000001.JPG
APPMODE=5
APPNETWORKKEY=YOUR_NETWORK_KEY_HERE
APPSSID=YOUR_SSID_HERE
VERSION=F24A6W3AW1.00.03
CID=02544d5357303847075000c0bf00c801
PRODUCT=FlashAir
VENDOR=TOSHIBA
MASTERCODE=00216b97d78a
LOCK=1
APPNAME=flashair
UPLOAD=1
*/
date_default_timezone_set($TZ);
if(!file_exists($SyncTo))
{
mkdir($SyncTo);
}
$ForceUpdate = (!file_exists($SyncTo . '/.Last_Update'))
||file_exists($SyncTo.'/.Force_Update') ;
@unlink($SyncTo.'/.Force_Update');
// Files which have been copied in the past, we use this when we see
// a file not present on the local, if it was copied in the past it must have
// been deleted, so we will propogate that deletion back to the card.
function was_deleted($Destination)
{
if(file_exists($Destination)) return false;
if(!file_exists(dirname($Destination) . '/.Manifest'))
{
mkdir(dirname($Destination) . '/.Manifest');
}
if(file_exists(dirname($Destination) . '/.Manifest/' . basename($Destination)))
{
return true;
}
return false;
}
function sync_for_file($From, $To, $Time)
{
global $FlashAirIP;
if(was_deleted($To))
{
// Delete from card
echo "Delete {$From}\n";
command("upload.cgi", array('DEL' => $From));
unlink(dirname($To) . '/.Manifest/'.basename($To));
}
elseif(!file_exists($To))
{
if(copy("http://{$FlashAirIP}".$From, $To))
{
echo "Copy {$From}\n";
touch($To, $Time);
// Add it to the manifest
touch(dirname($To) . '/.Manifest/'.basename($To), $Time);
}
else
{
if(!alive())
{
force_next_update();
exit;
}
}
}
}
// Check to see if the card is on the network
function alive()
{
global $FlashAirIP, $options;
$timeout = $options['pingtimeout'];
$RC = 1;
exec('ping -c 1 -t ' . $timeout . ' ' . $FlashAirIP,$retArr, $RC);
return !$RC;
}
// Write a flag to fo a forced update the next time
// this happens if we are interrupted by the camera going
// into power down during a sync
function force_next_update()
{
global $SyncTo;
touch($SyncTo . '/.Force_Update');
echo "Interrupted during processing.\n";
}
function command($Op, $Args = array())
{
global $FlashAirIP;
if(!alive())
{
force_next_update();
exit;
}
$Command = is_numeric($Op) ? "http://{$FlashAirIP}/command.cgi?op=$Op" : "http://{$FlashAirIP}/{$Op}?__DUMMY__=1";
foreach($Args as $k => $v)
{
$Command .= "&$k=".rawurlencode($v);
}
$Contents = file_get_contents($Command);
if($Contents === FALSE)
{
force_next_update();
exit;
}
return $Contents;
}
if(!alive())
{
echo "Not Online\n";
exit;
}
if(!$ForceUpdate && command(102) == 0)
{
echo "No Changes\n";
exit;
}
function sync_dir($Dir, $To)
{
global $FlashAirIP, $TZ;
$List = command(100, array('DIR' => $Dir));
$List = preg_split('/\r?\n/', $List);
foreach($List as $r)
{
$r = str_getcsv($r);
if(count($r) < 3) continue;
if($r[3] & 16) // bit 5 = Directory
{
if(!file_exists($To . '/'.$r[1])) mkdir($To . '/' . $r[1]);
sync_dir($Dir . '/' . $r[1], $To . '/' . $r[1]);
continue;
}
// Else normal file
$Day = ($r[4] & 0b0000000000011111);
$Month = ($r[4] & 0b0000000111100000) >> 5;
$Year = (($r[4] & 0b1111111000000000) >> 9)+1980;
$Seconds = ($r[5] & 0b0000000000011111) * 2;
$Minutes = ($r[5] & 0b0000011111100000) >> 5;
$Hours = ($r[5] & 0b1111100000000000) >> 11;
// echo "{$r[1]} {$Year}-{$Month}-{$Day} {$Hours}:{$Minutes}:{$Seconds}\n";
// $Time = mktime($Hours, $Minutes, $Seconds, $Month, $Day, $Year);
$Time = strtotime("{$Year}-{$Month}-{$Day} {$Hours}:{$Minutes}:{$Seconds} {$TZ}");
sync_for_file($Dir . '/' . $r[1], $To . '/' . $r[1], $Time);
}
}
sync_dir($SyncFrom, $SyncTo);
touch($SyncTo . '/.Last_Update');
?>