]> git.tdb.fi Git - r2c2.git/blob - source/libr2c2/dummy.cpp
Add turnout failure simulation to the dummy driver
[r2c2.git] / source / libr2c2 / dummy.cpp
1 #include <cstdlib>
2 #include <msp/strings/utils.h>
3 #include <msp/time/utils.h>
4 #include "dummy.h"
5
6 using namespace std;
7 using namespace Msp;
8
9 namespace R2C2 {
10
11 Dummy::Dummy(const Options &opts):
12         power(true),
13         turnout_delay(opts.get("turnout_delay", 0.0f)*Time::sec),
14         turnout_fail_rate(opts.get("turnout_fail_rate", 0.0f)*RAND_MAX)
15 { }
16
17 void Dummy::set_power(bool p)
18 {
19         power = p;
20         signal_power.emit(power);
21 }
22
23 void Dummy::halt(bool h)
24 {
25         halted = h;
26         if(halted)
27         {
28                 for(map<unsigned, LocoState>::iterator i=locos.begin(); i!=locos.end(); ++i)
29                         if(i->second.speed)
30                                 set_loco_speed(i->first, 0);
31         }
32         signal_halt.emit(halted);
33 }
34
35 const char *Dummy::enumerate_protocols(unsigned i) const
36 {
37         if(i==0)
38                 return "dummy";
39         return 0;
40 }
41
42 unsigned Dummy::get_protocol_speed_steps(const string &) const
43 {
44         return 0;
45 }
46
47 unsigned Dummy::add_turnout(unsigned addr, const TrackType &)
48 {
49         turnouts[addr];
50         return addr;
51 }
52
53 void Dummy::set_turnout(unsigned addr, unsigned state)
54 {
55         TurnoutState &turnout = turnouts[addr];
56         if(turnout.state==state && turnout.pending==state)
57         {
58                 signal_turnout.emit(addr, state);
59                 return;
60         }
61
62         turnout.pending = state;
63         if(turnout_delay)
64                 turnout.timeout = Time::now()+turnout_delay;
65         else
66         {
67                 if(!turnout_fail_rate || rand()>=turnout_fail_rate)
68                         turnout.state = state;
69                 signal_turnout.emit(addr, state);
70         }
71 }
72
73 unsigned Dummy::get_turnout(unsigned addr) const
74 {
75         map<unsigned, TurnoutState>::const_iterator i = turnouts.find(addr);
76         if(i!=turnouts.end())
77                 return i->second.state;
78         return 0;
79 }
80
81 void Dummy::set_loco_speed(unsigned addr, unsigned speed)
82 {
83         if(speed && halted)
84                 return;
85
86         LocoState &loco = locos[addr];
87         loco.speed = speed;
88         signal_loco_speed.emit(addr, speed, loco.reverse);
89 }
90
91 void Dummy::set_loco_reverse(unsigned addr, bool rev)
92 {
93         LocoState &loco = locos[addr];
94         loco.reverse = rev;
95         signal_loco_speed.emit(addr, loco.speed, rev);
96 }
97
98 void Dummy::set_loco_function(unsigned addr, unsigned func, bool state)
99 {
100         signal_loco_function.emit(addr, func, state);
101 }
102
103 void Dummy::set_sensor(unsigned addr, bool state)
104 {
105         if(sensors[addr]!=state)
106         {
107                 sensors[addr] = state;
108                 signal_sensor.emit(addr, state);
109         }
110 }
111
112 bool Dummy::get_sensor(unsigned addr) const
113 {
114         map<unsigned, bool>::const_iterator i = sensors.find(addr);
115         if(i!=sensors.end())
116                 return i->second;
117         return false;
118 }
119
120 void Dummy::tick()
121 {
122         Time::TimeStamp t = Time::now();
123         for(map<unsigned, TurnoutState>::iterator i=turnouts.begin(); i!=turnouts.end(); ++i)
124         {
125                 if(i->second.timeout && t>=i->second.timeout)
126                 {
127                         if(turnout_fail_rate && rand()<turnout_fail_rate)
128                         {
129                                 signal_turnout_failed.emit(i->first);
130                                 i->second.pending = i->second.state;
131                         }
132                         i->second.state = i->second.pending;
133                         i->second.timeout = Time::TimeStamp();
134                         signal_turnout.emit(i->first, i->second.state);
135                 }
136         }
137 }
138
139 } // namespace R2C2