tbr123psu has asked for the wisdom of the Perl Monks concerning the following question:
esteemed monks:
greetings all! i've been struggling with this for days now, and figured it was finally time to ask for some help.
I've been following the instructions found at http://virantha.com/2014/01/09/hacking-together-a-wifi-photo-frame-with-a-toshiba-flashair-sd-card-wireless-photo-uploads/ to set up a wifi SD card for use in a photoframe. I wanted to use Perl rather than the python referenced on the page because I generally prefer perl and because i kinda wanted to do it myself.
it's been smooth sailing, right up to the point of having to submit a FAT32 timestamp to set the creation date of the uploaded file. This part has me completely stumped.
i've been all over google, and the best reference I can find about the required formats is from this thread on stackoverflow: http://stackoverflow.com/questions/15763259/unix-timestamp-to-fat-timestamp. There's no search results here for fat32.
interestingly enough, I was able to figure out how interpret the dates coming off the card (for the purposes of knowing which photos were the last ones added, so I can only upload new ones), but trying to apply the same logic in reverse did not work so well. I'm also not entirely clear on why it worked the way it did, such that they come out split up but when going in, the card wants just one string, but I suppose that's just quirkiness in the API i've got to live with.
anyhow, i suspect the answer has something to do with pack, but i won't lie, i'm just flinging stuff at the wall in the hopes that it sticks. I thought i was making progress, in that I have some idea what the actual value for a current timestamp is that would be submitted to the api call (through trial and error/guesswork -- manually trying to make things up, based on the example given in the API documentation https://flashair-developers.com/en/documents/api/uploadcgi/).
so i've got some idea what the value needs to look like, but for the life of me i can't get that output to generate programatically. it seems that it's inclusive of 0-9 and a-f, so it seems like a hexadecimal number (as per http://www.microbuilder.eu/Tutorials/Fundamentals/Hexadecimal.aspx), but being honest, this gets a little deeper than i usually go. thinking about it sometimes makes my head hurt.
has anyone ever bumped into anything like this before or can offer any insight? code snippets below that do the relevant stuff with dates/times.
here's the code that pulls the time and date from the card and interprets it.
#Each row of the list is returned in the following format. #<directory>, <filename>, <size>, <attribute>, <date>, <time> # date 16 bit int -- bit 15-9 value based on 0 as 1980, bit 8-5 month +value from 1 to 12, bit 4-0 day, value from 1 to 31 # time 16 bit int -- bit 15-11 hour, 10-5, minute, 4-0 second / 2 # size my $fileList = getHttp($cardip, "command.cgi?op=100&DIR=/"); #print ($fileList . "\n"); my @fileArray = split("\n", $fileList); my @fileTimesArray; my $lastTime = 0; print (ref(@fileArray) . "\n"); foreach my $file (@fileArray) { if (index($file, ",") != -1) { print "working with file $file\n"; my ($directory, $name, $size, $att, $date, $time) = split(",", + $file); # example date, time = 18151,39092 my $day = ($date >> 0) & (2**5-1); my $month = ($date >> 5) & (2**4-1); my $year = ($date >> 9) & (2**7-1); $year = 1980 + $year; my $second = ($time >> 0) & (2**5-1); my $minute = ($time >> 5) & (2**6-1); my $hour = ($time >> 11) & (2**5-1); $second = $second * 2; print ("file: $name | $month - $day - $year | $hour : $minute +: $second | $epochTime\n"); #print ("file: $name | $date | $time\n"); #print ("day: $day\n"); #print ("month: $month\n"); #print ("year: $year\n"); #print ("second: $second\n"); #print ("minute: $minute\n"); #print ("hour: $hour\n"); my $perlMonth = $month - 1; my $epochTime = timelocal($second,$minute,$hour,$day,$perlMont +h,$year); if ($epochTime > $lastTime) { $lastTime = $epochTime; } push @fileTimesArray, { file => $name, epoch => $epochTime, si +ze => $size }; } }
and here's the code for trying to generate a timestamp based on the timestamp returned from the file on disk.
@info = stat($path->{file}); my $createdtime = $info[10]; print "regular created time is: $createdtime\n"; my ($sec, $min, $hour, $day,$month,$year) = (localtime($createdtim +e))[0,1,2,3,4,5]; # You can use 'gmtime' for GMT/UTC dates instead of 'localtime' $month++; my $displayYear = $year; my $realYear = $year; $year = $year - 80; $second = ceil($sec / 2); # example date, time = 18151,39092 --> not same format!?! # time 16 bit int -- bit 15-11 hour, 10-5, minute, 4-0 second / 2 #my $encSecond = $second & (2**5-1); #my $encMinute = $minute & (2**6-1); #my $encHour = $hour & (2**5-1); # date 16 bit int -- bit 15-9 value based on 0 as 1980, bit 8-5 mo +nth value from 1 to 12, bit 4-0 day, value from 1 to 31 #my $encDay = $day & (2**5-1); #my $encMonth = $month & (2**4-1); #my $encYear = $month & (2**7-1); #use integer; my $data = $year . $month . $day . $hour . $min . $second; print "using $data as input for pack\n"; #my $data = $second . " " . $minute . " " . $hour . " " . $day . " + " . $month . " " . $year; #my $createdtimeFat = pack "N8", $data; my $createdtimeFat = pack "N8", $year,$month,$day,$hour,$min,$sec +ond; #my $createdtimeFat = ($year << 25) | ($month << 21) | ($day << 1 +6) | ($hour << 11) | ($min << 5) | ($second << 0); #my $createdtimeFat = (($year & (2**7-1)) << 25) | (($month & (2* +*4-1)) << 21) | (($day & (2**5-1)) << 16) | (($hour & (2**5-1)) << 11 +) | (($min & (2**6-1)) << 5) | (($second & (2**5-1)) << 0); # 8 digits # 8 = year # 7 = year + month # 6 = month + day # 5 = day #### # 4 = hour # 3 = hour + month # 2 = minute + second # 4 = second #my $createdtimeFat = '469f9f01'; #my $hex = sprintf("0x%x", $createdtimeFat); #my $hex = printf("%x",$createdtimeFat); print "Unix time ".$createdtime." converts to ".$month." ".$day.", + ".($displayYear+1900)." ".$hour.":".$min.":".$sec." year (in offset +from 1980) is $year [real year is $realYear]\n"; #print $encSecond ." ". $encMinute ." ". $encHour ." ". $encDay ." + ". $encMonth ." ". $encYear . "\n"; print "createdtimeFat should look something like 46ef99c6\n"; print "createdtimeFat is $createdtimeFat\n"; my @unpacked = unpack("N8",$createdtimeFat); print "and unpacked: " . @unpacked . "\n"; my $setdate = getHttp($cardip, "upload.cgi?FTIME=0x" . $createdtim +eFat); print "result of setdate operation: $setdate\n";
and this is the getHttp function/sub
sub getHttp() { my $ip = shift; my $args = shift; my $status; my $url = "http://" . $ip . "/" . $args; #print ("accessing " . $url . "\n"); # set custom HTTP request header fields my $req = HTTP::Request->new(GET => $url); my $resp = $ua->request($req); if ($resp->is_success) { my $message = $resp->decoded_content; #print "Received reply: $message\n"; $status = $resp->decoded_content; } else { print "HTTP GET error code: ", $resp->code, "\n"; print "HTTP GET error message: ", $resp->message, "\n"; $status = $resp->message; } return $status }
many thanks in advance for any help or guidance anyone can offer - i'm at wit's end, and i feel like i've got to be missing something!
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: Pack + Fat32 timestamp (|, <<)
by tye (Sage) on Jul 25, 2015 at 22:57 UTC | |
by tbr123psu (Novice) on Jul 25, 2015 at 23:32 UTC | |
|
Re: Pack + Fat32 timestamp
by anonymized user 468275 (Curate) on Jul 28, 2015 at 14:44 UTC |