public void writeInside(FileStream outfd)
{
var t = Time.gm(ts);
- outfd.printf(" <time>%s</time>\n", t.format("%Y-%m-%dT%H:%M:%SZ"));
+ outfd.printf(" <time>%s</time>\n", t.format("%Y-%m-%dT%H:%M:%S%z"));
}
}
{
public string tag;
public string title;
+ public bool acked;
public List<LogEntry> entries;
public List<TrackEntry> track;
- public Log(string tag, string title)
+ public Log(string tag, string title, bool acked=false)
{
this.tag = tag;
this.title = title;
+ this.acked = acked;
entries = null;
track = null;
}
if (entries == null) return;
// Directory where we save the log
- string dir = config.homedir + "/log-" + tag;
+ string dir;
+ if (acked)
+ dir = config.homedir + "/archive";
+ else
+ dir = config.homedir + "/log";
DirUtils.create(dir, 0777);
// First try with a plain name
var t = Time.local(entries.data.ts);
- string basename = dir + "/" + t.format("%Y%m%d-%H%M%S");
+ string basename = dir + "/" + t.format("%Y%m%d-%H%M%S") + "-" + tag;
string pathname = basename + ".gpx";
outfd.flush();
}
+ public void dump()
+ {
+ write(stderr);
+ }
+
protected void writeTrack(FileStream outfd)
{
outfd.puts(" <trk>\n");
protected void writeEntries(FileStream outfd)
{
- outfd.puts(" <wpt>\n");
for (weak List<LogEntry> i = entries; i != null; i = i.next)
i.data.write(outfd);
- outfd.puts(" </wpt>\n");
}
protected void write(FileStream outfd)
}
}
+enum LogParserState {
+ NONE,
+ METADATA,
+ TRACK,
+ WPT,
+}
+
+class LogParser: Object
+{
+ const MarkupParser parser = { // It's a structure, not an object
+ start,// when an element opens
+ end, // when an element closes
+ text, // when text is found
+ null, // when comments are found
+ null // when errors occur
+ };
+
+ MarkupParseContext context = null;
+ public Log result = null;
+ LogParserState state = LogParserState.NONE;
+ string cur_text = "";
+ LogEntry cur_logentry = null;
+ TrackEntry cur_trackentry = null;
+
+ construct
+ {
+ context = new MarkupParseContext(
+ parser, // the structure with the callbacks
+ 0, // MarkupParseFlags
+ this, // extra argument for the callbacks, methods in this case
+ destroy // when the parsing ends
+ );
+ }
+
+ void destroy()
+ {
+ cur_text = "";
+ cur_logentry = null;
+ cur_trackentry = null;
+ }
+
+ public bool parse(string content, ssize_t len = -1) throws MarkupError
+ {
+ string oldtz = Environment.get_variable("TZ");
+ Environment.set_variable("TZ", "UTC", true);
+ bool res = context.parse(content, len);
+ if (oldtz == null)
+ Environment.unset_variable("TZ");
+ else
+ Environment.set_variable("TZ", oldtz, true);
+ return res;
+ }
+
+ void parse_attrs(Waypoint w, string[] attr_names, string[] attr_values)
+ {
+ w.lat = 1000;
+ w.lon = 1000;
+ for (int i = 0; attr_names[i] != null; ++i)
+ {
+ if (attr_names[i] == "lat")
+ w.lat = attr_values[i].to_double();
+ else if (attr_names[i] == "lon")
+ w.lon = attr_values[i].to_double();
+ }
+ }
+
+ void start (MarkupParseContext context, string name,
+ string[] attr_names, string[] attr_values) throws MarkupError
+ {
+ if (name == "gpx")
+ {
+ state = LogParserState.NONE;
+ result = new Log("TODO:TAG", "TODO:TITLE");
+ } else if (name == "metadata") {
+ state = LogParserState.METADATA;
+ } else if (name == "wpt") {
+ cur_logentry = new LogEntry();
+ parse_attrs(cur_logentry, attr_names, attr_values);
+ result.entries.append(cur_logentry);
+ state = LogParserState.WPT;
+ } else if (name == "trkpt") {
+ cur_trackentry = new TrackEntry();
+ parse_attrs(cur_trackentry, attr_names, attr_values);
+ result.track.append(cur_trackentry);
+ state = LogParserState.TRACK;
+ }
+ cur_text = "";
+ }
+
+ void end (MarkupParseContext context, string name) throws MarkupError
+ {
+ if (name == "name")
+ {
+ switch (state)
+ {
+ case LogParserState.METADATA:
+ result.title = cur_text;
+ break;
+ case LogParserState.WPT:
+ cur_logentry.msg = cur_text;
+ break;
+ }
+ }
+ else if (name == "time")
+ {
+ Time t = Time();
+ t.strptime(cur_text, "%Y-%m-%dT%H:%M:%S%z");
+ if (state == LogParserState.WPT)
+ cur_logentry.ts = t.mktime();
+ else if (state == LogParserState.TRACK)
+ cur_trackentry.ts = t.mktime();
+ }
+ }
+
+ void text (MarkupParseContext context,
+ string text, size_t text_len) throws MarkupError
+ {
+ cur_text += text;
+ }
+}
+
public class Logger : Resource, Object
{
protected List<Log> logs;
if (logs == null) end_trace();
}
+ public Log load(string fname)
+ {
+ string contents;
+ size_t length;
+ FileUtils.get_contents(fname, out contents, out length);
+ LogParser parser = new LogParser();
+ parser.parse(contents, (ssize_t)length);
+ return parser.result;
+ }
+
+ protected size_t list_dir(string dir, ref List<string> res)
+ {
+ size_t count = 0;
+ var d = File.new_for_path(dir);
+ var enumerator = d.enumerate_children(FILE_ATTRIBUTE_STANDARD_NAME, 0, null);
+ FileInfo file_info;
+ while ((file_info = enumerator.next_file(null)) != null)
+ {
+ if (!file_info.get_name().has_suffix(".gpx")) continue;
+ res.append(file_info.get_name());
+ ++count;
+ }
+ return count;
+ }
+
+ public string[] list_entries(bool only_unacked=true)
+ {
+ size_t count = 0;
+ List<string> entries = new List<string>();
+ if (!only_unacked)
+ count += list_dir(config.homedir + "/archive", ref entries);
+ count += list_dir(config.homedir + "/log", ref entries);
+ string[] res = new string[count+1];
+ size_t cur = 0;
+ for (weak List<string> i = entries; i != null; i = i.next)
+ res[cur++] = i.data;
+ res[cur] = null;
+ return res;
+ }
+
public void instant(string tag, string msg)
{
var log = new Log(tag, msg);