From d5d8ee8bb873ad9833be0729d9d7336c093fef4e Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 18 Nov 2013 16:44:33 +0200 Subject: [PATCH] Remember discovered MFX locomotives across runs --- source/libr2c2/arducontrol.cpp | 89 ++++++++++++++++++++++++++++++---- source/libr2c2/arducontrol.h | 36 ++++++++++++++ 2 files changed, 116 insertions(+), 9 deletions(-) diff --git a/source/libr2c2/arducontrol.cpp b/source/libr2c2/arducontrol.cpp index e29614f..2361d85 100644 --- a/source/libr2c2/arducontrol.cpp +++ b/source/libr2c2/arducontrol.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include #include #include #include "arducontrol.h" @@ -18,12 +21,21 @@ ArduControl::ProtocolInfo ArduControl::protocol_info[2] = ArduControl::ArduControl(const string &dev): serial(dev), debug(1), + state_file("arducontrol.state"), power(false), active_accessory(0), s88(*this), mfx_search(*this), thread(*this) { + if(FS::exists(state_file)) + DataFile::load(*this, state_file.str()); + + unsigned max_address = 0; + for(MfxInfoArray::const_iterator i=mfx_info.begin(); i!=mfx_info.end(); ++i) + max_address = max(max_address, i->address); + mfx_search.set_next_address(max_address+1); + PendingCommand cmd; cmd.command[0] = READ_POWER_STATE; cmd.length = 1; @@ -107,6 +119,20 @@ unsigned ArduControl::add_loco(unsigned addr, const string &proto_name, const Ve return loco.id; } +ArduControl::MfxInfoArray::iterator ArduControl::add_mfx_info(const MfxInfo &info) +{ + MfxInfoArray::iterator i; + for(i=mfx_info.begin(); (i!=mfx_info.end() && i->id!=info.id); ++i) ; + if(i==mfx_info.end()) + { + mfx_info.push_back(info); + i = --mfx_info.end(); + } + else + *i = info; + return i; +} + void ArduControl::remove_loco(unsigned id) { Locomotive &loco = get_item(locomotives, id); @@ -288,15 +314,8 @@ void ArduControl::tick() MfxInfo info; if(mfx_search.pop_info(info)) { - MfxInfoArray::iterator i; - for(i=mfx_info.begin(); (i!=mfx_info.end() && i->id!=info.id); ++i) ; - if(i==mfx_info.end()) - { - mfx_info.push_back(info); - i = --mfx_info.end(); - } - else - *i = info; + MfxInfoArray::iterator i = add_mfx_info(info); + save_state(); signal_locomotive_detected.emit(*i); } } @@ -408,6 +427,23 @@ void ArduControl::flush() { } +void ArduControl::save_state() const +{ + FS::RedirectedPath tmp_file(state_file); + IO::BufferedFile out(tmp_file.str(), IO::M_WRITE); + DataFile::Writer writer(out); + + writer.write((DataFile::Statement("mfx_announce_serial"), mfx_announce.get_serial())); + for(MfxInfoArray::const_iterator i=mfx_info.begin(); i!=mfx_info.end(); ++i) + { + DataFile::Statement st("mfx_locomotive"); + st.append(i->id); + st.sub.push_back((DataFile::Statement("address"), i->address)); + st.sub.push_back((DataFile::Statement("name"), i->name)); + writer.write(st); + } +} + ArduControl::Tag::Tag(): type(NONE), @@ -852,6 +888,11 @@ void ArduControl::MfxSearchTask::process_reply(const char *reply, unsigned lengt } } +void ArduControl::MfxSearchTask::set_next_address(unsigned a) +{ + next_address = a; +} + bool ArduControl::MfxSearchTask::pop_info(MfxInfo &info) { return queue.pop(info); @@ -1047,4 +1088,34 @@ unsigned ArduControl::ControlThread::process_reply(const char *reply, unsigned r return 0; } + +ArduControl::Loader::Loader(ArduControl &c): + DataFile::ObjectLoader(c) +{ + add("mfx_announce_serial", &Loader::mfx_announce_serial); + add("mfx_locomotive", &Loader::mfx_locomotive); +} + +void ArduControl::Loader::mfx_announce_serial(unsigned s) +{ + obj.mfx_announce.set_serial(s); +} + +void ArduControl::Loader::mfx_locomotive(unsigned id) +{ + MfxInfo info; + info.id = id; + info.protocol = "MFX"; + load_sub(info); + obj.add_mfx_info(info); +} + + +ArduControl::MfxInfo::Loader::Loader(MfxInfo &i): + DataFile::ObjectLoader(i) +{ + add("address", static_cast(&MfxInfo::address)); + add("name", static_cast(&MfxInfo::name)); +} + } // namespace R2C2 diff --git a/source/libr2c2/arducontrol.h b/source/libr2c2/arducontrol.h index c9a88aa..1f45534 100644 --- a/source/libr2c2/arducontrol.h +++ b/source/libr2c2/arducontrol.h @@ -3,6 +3,8 @@ #include #include +#include +#include #include #include #include @@ -12,6 +14,17 @@ namespace R2C2 { class ArduControl: public Driver { +public: + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(ArduControl &); + + private: + void mfx_announce_serial(unsigned); + void mfx_locomotive(unsigned); + }; + private: enum Command { @@ -133,6 +146,12 @@ private: struct MfxInfo: public DetectedLocomotive { + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(MfxInfo &); + }; + unsigned id; }; @@ -211,6 +230,15 @@ private: virtual void process_reply(const char *, unsigned) { } }; + class CommandQueueTask: public Task + { + private: + Queue queue; + + public: + virtual bool get_work(PendingCommand &); + }; + class RefreshTask: public Task { private: @@ -264,6 +292,7 @@ private: virtual bool get_work(PendingCommand &); void set_serial(unsigned); + unsigned get_serial() const { return serial; } }; class MfxSearchTask: public Task @@ -283,6 +312,7 @@ private: virtual bool get_work(PendingCommand &); virtual void process_reply(const char *, unsigned); + void set_next_address(unsigned); bool pop_info(MfxInfo &); }; @@ -313,6 +343,7 @@ private: Msp::IO::Serial serial; unsigned debug; + Msp::FS::Path state_file; ControlledVariable power; @@ -353,6 +384,9 @@ public: virtual const DetectedLocomotive *enumerate_detected_locos(unsigned) const; virtual unsigned add_loco(unsigned, const std::string &, const VehicleType &); +private: + MfxInfoArray::iterator add_mfx_info(const MfxInfo &); +public: virtual void remove_loco(unsigned); virtual void set_loco_speed(unsigned, unsigned); virtual void set_loco_reverse(unsigned, bool); @@ -382,6 +416,8 @@ public: virtual void tick(); virtual void flush(); +private: + void save_state() const; }; } // namespace R2C2 -- 2.45.2