--- /dev/null
+/* $Id$
+
+This file is part of R²C²
+Copyright © 2010 Mikkosoft Productions, Mikko Rasa
+Distributed under the GPL
+*/
+
+#ifndef LIBR2C2_CENTRALSTATION_H_
+#define LIBR2C2_CENTRALSTATION_H_
+
+#include <msp/net/streamsocket.h>
+#include <msp/time/timestamp.h>
+#include "driver.h"
+
+namespace R2C2 {
+
+class CentralStation: public Driver
+{
+private:
+ struct Tag
+ {
+ std::string type;
+ unsigned code;
+ std::string value;
+
+ Tag();
+
+ operator bool() const;
+ };
+
+ struct Message
+ {
+ typedef std::map<std::string, std::string> AttribMap;
+ typedef std::map<unsigned, AttribMap> ObjectMap;
+
+ Tag header;
+ ObjectMap content;
+ Tag footer;
+
+ operator bool() const;
+ };
+
+ enum Error
+ {
+ OK,
+ NERROR_UNKNOWNCOMMAND = 10,
+ NERROR_UNKNOWNARG = 11,
+ NERROR_UNKNOWNPARAM = 12,
+ NERROR_UNKNOWNID = 15,
+ NERROR_SIZE = 20,
+ NERROR_NOTALLOWED = 22,
+ NERROR_NOCONTROL = 25,
+ NERROR_NOCREATE = 28,
+ NERROR_NOARG = 29
+ };
+
+ enum Protocol
+ {
+ MM,
+ MM_27,
+ MFX
+ };
+
+ struct Locomotive
+ {
+ std::string name;
+ Protocol protocol;
+ unsigned address;
+ unsigned speed;
+ bool reverse;
+ unsigned funcs;
+ bool control;
+
+ Locomotive();
+ };
+
+ struct Turnout
+ {
+ enum Symbol
+ {
+ LEFT,
+ RIGHT,
+ THREEWAY,
+ DOUBLESLIP
+ };
+
+ unsigned address;
+ unsigned symbol;
+ unsigned state;
+ unsigned bits;
+ bool synced;
+
+ Turnout();
+ };
+
+ struct Sensor
+ {
+ bool state;
+ Msp::Time::TimeStamp off_timeout;
+
+ Sensor();
+ };
+
+ typedef std::map<unsigned, unsigned> AddressMap;
+ typedef std::map<unsigned, Locomotive> LocoMap;
+ typedef std::map<unsigned, Turnout> TurnoutMap;
+ typedef std::map<unsigned, Sensor> SensorMap;
+
+ Msp::Net::StreamSocket socket;
+ std::list<std::string> cmd_queue;
+ unsigned pending_commands;
+ bool power;
+ bool halted;
+ std::string in_buffer;
+ LocoMap locos;
+ AddressMap loco_addr;
+ bool locos_synced;
+ TurnoutMap turnouts;
+ AddressMap turnout_addr;
+ bool turnouts_synced;
+ SensorMap sensors;
+ std::vector<unsigned> s88;
+ bool sensors_synced;
+
+public:
+ CentralStation(const std::string &);
+ ~CentralStation();
+
+ virtual void set_power(bool);
+ virtual bool get_power() const { return power; }
+ virtual void halt(bool);
+ virtual bool is_halted() const { return halted; }
+
+ virtual const char *enumerate_protocols(unsigned) const;
+ virtual unsigned get_protocol_speed_steps(const std::string &) const;
+
+ virtual void add_loco(unsigned, const std::string &, const VehicleType &);
+ virtual void set_loco_speed(unsigned, unsigned);
+ virtual void set_loco_reverse(unsigned, bool);
+ virtual void set_loco_function(unsigned, unsigned, bool);
+
+ virtual void add_turnout(unsigned, const TrackType &);
+ virtual void set_turnout(unsigned, unsigned);
+ virtual unsigned get_turnout(unsigned) const;
+
+ virtual void add_sensor(unsigned);
+ virtual void set_sensor(unsigned, bool) { }
+ virtual bool get_sensor(unsigned) const;
+
+ virtual void tick();
+ virtual void flush();
+
+private:
+ void command(const std::string &, bool = false);
+ Message receive();
+ void process_reply(const Message &);
+ void process_event(const Message &);
+ void process_object(unsigned, const Message::AttribMap &);
+ Protocol map_protocol(const std::string &) const;
+ template<typename T>
+ unsigned map_address(const std::map<unsigned, T> &, const AddressMap &, unsigned) const;
+ void skip(std::string::iterator &, const std::string::iterator &, const std::string &) const;
+ std::string parse_token(std::string::iterator &, const std::string::iterator &, const std::string &) const;
+ Tag parse_tag(std::string::iterator &, const std::string::iterator &) const;
+ Message parse_message(std::string::iterator &, const std::string::iterator &) const;
+};
+
+} // namespace R2C2
+
+#endif