Subversion Repositories HomeAutomation

Rev

Rev 1606 | Rev 1642 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 1606 Rev 1627
Line 19... Line 19...
19
 */
19
 */
20
 
20
 
21
#include "Node.h"
21
#include "Node.h"
22
 
22
 
23
#include <boost/date_time/posix_time/posix_time.hpp>
23
#include <boost/date_time/posix_time/posix_time.hpp>
-
 
24
#include <boost/lexical_cast.hpp>
24
 
25
 
-
 
26
#include "Manager.h"
25
#include "Message.h"
27
#include "Message.h"
26
#include "broker/Manager.h"
28
#include "broker/Manager.h"
27
 
29
 
28
namespace atom {
30
namespace atom {
29
namespace can {
31
namespace can {
30
   
32
 
-
 
33
Node::TransitionList Node::transitions_;
-
 
34
   
31
Node::Node(Node::Id id)
35
Node::Node(Node::Id id) : LOG("can::Node")
32
{
36
{
33
    this->state_ = STATE_OFFLINE;
37
    this->state_ = STATE_NORM_OFFLINE;
34
    this->id_ = id;
38
    this->id_ = id;
35
}
39
}
36
 
40
 
37
Node::~Node()
41
Node::~Node()
38
{
42
{
39
 
43
 
-
 
44
}
-
 
45
 
-
 
46
void Node::ConnectSlots(const SignalOnNewState::slot_type& slot_on_new_state)
-
 
47
{
-
 
48
    this->signal_on_new_state_.connect(slot_on_new_state);
40
}
49
}
41
 
50
 
42
Node::Id Node::GetId()
51
Node::Id Node::GetId()
43
{
52
{
44
    return this->id_;
53
    return this->id_;
45
}
54
}
46
 
55
 
47
Node::State Node::GetState()
56
Node::State Node::GetState()
48
{
57
{
49
    return this->state_;
58
    return this->state_;
50
}
59
}
51
 
60
 
52
void Node::SetState(Node::State state)
61
void Node::SetupStateMachine()
-
 
62
{
-
 
63
    // Normal flow
-
 
64
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_BIOS_START,        STATE_NORM_ONLINE);
-
 
65
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_APP_START,         STATE_NORM_LIST);
-
 
66
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_HEARTBEAT,         STATE_NORM_LIST);
-
 
67
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_PROGRAM_BIOS,      STATE_BPGM_OFFLINE);
-
 
68
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_PROGRAM_APP,       STATE_APGM_OFFLINE);
-
 
69
    Node::AddTransition(STATE_NORM_OFFLINE,          EVENT_RESET,             STATE_NO_CHANGE);
-
 
70
   
-
 
71
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_BIOS_START,        STATE_NORM_ONLINE);
-
 
72
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_APP_START,         STATE_NORM_LIST);
-
 
73
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_HEARTBEAT,         STATE_NORM_LIST);
-
 
74
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_PROGRAM_BIOS,      STATE_BPGM_OFFLINE);
-
 
75
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_PROGRAM_APP,       STATE_APGM_OFFLINE);
-
 
76
    Node::AddTransition(STATE_NORM_ONLINE,           EVENT_RESET,             STATE_NORM_OFFLINE);
-
 
77
   
-
 
78
    Node::AddTransition(STATE_NORM_LIST,             EVENT_BIOS_START,        STATE_NORM_ONLINE);
-
 
79
    Node::AddTransition(STATE_NORM_LIST,             EVENT_APP_START,         STATE_NORM_LIST);
-
 
80
    Node::AddTransition(STATE_NORM_LIST,             EVENT_HEARTBEAT,         STATE_NO_CHANGE);
-
 
81
    Node::AddTransition(STATE_NORM_LIST,             EVENT_LIST_DONE,         STATE_NORM_INITIALIZED);
-
 
82
    Node::AddTransition(STATE_NORM_LIST,             EVENT_PROGRAM_BIOS,      STATE_BPGM_OFFLINE);
-
 
83
    Node::AddTransition(STATE_NORM_LIST,             EVENT_PROGRAM_APP,       STATE_APGM_OFFLINE);
-
 
84
    Node::AddTransition(STATE_NORM_LIST,             EVENT_RESET,             STATE_NORM_OFFLINE);
-
 
85
   
-
 
86
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_BIOS_START,        STATE_NORM_ONLINE);
-
 
87
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_APP_START,         STATE_NORM_LIST);
-
 
88
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_HEARTBEAT,         STATE_NO_CHANGE);
-
 
89
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_PROGRAM_BIOS,      STATE_BPGM_OFFLINE);
-
 
90
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_PROGRAM_APP,       STATE_APGM_OFFLINE);
-
 
91
    Node::AddTransition(STATE_NORM_INITIALIZED,      EVENT_RESET,             STATE_NORM_OFFLINE);
-
 
92
   
-
 
93
   
-
 
94
    // Program bios flow
-
 
95
    Node::AddTransition(STATE_BPGM_OFFLINE,          EVENT_BIOS_START,        STATE_BPGM_START);
-
 
96
   
-
 
97
    Node::AddTransition(STATE_BPGM_START,            EVENT_PGM_ACK,           STATE_BPGM_DATA);
-
 
98
    Node::AddTransition(STATE_BPGM_START,            EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
99
 
-
 
100
    Node::AddTransition(STATE_BPGM_DATA,             EVENT_PGM_ACK,           STATE_BPGM_DATA); // If there is no more data to send STATE_PGM_END will be set instead
-
 
101
    Node::AddTransition(STATE_BPGM_DATA,             EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
102
   
-
 
103
    Node::AddTransition(STATE_BPGM_END,              EVENT_PGM_ACK,           STATE_BPGM_COPY);
-
 
104
    Node::AddTransition(STATE_BPGM_END,              EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
105
   
-
 
106
    Node::AddTransition(STATE_BPGM_COPY,             EVENT_BIOS_START,        STATE_NORM_ONLINE); // Return to normal flow
-
 
107
   
-
 
108
   
-
 
109
    // Program application flow
-
 
110
    Node::AddTransition(STATE_APGM_OFFLINE,          EVENT_BIOS_START,        STATE_APGM_START);
-
 
111
   
-
 
112
    Node::AddTransition(STATE_APGM_START,            EVENT_PGM_ACK,           STATE_APGM_DATA);
-
 
113
    Node::AddTransition(STATE_APGM_START,            EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
114
   
-
 
115
    Node::AddTransition(STATE_APGM_DATA,             EVENT_PGM_ACK,           STATE_APGM_DATA); // If there is no more data to send STATE_PGM_END will be set instead
-
 
116
    Node::AddTransition(STATE_APGM_DATA,             EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
117
   
-
 
118
    Node::AddTransition(STATE_APGM_END,              EVENT_PGM_ACK,           STATE_NORM_OFFLINE); // Return to normal flow
-
 
119
    Node::AddTransition(STATE_APGM_END,              EVENT_PGM_NACK,          STATE_NORM_OFFLINE); // Return to normal flow
-
 
120
}
-
 
121
 
-
 
122
void Node::AddTransition(Node::State current_state, Node::Event event, State target_state)
-
 
123
{
-
 
124
    Node::transitions_[current_state][event] = target_state;
-
 
125
}
-
 
126
 
-
 
127
Node::State Node::GetTransitionTarget(Node::Event event)
-
 
128
{
-
 
129
    Node::TransitionList::iterator it1 = Node::transitions_.find(this->state_);
-
 
130
   
-
 
131
    if (it1 == Node::transitions_.end())
-
 
132
    {
-
 
133
        LOG.Warning("No transitions found for current state " + boost::lexical_cast<std::string>(this->state_));
-
 
134
        return STATE_INVALID;
-
 
135
    }
-
 
136
   
-
 
137
    Node::Transition::iterator it2 = it1->second.find(event);
-
 
138
   
-
 
139
    if (it2 == it1->second.end())
-
 
140
    {
-
 
141
        LOG.Warning("No transitions found for current state " + boost::lexical_cast<std::string>(this->state_) + " for event " + boost::lexical_cast<std::string>(event));
-
 
142
        return STATE_INVALID;
-
 
143
    }
-
 
144
   
-
 
145
    return it2->second;
-
 
146
}
-
 
147
 
-
 
148
void Node::Trigger(Node::Event event, type::StringMap variables)
53
{
149
{
-
 
150
    this->ResetTimeout();
-
 
151
   
-
 
152
    State target_state = this->GetTransitionTarget(event);
-
 
153
   
-
 
154
    LOG.Debug("Trigger called: current state: " + boost::lexical_cast<std::string>(this->state_) + ", event: " + boost::lexical_cast<std::string>(event) + ", target state:"  + boost::lexical_cast<std::string>(target_state));
-
 
155
   
-
 
156
    if (target_state == STATE_INVALID)
-
 
157
    {
-
 
158
        this->SendReset();
-
 
159
        target_state = STATE_NORM_OFFLINE;
-
 
160
    }
-
 
161
    else if (target_state == STATE_NO_CHANGE)
-
 
162
    {
-
 
163
        return;
-
 
164
    }
-
 
165
    else if (target_state == STATE_NORM_LIST)
-
 
166
    {
-
 
167
        this->SendListRequest();
-
 
168
    }
-
 
169
    else if (target_state == STATE_NORM_OFFLINE)
-
 
170
    {
-
 
171
        this->SendReset();
-
 
172
    }
-
 
173
    else if (target_state == STATE_BPGM_OFFLINE || target_state == STATE_APGM_OFFLINE)
-
 
174
    {
-
 
175
        this->SendReset();
-
 
176
    }
-
 
177
    else if (target_state == STATE_BPGM_START || target_state == STATE_APGM_START)
-
 
178
    {
-
 
179
        // TODO: Send out pgm start
-
 
180
    }
-
 
181
    else if (target_state == STATE_BPGM_DATA || target_state == STATE_APGM_DATA)
-
 
182
    {
-
 
183
        // TODO: if more data send it
-
 
184
        // TODO: if no more data send pgm end and set target_state = STATE_APGM_END or target_state = STATE_BPGM_END
-
 
185
    }
-
 
186
   
-
 
187
    if (this->state_ != target_state)
-
 
188
    {
-
 
189
        this->signal_on_new_state_(this->id_, this->state_, target_state);
-
 
190
    }
-
 
191
   
54
    this->state_ = state;
192
    this->state_ = target_state;
55
}
193
}
56
 
194
 
57
bool Node::CheckTimeout()
195
bool Node::CheckTimeout()
58
{
196
{
59
    if (this->state_ == STATE_OFFLINE)
197
    if (this->state_ == STATE_NORM_OFFLINE)
60
    {
198
    {
61
        return true;
199
        return true;
62
    }
200
    }
63
   
201
   
64
    if (this->last_active_ + 10 < time(NULL))
202
    if (this->last_active_ + 10 < time(NULL))
65
    {
203
    {
66
        this->state_ = STATE_OFFLINE;
204
        this->state_ = STATE_NORM_OFFLINE;
67
        return false;
205
        return false;
68
    }
206
    }
69
   
207
   
70
    return true;
208
    return true;
71
}
209
}
72
 
210
 
73
void Node::ResetTimeout()
211
void Node::ResetTimeout()
74
{
212
{
75
    this->last_active_ = time(NULL);
213
    this->last_active_ = time(NULL);
-
 
214
}
-
 
215
 
-
 
216
void Node::SendReset()
-
 
217
{
-
 
218
    LOG.Debug("Sending node reset to " + type::ToHex(this->id_));
-
 
219
    Message* payload = new Message("nmt", "", "", 0, "Reset");
-
 
220
    payload->SetVariable("HardwareId", boost::lexical_cast<std::string>(this->id_));
-
 
221
   
-
 
222
    broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), Manager::Instance().get())));
-
 
223
}
-
 
224
 
-
 
225
void Node::SendListRequest()
-
 
226
{
-
 
227
    LOG.Debug("Sending module listing on node " + type::ToHex(this->id_));
-
 
228
    Message* payload = new Message("mnmt", "To_Owner", "", 0, "List");
-
 
229
    payload->SetVariable("HardwareId", boost::lexical_cast<std::string>(this->id_));
-
 
230
   
-
 
231
    broker::Manager::Instance()->Post(broker::Message::Pointer(new broker::Message(broker::Message::CAN_MESSAGE, broker::Message::PayloadPointer(payload), Manager::Instance().get())));
76
}
232
}
77
   
233
 
78
}; // namespace can
234
}; // namespace can
79
}; // namespace atom
235
}; // namespace atom