-/* $Id$
-
-This file is part of the MSP Märklin suite
-Copyright © 2009 Mikkosoft Productions, Mikko Rasa
-Distributed under the GPL
-*/
-
+#include <msp/core/refptr.h>
#include <msp/net/inet.h>
-#include "libmarklin/control.h"
-#include "libmarklin/layout.h"
-#include "libmarklin/locomotive.h"
-#include "libmarklin/locotype.h"
-#include "libmarklin/route.h"
+#include <msp/net/resolve.h>
+#include "libr2c2/catalogue.h"
+#include "libr2c2/driver.h"
+#include "libr2c2/route.h"
+#include "libr2c2/train.h"
+#include "libr2c2/trainrouter.h"
+#include "libr2c2/trainstatus.h"
+#include "libr2c2/vehicletype.h"
#include "server.h"
using namespace std;
using namespace Msp;
-namespace Marklin {
+namespace R2C2 {
-Server::Server(TrafficManager &tm):
- trfc_mgr(tm),
+Server::Server(Layout &l):
+ layout(l),
listen_sock(Net::INET),
event_disp(0)
{
- const list<Train *> &trains = trfc_mgr.get_trains();
- for(list<Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
- train_added(**i);
+ 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));
- listen_sock.listen(Net::InetAddr(0, 8315), 4);
+ const map<unsigned, Train *> &trains = layout.get_trains();
+ for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
+ train_added(*i->second);
+
+ RefPtr<Net::SockAddr> addr = Net::resolve("*", "8315", Net::INET);
+ listen_sock.listen(*addr, 4);
listen_sock.signal_data_available.connect(sigc::mem_fun(this, &Server::incoming_connection));
}
+Server::~Server()
+{ }
+
void Server::use_event_dispatcher(IO::EventDispatcher &ed)
{
event_disp = &ed;
connections.push_back(new Connection(*this, sock));
}
-void Server::train_added(Train &train)
+void Server::driver_state_changed()
{
- Locomotive &loco = train.get_locomotive();
- train.signal_target_speed_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_speed_changed), sigc::ref(train)));
- loco.signal_reverse_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_reverse_changed), sigc::ref(train)));
- loco.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train)));
- train.signal_route_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_route_changed), sigc::ref(train)));
- train.signal_status_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_status_changed), sigc::ref(train)));
-
- TrainInfoPacket pkt;
- pkt.address = loco.get_address();
- pkt.loco_type = loco.get_type().get_article_number();
- pkt.name = train.get_name();
+ DriverStatePacket pkt;
+ pkt.power = layout.get_driver().get_power();
+ pkt.halt = layout.get_driver().is_halted();
send(pkt);
}
-void Server::train_speed_changed(const Train &train, unsigned speed)
+void Server::emergency(Block *, const string &msg)
{
- TrainSpeedPacket pkt;
- pkt.address = train.get_locomotive().get_address();
- pkt.speed = speed;
- pkt.reverse = train.get_locomotive().get_reverse();
+ EmergencyPacket pkt;
+ pkt.message = msg;
send(pkt);
}
-void Server::train_reverse_changed(const Train &train, bool reverse)
+void Server::train_added(Train &train)
{
- TrainSpeedPacket pkt;
- pkt.address = train.get_locomotive().get_address();
- pkt.speed = train.get_target_speed();
- pkt.reverse = reverse;
+ train.signal_control_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_control_changed), sigc::ref(train)));
+ train.signal_function_changed.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_function_changed), sigc::ref(train)));
+ train.signal_ai_event.connect(sigc::bind<0>(sigc::mem_fun(this, &Server::train_ai_event), sigc::ref(train)));
+
+ TrainInfoPacket pkt;
+ pkt.address = train.get_address();
+ pkt.loco_type = layout.get_catalogue().get_name(&train.get_locomotive_type());
+ pkt.name = train.get_name();
send(pkt);
+
+ if(!train.get_ai_of_type<TrainStatus>())
+ new TrainStatus(train);
}
-void Server::train_function_changed(const Train &train, unsigned, bool)
+void Server::train_control_changed(const Train &train, const string &control, float value)
{
- TrainFunctionPacket pkt;
- pkt.address = train.get_locomotive().get_address();
- pkt.functions = train.get_locomotive().get_functions();
+ TrainControlPacket pkt;
+ pkt.address = train.get_address();
+ pkt.control = control;
+ pkt.value = value;
send(pkt);
}
-void Server::train_route_changed(const Train &train, const Route *route)
+void Server::train_function_changed(const Train &train, unsigned, bool)
{
- TrainRoutePacket pkt;
- pkt.address = train.get_locomotive().get_address();
- if(route)
- pkt.route = route->get_name();
+ TrainFunctionPacket pkt;
+ pkt.address = train.get_address();
+ pkt.functions = train.get_functions();
send(pkt);
}
-void Server::train_status_changed(const Train &train, const string &status)
+void Server::train_ai_event(const Train &train, TrainAI &, const TrainAI::Message &ev)
{
- TrainStatusPacket pkt;
- pkt.address = train.get_locomotive().get_address();
- pkt.status = status;
- send(pkt);
+ if(ev.type=="route-changed")
+ {
+ TrainRoutePacket pkt;
+ pkt.address = train.get_address();
+ if(const Route *route = ev.value.value<const Route *>())
+ pkt.route = route->get_name();
+ send(pkt);
+ }
+ else if(ev.type=="status-changed")
+ {
+ TrainStatusPacket pkt;
+ pkt.address = train.get_address();
+ pkt.status = ev.value.value<std::string>();
+ send(pkt);
+ }
}
template<typename P>
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.trfc_mgr.get_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 list<Train *> &trains = server.trfc_mgr.get_trains();
- for(list<Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
+ const set<Route *> &routes = server.layout.get_all<Route>();
+ 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 Catalogue &cat = server.layout.get_catalogue();
+ const map<unsigned, Train *> &trains = server.layout.get_trains();
+ for(map<unsigned, Train *>::const_iterator i=trains.begin(); i!=trains.end(); ++i)
{
- Locomotive &loco = (*i)->get_locomotive();
+ const Train &train = *i->second;
{
TrainInfoPacket pkt;
- pkt.address = loco.get_address();
- pkt.loco_type = loco.get_type().get_article_number();
- pkt.name = (*i)->get_name();
+ pkt.address = train.get_address();
+ pkt.loco_type = cat.get_name(&train.get_locomotive_type());
+ pkt.name = train.get_name();
comm.send(pkt);
}
+ for(unsigned j=0;; ++j)
{
- TrainSpeedPacket pkt;
- pkt.address = loco.get_address();
- pkt.speed = (*i)->get_target_speed();
- pkt.reverse = loco.get_reverse();
+ 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 = loco.get_address();
- pkt.functions = loco.get_functions();
+ pkt.address = train.get_address();
+ pkt.functions = train.get_functions();
comm.send(pkt);
}
+ if(TrainStatus *status = train.get_ai_of_type<TrainStatus>())
{
TrainStatusPacket pkt;
- pkt.address = loco.get_address();
- pkt.status = (*i)->get_status();
+ pkt.address = train.get_address();
+ pkt.status = status->get_status();
comm.send(pkt);
}
- if((*i)->get_route())
+ if(TrainRouter *router = train.get_ai_of_type<TrainRouter>())
{
TrainRoutePacket pkt;
- pkt.address = loco.get_address();
- pkt.route = (*i)->get_route()->get_name();
+ pkt.address = train.get_address();
+ pkt.route = router->get_route()->get_name();
comm.send(pkt);
}
}
void Server::Connection::end_of_file()
{
- socket->close();
stale = true;
}
-void Server::Connection::receive(const TrainSpeedPacket &pkt)
+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
{
- Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
- Train &train = server.trfc_mgr.get_train_by_locomotive(loco);
- if(pkt.reverse!=loco.get_reverse())
- train.set_reverse(pkt.reverse);
- else
- train.set_speed(pkt.speed);
+ Train &train = server.layout.get_train(pkt.address);
+ train.set_control(pkt.control, pkt.value);
}
- catch(const Exception &e)
+ catch(const exception &e)
{
error(e.what());
}
{
try
{
- Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
+ Train &train = server.layout.get_train(pkt.address);
for(unsigned i=0; i<9; ++i)
- if(((pkt.functions^loco.get_functions())>>i)&1)
- loco.set_function(i, (pkt.functions>>i)&1);
+ if(((pkt.functions^train.get_functions())>>i)&1)
+ train.set_function(i, (pkt.functions>>i)&1);
}
- catch(const Exception &e)
+ catch(const exception &e)
{
error(e.what());
}
{
try
{
- Locomotive &loco = server.trfc_mgr.get_control().get_locomotive(pkt.address);
- Train &train = server.trfc_mgr.get_train_by_locomotive(loco);
+ Train &train = server.layout.get_train(pkt.address);
if(pkt.route.empty())
- train.set_route(0);
+ train.ai_message(TrainAI::Message("clear-route"));
else
{
- Route &route = server.trfc_mgr.get_layout().get_route(pkt.route);
- train.set_route(&route);
+ Route &route = server.layout.get_route(pkt.route);
+ train.ai_message(TrainAI::Message("set-route", &route));
}
}
- catch(const Exception &e)
+ catch(const exception &e)
{
error(e.what());
}
comm.send(pkt);
}
-} // namespace Marklin
+} // namespace R2C2