k3kaimu
1/21/2014 - 11:52 AM

GPSモジュールが吐くNMEAを処理して現在地をツイートできるだろうコード(動かしてない)

GPSモジュールが吐くNMEAを処理して現在地をツイートできるだろうコード(動かしてない)

import std.typetuple;
import std.utf;
import std.variant;

import diode.windows;
import dio.core;

import dranges.range;

import graphite.twitter;


enum imgFileName = "map.png";


void main(string[] args)
{
    nmeaStream(args[1])
    .splitBy!`a == '\n'`
    .map!(a => a.array.assumeUnique.chomp.split(","))
    .filter!(a => a[0] == "$GPGGA")
    .map!readGGA
    .map!(a => (a.downloadMap(400, 400, imgFileName),
                a.tweet(),
                0))
    .reduce!"a+b"();
}


enum nmeaStream = (string name) =>
    Serial.open(name)
    .buffered
    .ranged
    .map!"cast(char)a"
    .memoized;

enum readTime = (string[] fields) =>
    SysTime.fromISOString(
        Clock.currTime.toUTC.toISOString.findSplitAfter("T")[0].toUTF32()
        ~ fields[1].toUTF32()
    );

enum readLatitude = (string[] fields) => 
    fields[2][0 .. 2].to!float
    + fields[2][2 .. $].to!float / 60;

enum readLatHemisphere = (string[] fields) =>
    fields[3].to!char;

enum readLongtitude = (string[] fields) => 
    fields[4][0 .. 3].to!float
    + fields[4][3 .. $].to!float / 60;

enum readLngHemisphere = (string[] fields) =>
    fields[5].to!char;

enum readNumOfSat = (string[] fields) =>
    fields[7].to!uint;

enum readAboveSeaLevel = (string[] fields) =>
    fields[9].to!float;

enum readGeoidalHeight = (string[] fields) =>
    fields[11].to!float;

enum readGGA = (string[] fields) => 
    fields.adjoin!(readTime,
                   readLatitude,
                   readLatHemisphere,
                   readLongtitude,
                   readLngHemisphere,
                   readNumOfSat,
                   readAboveSeaLevel,
                   readGeoidalHeight);

alias GGAType = typeof(readGGA([]));

enum downloadMap = (GGAType gga,
                    uint width, uint height,
                    string saveToPath) =>
    "http://maps.google.com/maps/api/staticmap"
    "?center=%s,%s"
    "&zoom=18"
    "&size=%sx%s"
    "&sensor=true"
    "&maptype=roadmap"
    "&format=png"
    .format(gga[1], gga[3], width, height)
    .download(saveToPath);


immutable consumerToken =
    ConsumerToken("",
                  "");

Nullable!Twitter accToken;
Nullable!Tid receptionist;

enum receptionThread = () =>
    ownerTid.send(
        ((Twitter reqtok) =>
            Twitter(reqtok.callAPI!"oauth.accessToken"(readln().chomp())))
        (Twitter(Twitter.oauth.requestToken(consumerToken, null)))
    );

enum tweet = (GGAType gga) =>
    (accToken.isNull
    ?
        (receptionist.isNull
        ?
            receptionist = spawn(receptionThread)
        :
            receiveTimeout(dur!"msecs"(0), (Twitter tok) => accToken = tok)
        )
    :
        accToken.callAPI!"statuses.updateWithMedia"([imgFileName],
            ["status" : "げんざいち?現在地!それここ!%s緯%s度%s経%s度!"
                        .format(gga[2] == 'N' ? "北" : "南",
                                gga[1],
                                gga[4] == 'E' ? "東" : "西",
                                gga[3])])
    );