-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2009-2010 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
#include <msp/net/inet.h>
-#include "libmarklin/route.h"
-#include "libmarklin/train.h"
-#include "libmarklin/vehicletype.h"
+#include "libr2c2/driver.h"
+#include "libr2c2/route.h"
+#include "libr2c2/train.h"
+#include "libr2c2/vehicletype.h"
#include "server.h"
using namespace std;
using namespace Msp;
-namespace Marklin {
+namespace R2C2 {
Server::Server(Layout &l):
layout(l),
listen_sock(Net::INET),
event_disp(0)
{
+ layout.get_driver().signal_power.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
+ layout.get_driver().signal_halt.connect(sigc::hide(sigc::mem_fun(this, &Server::driver_state_changed)));
+ layout.signal_emergency.connect(sigc::mem_fun(this, &Server::emergency));
+
layout.signal_train_added.connect(sigc::mem_fun(this, &Server::train_added));
const map<unsigned, Train *> &trains = layout.get_trains();
connections.push_back(new Connection(*this, sock));
}
+void Server::driver_state_changed()
+{
+ DriverStatePacket pkt;
+ pkt.power = layout.get_driver().get_power();
+ pkt.halt = layout.get_driver().is_halted();
+ send(pkt);
+}
+
+void Server::emergency(const string &msg)
+{
+ EmergencyPacket pkt;
+ pkt.message = msg;
+ send(pkt);
+}
+
void Server::train_added(Train &train)
{
train.signal_control_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_control_changed), sigc::ref(train)));
TrainInfoPacket pkt;
pkt.address = train.get_address();
- pkt.loco_type = train.get_locomotive_type().get_article_number();
+ pkt.loco_type = train.get_locomotive_type().get_article_number().str();
pkt.name = train.get_name();
send(pkt);
+
+ TrainStatus *status = new TrainStatus(train);
+ status->set_tag("server:status");
+ status->signal_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
}
void Server::train_control_changed(const Train &train, const string &control, float value)
void Server::send(const P &pkt)
{
for(vector<Connection *>::const_iterator i=connections.begin(); i!=connections.end(); ++i)
- if(!(*i)->stale)
- (*i)->comm.send(pkt);
+ if(!(*i)->stale && (*i)->comm.is_handshake_done())
+ {
+ try
+ {
+ (*i)->comm.send(pkt);
+ }
+ catch(...)
+ {
+ (*i)->stale = true;
+ }
+ }
}
void Server::Connection::handshake_done()
{
- const set<Route *> &routes = server.layout.get_routes();
- for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
{
- RouteInfoPacket pkt;
- pkt.name = (*i)->get_name();
+ DriverStatePacket pkt;
+ pkt.power = server.layout.get_driver().get_power();
+ pkt.halt = server.layout.get_driver().is_halted();
comm.send(pkt);
}
+ const set<Route *> &routes = server.layout.get_routes();
+ for(set<Route *>::const_iterator i=routes.begin(); i!=routes.end(); ++i)
+ if(!(*i)->is_temporary())
+ {
+ RouteInfoPacket pkt;
+ pkt.name = (*i)->get_name();
+ comm.send(pkt);
+ }
+
const map<unsigned, Train *> &trains = server.layout.get_trains();
for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
{
TrainInfoPacket pkt;
pkt.address = train.get_address();
- pkt.loco_type = train.get_locomotive_type().get_article_number();
+ pkt.loco_type = train.get_locomotive_type().get_article_number().str();
pkt.name = train.get_name();
comm.send(pkt);
}
- // XXX Need control enumeration to send control packets
+ for(unsigned j=0;; ++j)
+ {
+ const char *name = train.get_controller().enumerate_controls(j);
+ if(!name)
+ break;
+
+ TrainControlPacket pkt;
+ pkt.address = train.get_address();
+ pkt.control = name;
+ pkt.value = train.get_control(name);
+ comm.send(pkt);
+ }
{
TrainFunctionPacket pkt;
pkt.address = train.get_address();
pkt.functions = train.get_functions();
comm.send(pkt);
}
+ if(TrainStatus *status = dynamic_cast<TrainStatus *>(train.get_tagged_ai("server:status")))
{
TrainStatusPacket pkt;
pkt.address = train.get_address();
- pkt.status = train.get_status();
+ pkt.status = status->get_status();
comm.send(pkt);
}
if(train.get_route())
stale = true;
}
+void Server::Connection::receive(const DriverStatePacket &pkt)
+{
+ Driver &driver = server.layout.get_driver();
+ if(pkt.power!=driver.get_power())
+ driver.set_power(pkt.power);
+ if(pkt.halt!=driver.is_halted())
+ driver.halt(pkt.halt);
+}
+
void Server::Connection::receive(const TrainControlPacket &pkt)
{
try
comm.send(pkt);
}
-} // namespace Marklin
+} // namespace R2C2