#!/usr/bin/env perl use strict; use warnings; use Time::HiRes qw(sleep); use Data::Dumper; use Net::Clacks::Client; use XML::Simple; use Carp; # Load the temporary GSPSupport module (currently under redesign due to protocol change) # FIXME: This script uses all kinds of hardcoded values. This will need to change after the protocol upgrade BEGIN { unshift @INC, './'; }; use GSPSupport; my $project = GSPSupport->parse(); # Load local config (e.g. with radio device we are talking to, relay routing etc) my $config = GSPSupport::loadClacksConfig(); # Slurb the binary crontab file my $tmptab = GSPSupport::slurpBinFile('crontab.bin'); my @crontab = split//, $tmptab; my $offset = 0; my $lastpacket; my $resendtime = 0; # Connect to Net::Clacks and listen to packets from our target device my $clacks = Net::Clacks::Client->new($config->{host}, $config->{port}, $config->{user}, $config->{password}, 'GSPDecoder'); $clacks->listen('GSP::RECIEVE::' . $project->{textid}); my $nextping = 0; my $done = 0; # Initiate stream by sending the first chunk sendNextChunk(); while(!$done) { my $now = time; if($nextping < $now) { $clacks->ping(); $nextping = $now + 30; } # Check for timeout and resend packet if required if($resendtime > 0 && $resendtime < time) { $clacks->set('GSP::SEND', $lastpacket); $clacks->doNetwork(); $resendtime = time + 5; } $clacks->doNetwork(); while((my $message = $clacks->getNext())) { if($message->{type} eq 'disconnect') { $clacks->listen('GSP::RECIEVE::' . $project->{textid}); $clacks->ping(); $clacks->doNetwork(); $nextping = $now + 30; next; } next unless($message->{type} eq 'set'); next unless($message->{name} eq 'GSP::RECIEVE::' . $project->{textid}); # We got some packet from our target Radioduino, check if it's the right one (it may not be, it could be some other # telemetry stuff) decodeFrame($message->{data}); } sleep(0.01); } exit(0); my @frame; sub decodeFrame { my $line = shift; @frame = GSPSupport::packet2frame($line); if($frame[6] != $project->{id}) { # Not from this project return; } if($frame[8] == 255) { # ERROR FRAME. This happens if we did not disable the scheduler manually before starting to upload # a new crontab GSPSupport::decodeErrorFrame(@frame); $done = 1; return; } if($frame[8] != 8) { # Not a COMMAND_DOWN_READFRAM, probably some other automatic telemetry stream return; } if($offset == 2048) { # Seems we have send all data, so we are done print "All sent!\n"; $done = 1; return; } # Ok, send the next chunk of data sendNextChunk(); } sub sendNextChunk { print "Sending $offset...\n"; # Get an empty frame with default values like routing already set my @outframe = GSPSupport::emptyframe($project); # Set command number $outframe[8] = 6; # COMMAND_UP_WRITEFRAM # Set FRAM address and data length $outframe[9] = ($offset >> 8) & 0xff; $outframe[10] = $offset & 0xff; $outframe[11] = 16; # Copy the data chunk for(my $i = 0; $i < 16; $i++) { my $char = shift @crontab; $outframe[12 + $i] = ord($char); } # Turn this array into a proper nRF24-over-Clacks frame packet my $packet = GSPSupport::frame2packet(@outframe); # Remember the packet in case we need to resend it $lastpacket = $packet; # Send it via clacks and remember the new timeout time $clacks->set('GSP::SEND', $packet); $clacks->doNetwork(); $resendtime = time + 5; # Move offset $offset += 16; return; }