Skip to content

Instantly share code, notes, and snippets.

@jantore
Last active August 29, 2015 14:04
Show Gist options
  • Save jantore/c5bce6aa144ef8c0622b to your computer and use it in GitHub Desktop.
Save jantore/c5bce6aa144ef8c0622b to your computer and use it in GitHub Desktop.
mojitude
#!/usr/bin/perl
use strict;
use warnings;
package Positioner;
use Mojo::Base 'Mojo::EventEmitter';
use Mojo::IOLoop;
has 'ioloop' => sub { Mojo::IOLoop->singleton->multi_accept(1) };
has 'position' => undef;
sub parse_rmc {
my ($line) = @_;
my @g = split(/,/, $line);
return if $g[2] ne 'A' or not $g[3] or not $g[5];
my $time = $g[1];
my ($lad, $lam) = $g[3] =~ m/^(\d\d)(\d\d\.\d\d\d\d)/;
my $lat = $lad + ($lam / 60);
$lat *= -1 if($g[4] eq 'S');
my ($lod, $lom) = $g[5] =~ m/^(\d\d\d)(\d\d\.\d\d\d\d)/;
my $lng = $lod + ($lom / 60);
$lng *= -1 if($g[6] eq 'W');
return {
time => $time,
lat => $lat,
lng => $lng,
};
}
sub start {
my ($self) = @_;
$self->{'buffer'} = '';
$self->ioloop->server({
address => '127.0.0.1',
port => 51234,
} => sub {
my ($loop, $server) = @_;
$server->on(read => sub {
my ($stream, $bytes) = @_;
$self->{'buffer'} .= $bytes;
while($self->{'buffer'} =~ s/^([^\r\n]+)\r\n//m) {
my $pos = parse_rmc($1);
if(defined $pos) {
$self->position($pos);
$self->emit(position => $pos);
}
}
});
});
}
package main;
use Mojolicious::Lite;
use Mojo::ByteStream qw{ b };
use Mojo::JSON qw{ encode_json };
my $p = Positioner->new;
helper 'position' => sub {
b(encode_json($p->position));
};
websocket '/position' => sub {
my $c = shift;
my $cb = $p->on(position => sub {
$c->send({ json => $_[1] });
});
$c->on(finish => sub {
$p->unsubscribe(position => $cb);
});
};
get '/' => 'index';
$p->start;
app->start;
__DATA__
@@ index.html.ep
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { height: 100% }
</style>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js"></script>
<script type="text/javascript">
function initialize() {
% if(position ne "null") {
var pos = <%= position %>
% } else {
var pos = new google.maps.LatLng(0, 0);
% }
var map = new google.maps.Map(
document.getElementById("map-canvas"),
{
center: pos,
zoom: 15
}
);
var marker;
var ws = new WebSocket('<%= url_for('position')->to_abs %>');
ws.onmessage = function (event) {
var p = JSON.parse(event.data);
console.log(p['lat']);
if(marker) {
marker.setPosition(p);
} else {
marker = new google.maps.Marker({
position: p,
map: map
});
//marker.setMap(map);
}
map.panTo(p);
};
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"></div>
</body>
</html>
#!/usr/bin/perl
use strict;
use warnings;
use v5.010;
use AnyEvent::SerialPort;
use IO::Socket::INET6;
$| = 1;
my $cv = AnyEvent->condvar;
my $CRLF = "\r\n";
my $ctl = AnyEvent::SerialPort->new(
serial_port => [
'/dev/ttyACM1' => [ baudrate => 115200 ],
]
);
my $gps = AnyEvent::SerialPort->new(
serial_port => [
'/dev/ttyACM2' => [ baudrate => 115200 ],
]
);
my $out = IO::Socket::INET6->new(
PeerAddr => '91.189.176.203',
PeerPort => 49160,
Proto => 'udp',
) or die "couldn't create socket: $!";
$ctl->push_write("AT+CFUN=1\r\n");
$ctl->push_read(line => sub {
if($_[1] =~ /^OK$/) {
$ctl->push_write("AT*E2GPSCTL=1,1,1\r\n");
}
});
my $a;
$a = sub {
my ($gps, $line) = @_;
$line =~ s/^\x00*//;
if($line =~ m/^\$GPRMC/) {
chomp $line;
$out->send($line . "\r\n");
}
$gps->push_read(response => $a);
};
$gps->push_read(response => sub {
my ($gps, $line) = @_;
if($line =~ /\^*EMRDY: 1$/) {
$gps->push_write("AT*E2GPSNPD\r\n");
$gps->push_read(response => $a);
}
});
$cv->recv;
package response;
sub anyevent_read_type {
my ($handle, $cb) = @_;
sub {
$handle->push_read(line => sub {
my $c;
$c = sub {
if($_[1]) {
$cb->($handle, $_[1]);
} else {
$handle->unshift_read(line => $c);
}
};
$c->($handle, $_[1]);
});
return 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment