Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(293)

Side by Side Diff: tools/battor_agent/battor_agent.cc

Issue 2826913002: [BattOr] Retry battor_agent commands when they fail. (Closed)
Patch Set: Final comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | tools/battor_agent/battor_agent_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 #include "tools/battor_agent/battor_agent.h" 4 #include "tools/battor_agent/battor_agent.h"
5 5
6 #include <iomanip> 6 #include <iomanip>
7 7
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/threading/thread_task_runner_handle.h" 9 #include "base/threading/thread_task_runner_handle.h"
10 #include "tools/battor_agent/battor_connection_impl.h" 10 #include "tools/battor_agent/battor_connection_impl.h"
11 #include "tools/battor_agent/battor_sample_converter.h" 11 #include "tools/battor_agent/battor_sample_converter.h"
12 12
13 using std::vector; 13 using std::vector;
14 14
15 namespace battor { 15 namespace battor {
16 16
17 namespace { 17 namespace {
18 18
19 // The maximum number of times to retry when initializing a BattOr. 19 // The maximum number of times to retry a command.
20 const uint8_t kMaxInitAttempts = 20; 20 const uint8_t kMaxCommandAttempts = 10;
21
22 // The maximum number of times to retry the StartTracing command.
23 const uint8_t kMaxStartTracingAttempts = 5;
24
25 // The number of milliseconds to wait before retrying initialization.
26 const uint16_t kInitRetryDelayMilliseconds = 100;
27
28 // The maximum number of times to retry when reading a message.
29 const uint8_t kMaxReadAttempts = 20;
30
31 // The number of milliseconds to wait before trying to read a message again.
32 const uint8_t kReadRetryDelayMilliseconds = 1;
33 21
34 // The amount of time we need to wait after recording a clock sync marker in 22 // The amount of time we need to wait after recording a clock sync marker in
35 // order to ensure that the sample we synced to doesn't get thrown out. 23 // order to ensure that the sample we synced to doesn't get thrown out.
36 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; 24 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100;
37 25
38 // The number of seconds allowed for a given action before timing out. 26 // The number of seconds to wait before retrying a command.
39 const uint8_t kBattOrTimeoutSeconds = 4; 27 const uint16_t kCommandRetryDelaySeconds = 2;
28
29 // The number of seconds allowed for a control message before timing out.
30 const uint8_t kBattOrControlMessageTimeoutSeconds = 2;
31
32 // The number of seconds allowed for connection to open before timing out.
33 const uint8_t kBattOrConnectionTimeoutSeconds = 4;
40 34
41 // Returns true if the specified vector of bytes decodes to a message that is an 35 // Returns true if the specified vector of bytes decodes to a message that is an
42 // ack for the specified control message type. 36 // ack for the specified control message type.
43 bool IsAckOfControlCommand(BattOrMessageType message_type, 37 bool IsAckOfControlCommand(BattOrMessageType message_type,
44 BattOrControlMessageType control_message_type, 38 BattOrControlMessageType control_message_type,
45 const vector<char>& msg) { 39 const vector<char>& msg) {
46 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) 40 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK)
47 return false; 41 return false;
48 42
49 if (msg.size() != sizeof(BattOrControlMessageAck)) 43 if (msg.size() != sizeof(BattOrControlMessageAck))
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 Listener* listener, 110 Listener* listener,
117 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, 111 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner,
118 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) 112 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
119 : connection_(new BattOrConnectionImpl(path, 113 : connection_(new BattOrConnectionImpl(path,
120 this, 114 this,
121 file_thread_task_runner, 115 file_thread_task_runner,
122 ui_thread_task_runner)), 116 ui_thread_task_runner)),
123 listener_(listener), 117 listener_(listener),
124 last_action_(Action::INVALID), 118 last_action_(Action::INVALID),
125 command_(Command::INVALID), 119 command_(Command::INVALID),
126 num_init_attempts_(0), 120 num_command_attempts_(0) {
127 num_start_tracing_attempts_(0),
128 num_read_attempts_(0) {
129 // We don't care what thread the constructor is called on - we only care that 121 // We don't care what thread the constructor is called on - we only care that
130 // all of the other method invocations happen on the same thread. 122 // all of the other method invocations happen on the same thread.
131 thread_checker_.DetachFromThread(); 123 thread_checker_.DetachFromThread();
132 } 124 }
133 125
134 BattOrAgent::~BattOrAgent() { 126 BattOrAgent::~BattOrAgent() {
135 DCHECK(thread_checker_.CalledOnValidThread()); 127 DCHECK(thread_checker_.CalledOnValidThread());
136 } 128 }
137 129
138 void BattOrAgent::StartTracing() { 130 void BattOrAgent::StartTracing() {
139 DCHECK(thread_checker_.CalledOnValidThread()); 131 DCHECK(thread_checker_.CalledOnValidThread());
140 132
141 // When tracing is restarted, all previous clock sync markers are invalid. 133 // When tracing is restarted, all previous clock sync markers are invalid.
142 clock_sync_markers_.clear(); 134 clock_sync_markers_.clear();
143 last_clock_sync_time_ = base::TimeTicks(); 135 last_clock_sync_time_ = base::TimeTicks();
144 136
145 num_start_tracing_attempts_ = 1;
146 command_ = Command::START_TRACING; 137 command_ = Command::START_TRACING;
147 PerformAction(Action::REQUEST_CONNECTION); 138 PerformAction(Action::REQUEST_CONNECTION);
148 } 139 }
149 140
150 void BattOrAgent::StopTracing() { 141 void BattOrAgent::StopTracing() {
151 DCHECK(thread_checker_.CalledOnValidThread()); 142 DCHECK(thread_checker_.CalledOnValidThread());
152 143
153 command_ = Command::STOP_TRACING; 144 command_ = Command::STOP_TRACING;
154 PerformAction(Action::REQUEST_CONNECTION); 145 PerformAction(Action::REQUEST_CONNECTION);
155 } 146 }
156 147
157 void BattOrAgent::RecordClockSyncMarker(const std::string& marker) { 148 void BattOrAgent::RecordClockSyncMarker(const std::string& marker) {
158 DCHECK(thread_checker_.CalledOnValidThread()); 149 DCHECK(thread_checker_.CalledOnValidThread());
159 150
160 command_ = Command::RECORD_CLOCK_SYNC_MARKER; 151 command_ = Command::RECORD_CLOCK_SYNC_MARKER;
161 pending_clock_sync_marker_ = marker; 152 pending_clock_sync_marker_ = marker;
162 PerformAction(Action::REQUEST_CONNECTION); 153 PerformAction(Action::REQUEST_CONNECTION);
163 } 154 }
164 155
165 void BattOrAgent::GetFirmwareGitHash() { 156 void BattOrAgent::GetFirmwareGitHash() {
166 DCHECK(thread_checker_.CalledOnValidThread()); 157 DCHECK(thread_checker_.CalledOnValidThread());
167 158
168 command_ = Command::GET_FIRMWARE_GIT_HASH; 159 command_ = Command::GET_FIRMWARE_GIT_HASH;
169 PerformAction(Action::REQUEST_CONNECTION); 160 PerformAction(Action::REQUEST_CONNECTION);
170 } 161 }
171 162
172 void BattOrAgent::BeginConnect() { 163 void BattOrAgent::BeginConnect() {
173 DCHECK(thread_checker_.CalledOnValidThread()); 164 DCHECK(thread_checker_.CalledOnValidThread());
174 165
166 SetActionTimeout(kBattOrConnectionTimeoutSeconds);
167
175 connection_->Open(); 168 connection_->Open();
176 } 169 }
177 170
178 void BattOrAgent::OnConnectionOpened(bool success) { 171 void BattOrAgent::OnConnectionOpened(bool success) {
179 // Return immediately if opening the connection already timed out. 172 // Cancel timeout because the connection was opened in time.
180 if (timeout_callback_.IsCancelled())
181 return;
182 timeout_callback_.Cancel(); 173 timeout_callback_.Cancel();
183 174
184 if (!success) { 175 if (!success) {
185 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); 176 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED);
186 return; 177 return;
187 } 178 }
188 179
189 switch (command_) { 180 switch (command_) {
190 case Command::START_TRACING: 181 case Command::START_TRACING:
191 num_init_attempts_ = 1;
192 PerformAction(Action::SEND_INIT); 182 PerformAction(Action::SEND_INIT);
193 return; 183 return;
194 case Command::STOP_TRACING: 184 case Command::STOP_TRACING:
195 PerformAction(Action::SEND_EEPROM_REQUEST); 185 PerformAction(Action::SEND_EEPROM_REQUEST);
196 return; 186 return;
197 case Command::RECORD_CLOCK_SYNC_MARKER: 187 case Command::RECORD_CLOCK_SYNC_MARKER:
198 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); 188 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST);
199 return; 189 return;
200 case Command::GET_FIRMWARE_GIT_HASH: 190 case Command::GET_FIRMWARE_GIT_HASH:
201 num_init_attempts_ = 1;
202 PerformAction(Action::SEND_INIT); 191 PerformAction(Action::SEND_INIT);
203 return; 192 return;
204 case Command::INVALID: 193 case Command::INVALID:
205 NOTREACHED(); 194 NOTREACHED();
195 return;
206 } 196 }
207 } 197 }
208 198
209 void BattOrAgent::OnBytesSent(bool success) { 199 void BattOrAgent::OnBytesSent(bool success) {
210 DCHECK(thread_checker_.CalledOnValidThread()); 200 DCHECK(thread_checker_.CalledOnValidThread());
211 201
212 // Return immediately if whatever action we were trying to perform already
213 // timed out.
214 if (timeout_callback_.IsCancelled())
215 return;
216 timeout_callback_.Cancel();
217
218 if (!success) { 202 if (!success) {
219 CompleteCommand(BATTOR_ERROR_SEND_ERROR); 203 CompleteCommand(BATTOR_ERROR_SEND_ERROR);
220 return; 204 return;
221 } 205 }
222 206
223 switch (last_action_) { 207 switch (last_action_) {
224 case Action::SEND_INIT: 208 case Action::SEND_INIT:
225 PerformAction(Action::READ_INIT_ACK); 209 PerformAction(Action::READ_INIT_ACK);
226 return; 210 return;
227 case Action::SEND_SET_GAIN: 211 case Action::SEND_SET_GAIN:
228 PerformAction(Action::READ_SET_GAIN_ACK); 212 PerformAction(Action::READ_SET_GAIN_ACK);
229 return; 213 return;
230 case Action::SEND_START_TRACING: 214 case Action::SEND_START_TRACING:
231 PerformAction(Action::READ_START_TRACING_ACK); 215 PerformAction(Action::READ_START_TRACING_ACK);
232 return; 216 return;
233 case Action::SEND_EEPROM_REQUEST: 217 case Action::SEND_EEPROM_REQUEST:
234 num_read_attempts_ = 1;
235 PerformAction(Action::READ_EEPROM); 218 PerformAction(Action::READ_EEPROM);
236 return; 219 return;
237 case Action::SEND_SAMPLES_REQUEST: 220 case Action::SEND_SAMPLES_REQUEST:
238 num_read_attempts_ = 1;
239 PerformAction(Action::READ_CALIBRATION_FRAME); 221 PerformAction(Action::READ_CALIBRATION_FRAME);
240 return; 222 return;
241 case Action::SEND_CURRENT_SAMPLE_REQUEST: 223 case Action::SEND_CURRENT_SAMPLE_REQUEST:
242 num_read_attempts_ = 1;
243 PerformAction(Action::READ_CURRENT_SAMPLE); 224 PerformAction(Action::READ_CURRENT_SAMPLE);
244 return; 225 return;
245 case Action::SEND_GIT_HASH_REQUEST: 226 case Action::SEND_GIT_HASH_REQUEST:
246 num_read_attempts_ = 1;
247 PerformAction(Action::READ_GIT_HASH); 227 PerformAction(Action::READ_GIT_HASH);
248 return; 228 return;
249 default: 229 default:
250 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 230 NOTREACHED();
231 return;
251 } 232 }
252 } 233 }
253 234
254 void BattOrAgent::OnMessageRead(bool success, 235 void BattOrAgent::OnMessageRead(bool success,
255 BattOrMessageType type, 236 BattOrMessageType type,
256 std::unique_ptr<vector<char>> bytes) { 237 std::unique_ptr<vector<char>> bytes) {
257 // Return immediately if whatever action we were trying to perform already
258 // timed out.
259 if (timeout_callback_.IsCancelled())
260 return;
261 timeout_callback_.Cancel();
262
263 if (!success) { 238 if (!success) {
264 switch (last_action_) { 239 switch (last_action_) {
265 case Action::READ_GIT_HASH: 240 case Action::READ_GIT_HASH:
241 case Action::READ_INIT_ACK:
242 case Action::READ_SET_GAIN_ACK:
243 case Action::READ_START_TRACING_ACK:
266 case Action::READ_EEPROM: 244 case Action::READ_EEPROM:
267 case Action::READ_CALIBRATION_FRAME: 245 case Action::READ_CALIBRATION_FRAME:
268 case Action::READ_DATA_FRAME: 246 case Action::READ_DATA_FRAME:
269 case Action::READ_CURRENT_SAMPLE: 247 RetryCommand();
270 if (num_read_attempts_++ > kMaxReadAttempts) {
271 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
272 return;
273 }
274
275 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds(
276 kReadRetryDelayMilliseconds));
277 return; 248 return;
278 249
279 // Retry sending an INIT if it an ACK is not received. 250 case Action::READ_CURRENT_SAMPLE:
280 case Action::SEND_INIT: 251 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
281 case Action::READ_INIT_ACK:
282 if (num_init_attempts_++ < kMaxInitAttempts) {
283 PerformDelayedAction(Action::SEND_INIT,
284 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
285 } else {
286 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
287 }
288
289 return;
290
291 case Action::READ_START_TRACING_ACK:
292 if (num_start_tracing_attempts_++ < kMaxStartTracingAttempts) {
293 num_init_attempts_ = 1;
294 PerformAction(Action::SEND_INIT);
295 } else {
296 CompleteCommand(BATTOR_ERROR_TOO_MANY_START_TRACING_RETRIES);
297 }
298
299 return; 252 return;
300 253
301 default: 254 default:
302 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 255 NOTREACHED();
303 return; 256 return;
304 } 257 }
305 } 258 }
306 259
260 // Successfully read a message, cancel any timeouts.
261 timeout_callback_.Cancel();
262
307 switch (last_action_) { 263 switch (last_action_) {
308 case Action::READ_INIT_ACK: 264 case Action::READ_INIT_ACK:
309 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, 265 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT,
310 *bytes)) { 266 *bytes)) {
311 if (num_init_attempts_++ < kMaxInitAttempts) { 267 RetryCommand();
312 PerformDelayedAction(Action::SEND_INIT,
313 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
314 } else {
315 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
316 }
317
318 return; 268 return;
319 } 269 }
320 270
321 switch (command_) { 271 switch (command_) {
322 case Command::START_TRACING: 272 case Command::START_TRACING:
323 PerformAction(Action::SEND_SET_GAIN); 273 PerformAction(Action::SEND_SET_GAIN);
324 return; 274 return;
325 case Command::GET_FIRMWARE_GIT_HASH: 275 case Command::GET_FIRMWARE_GIT_HASH:
326 PerformAction(Action::SEND_GIT_HASH_REQUEST); 276 PerformAction(Action::SEND_GIT_HASH_REQUEST);
327 return; 277 return;
328 default: 278 default:
329 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 279 NOTREACHED();
330 return; 280 return;
331 } 281 }
332 282
333 case Action::READ_SET_GAIN_ACK: 283 case Action::READ_SET_GAIN_ACK:
334 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, 284 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN,
335 *bytes)) { 285 *bytes)) {
336 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 286 RetryCommand();
337 return; 287 return;
338 } 288 }
339 289
340 PerformAction(Action::SEND_START_TRACING); 290 PerformAction(Action::SEND_START_TRACING);
341 return; 291 return;
342 292
343 case Action::READ_START_TRACING_ACK: 293 case Action::READ_START_TRACING_ACK:
344 if (!IsAckOfControlCommand( 294 if (!IsAckOfControlCommand(
345 type, BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, *bytes)) { 295 type, BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, *bytes)) {
346 if (num_start_tracing_attempts_++ < kMaxStartTracingAttempts) { 296 RetryCommand();
347 num_init_attempts_ = 1;
348 PerformAction(Action::SEND_INIT);
349 } else {
350 CompleteCommand(BATTOR_ERROR_TOO_MANY_START_TRACING_RETRIES);
351 }
352
353 return; 297 return;
354 } 298 }
355 299
356 CompleteCommand(BATTOR_ERROR_NONE); 300 CompleteCommand(BATTOR_ERROR_NONE);
357 return; 301 return;
358 302
359 case Action::READ_EEPROM: { 303 case Action::READ_EEPROM: {
360 battor_eeprom_ = ParseEEPROM(type, *bytes); 304 battor_eeprom_ = ParseEEPROM(type, *bytes);
361 if (!battor_eeprom_) { 305 if (!battor_eeprom_) {
362 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 306 RetryCommand();
363 return; 307 return;
364 } 308 }
365 309
366 // Make sure that we don't request samples until a safe amount of time has 310 // Make sure that we don't request samples until a safe amount of time has
367 // elapsed since recording the last clock sync marker: we need to ensure 311 // elapsed since recording the last clock sync marker: we need to ensure
368 // that the sample we synced to doesn't get thrown out. 312 // that the sample we synced to doesn't get thrown out.
369 base::TimeTicks min_request_samples_time = 313 base::TimeTicks min_request_samples_time =
370 last_clock_sync_time_ + base::TimeDelta::FromMilliseconds( 314 last_clock_sync_time_ + base::TimeDelta::FromMilliseconds(
371 kStopTracingClockSyncDelayMilliseconds); 315 kStopTracingClockSyncDelayMilliseconds);
372 base::TimeDelta request_samples_delay = std::max( 316 base::TimeDelta request_samples_delay = std::max(
373 min_request_samples_time - base::TimeTicks::Now(), base::TimeDelta()); 317 min_request_samples_time - base::TimeTicks::Now(), base::TimeDelta());
374 318
375 PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay); 319 PerformDelayedAction(Action::SEND_SAMPLES_REQUEST, request_samples_delay);
376 return; 320 return;
377 } 321 }
378 case Action::READ_CALIBRATION_FRAME: { 322 case Action::READ_CALIBRATION_FRAME: {
379 BattOrFrameHeader frame_header; 323 BattOrFrameHeader frame_header;
380 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++, 324 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++,
381 &frame_header, &calibration_frame_)) { 325 &frame_header, &calibration_frame_)) {
382 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 326 RetryCommand();
383 return; 327 return;
384 } 328 }
385 329
386 // Make sure that the calibration frame has actual samples in it. 330 // Make sure that the calibration frame has actual samples in it.
387 if (calibration_frame_.empty()) { 331 if (calibration_frame_.empty()) {
388 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 332 RetryCommand();
389 return; 333 return;
390 } 334 }
391 335
392 num_read_attempts_ = 1;
393 PerformAction(Action::READ_DATA_FRAME); 336 PerformAction(Action::READ_DATA_FRAME);
394 return; 337 return;
395 } 338 }
396 339
397 case Action::READ_DATA_FRAME: { 340 case Action::READ_DATA_FRAME: {
398 BattOrFrameHeader frame_header; 341 BattOrFrameHeader frame_header;
399 vector<RawBattOrSample> frame; 342 vector<RawBattOrSample> frame;
400 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++, 343 if (!ParseSampleFrame(type, *bytes, next_sequence_number_++,
401 &frame_header, &frame)) { 344 &frame_header, &frame)) {
402 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 345 RetryCommand();
403 return; 346 return;
404 } 347 }
405 348
406 // Check for the empty frame the BattOr uses to indicate it's done 349 // Check for the empty frame the BattOr uses to indicate it's done
407 // streaming samples. 350 // streaming samples.
408 if (frame.empty()) { 351 if (frame.empty()) {
352 // Cancel the next data frame timeout.
353 timeout_callback_.Cancel();
409 CompleteCommand(BATTOR_ERROR_NONE); 354 CompleteCommand(BATTOR_ERROR_NONE);
410 return; 355 return;
411 } 356 }
412 357
413 samples_.insert(samples_.end(), frame.begin(), frame.end()); 358 samples_.insert(samples_.end(), frame.begin(), frame.end());
414 359
415 num_read_attempts_ = 1;
416 PerformAction(Action::READ_DATA_FRAME); 360 PerformAction(Action::READ_DATA_FRAME);
417 return; 361 return;
418 } 362 }
419 363
420 case Action::READ_CURRENT_SAMPLE: 364 case Action::READ_CURRENT_SAMPLE:
421 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK || 365 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK ||
422 bytes->size() != sizeof(uint32_t)) { 366 bytes->size() != sizeof(uint32_t)) {
423 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 367 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
424 return; 368 return;
425 } 369 }
426 370
427 uint32_t sample_num; 371 uint32_t sample_num;
428 memcpy(&sample_num, bytes->data(), sizeof(uint32_t)); 372 memcpy(&sample_num, bytes->data(), sizeof(uint32_t));
429 clock_sync_markers_[sample_num] = pending_clock_sync_marker_; 373 clock_sync_markers_[sample_num] = pending_clock_sync_marker_;
430 last_clock_sync_time_ = base::TimeTicks::Now(); 374 last_clock_sync_time_ = base::TimeTicks::Now();
431 CompleteCommand(BATTOR_ERROR_NONE); 375 CompleteCommand(BATTOR_ERROR_NONE);
432 return; 376 return;
433 377
434 case Action::READ_GIT_HASH: 378 case Action::READ_GIT_HASH:
435 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK ){ 379 if (type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) {
436 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 380 RetryCommand();
437 return; 381 return;
438 } 382 }
383
439 firmware_git_hash_ = std::string(bytes->begin(), bytes->end()); 384 firmware_git_hash_ = std::string(bytes->begin(), bytes->end());
440 CompleteCommand(BATTOR_ERROR_NONE); 385 CompleteCommand(BATTOR_ERROR_NONE);
441 return; 386 return;
442 387
443 default: 388 default:
444 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 389 NOTREACHED();
390 return;
445 } 391 }
446 } 392 }
447 393
448 void BattOrAgent::PerformAction(Action action) { 394 void BattOrAgent::PerformAction(Action action) {
449 DCHECK(thread_checker_.CalledOnValidThread()); 395 DCHECK(thread_checker_.CalledOnValidThread());
450 396
451 timeout_callback_.Reset(
452 base::Bind(&BattOrAgent::OnActionTimeout, AsWeakPtr()));
453 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
454 FROM_HERE, timeout_callback_.callback(),
455 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds));
456
457 last_action_ = action; 397 last_action_ = action;
458 398
459 switch (action) { 399 switch (action) {
460 case Action::REQUEST_CONNECTION: 400 case Action::REQUEST_CONNECTION:
461 BeginConnect(); 401 BeginConnect();
462 return; 402 return;
463
464 // The following actions are required for StartTracing: 403 // The following actions are required for StartTracing:
465 case Action::SEND_INIT: 404 case Action::SEND_INIT:
466 // Clear out the serial data that may exist from prior init attempts.
467 connection_->Flush();
468
469 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); 405 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0);
470 return; 406 return;
471 case Action::READ_INIT_ACK: 407 case Action::READ_INIT_ACK:
472 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 408 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
473 return; 409 return;
474 case Action::SEND_SET_GAIN: 410 case Action::SEND_SET_GAIN:
475 // Set the BattOr's gain. Setting the gain tells the BattOr the range of 411 // Set the BattOr's gain. Setting the gain tells the BattOr the range of
476 // power measurements that we expect to see. 412 // power measurements that we expect to see.
477 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, BATTOR_GAIN_LOW, 413 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, BATTOR_GAIN_LOW,
478 0); 414 0);
479 return; 415 return;
480 case Action::READ_SET_GAIN_ACK: 416 case Action::READ_SET_GAIN_ACK:
481 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 417 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
482 return; 418 return;
483 case Action::SEND_START_TRACING: 419 case Action::SEND_START_TRACING:
484 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, 0, 0); 420 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_START_SAMPLING_SD, 0, 0);
485 return; 421 return;
486 case Action::READ_START_TRACING_ACK: 422 case Action::READ_START_TRACING_ACK:
487 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 423 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
488 return; 424 return;
489
490 // The following actions are required for StopTracing: 425 // The following actions are required for StopTracing:
491 case Action::SEND_EEPROM_REQUEST: 426 case Action::SEND_EEPROM_REQUEST:
492 // Read the BattOr's EEPROM to get calibration information that's required 427 // Read the BattOr's EEPROM to get calibration information that's required
493 // to convert the raw samples to accurate ones. 428 // to convert the raw samples to accurate ones.
494 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_EEPROM, 429 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_EEPROM,
495 sizeof(BattOrEEPROM), 0); 430 sizeof(BattOrEEPROM), 0);
496 return; 431 return;
497 case Action::READ_EEPROM: 432 case Action::READ_EEPROM:
498 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 433 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
499 return; 434 return;
500 case Action::SEND_SAMPLES_REQUEST: 435 case Action::SEND_SAMPLES_REQUEST:
501 // Send a request to the BattOr to tell it to start streaming the samples 436 // Send a request to the BattOr to tell it to start streaming the samples
502 // that it's stored on its SD card over the serial connection. 437 // that it's stored on its SD card over the serial connection.
503 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 0); 438 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SD_UART, 0, 0);
504 return; 439 return;
505 case Action::READ_CALIBRATION_FRAME: 440 case Action::READ_CALIBRATION_FRAME:
506 // Data frames are numbered starting at zero and counting up by one each 441 // Data frames are numbered starting at zero and counting up by one each
507 // data frame. We keep track of the next frame sequence number we expect 442 // data frame. We keep track of the next frame sequence number we expect
508 // to see to ensure we don't miss any data. 443 // to see to ensure we don't miss any data.
509 next_sequence_number_ = 0; 444 next_sequence_number_ = 0;
445
446 // Clear stored samples from prior attempts to read sample frames.
447 samples_.clear();
448 calibration_frame_.clear();
510 case Action::READ_DATA_FRAME: 449 case Action::READ_DATA_FRAME:
511 // The first frame sent back from the BattOr contains voltage and current 450 // The first frame sent back from the BattOr contains voltage and current
512 // data that excludes whatever device is being measured from the 451 // data that excludes whatever device is being measured from the
513 // circuit. We use this first frame to establish a baseline voltage and 452 // circuit. We use this first frame to establish a baseline voltage and
514 // current. 453 // current.
515 // 454 //
516 // All further frames contain real (but uncalibrated) voltage and current 455 // All further frames contain real (but uncalibrated) voltage and current
517 // data. 456 // data.
457 SetActionTimeout(kBattOrControlMessageTimeoutSeconds);
518 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES); 458 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_SAMPLES);
519 return; 459 return;
520 460
521 // The following actions are required for RecordClockSyncMarker: 461 // The following actions are required for RecordClockSyncMarker:
522 case Action::SEND_CURRENT_SAMPLE_REQUEST: 462 case Action::SEND_CURRENT_SAMPLE_REQUEST:
523 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SAMPLE_COUNT, 0, 0); 463 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_READ_SAMPLE_COUNT, 0, 0);
524 return; 464 return;
525 case Action::READ_CURRENT_SAMPLE: 465 case Action::READ_CURRENT_SAMPLE:
526 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 466 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
527 return; 467 return;
528 468
529 case Action::SEND_GIT_HASH_REQUEST: 469 case Action::SEND_GIT_HASH_REQUEST:
530 connection_->Flush();
531 SendControlMessage( 470 SendControlMessage(
532 BATTOR_CONTROL_MESSAGE_TYPE_GET_FIRMWARE_GIT_HASH, 0, 0); 471 BATTOR_CONTROL_MESSAGE_TYPE_GET_FIRMWARE_GIT_HASH, 0, 0);
533 return; 472 return;
534 473
535 case Action::READ_GIT_HASH: 474 case Action::READ_GIT_HASH:
536 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 475 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
537 return; 476 return;
538 477
539 case Action::INVALID: 478 case Action::INVALID:
540 NOTREACHED(); 479 NOTREACHED();
480 return;
541 } 481 }
542 } 482 }
543 483
544 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { 484 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) {
545 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 485 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
546 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), 486 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action),
547 delay); 487 delay);
548 } 488 }
549 489
550 void BattOrAgent::OnActionTimeout() { 490 void BattOrAgent::OnActionTimeout() {
551 switch (last_action_) { 491 switch (last_action_) {
552 case Action::READ_INIT_ACK: 492 case Action::READ_INIT_ACK:
553 if (num_init_attempts_++ < kMaxInitAttempts) { 493 case Action::READ_SET_GAIN_ACK:
554 // OnMessageRead() will fail and retry SEND_INIT.
555 connection_->CancelReadMessage();
556 } else {
557 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
558 }
559 return;
560
561 // TODO(crbug.com/672631): There's currently a BattOr firmware bug that's
562 // causing the BattOr to reset when it's sent the START_TRACING command.
563 // When the BattOr resets, it emits 0x00 to the serial connection. This 0x00
564 // isn't long enough for the connection to consider it a full ack of the
565 // START_TRACING command, so it continues to wait for more data. We handle
566 // this case here by assuming any timeouts while waiting for the
567 // StartTracing ack are related to this bug and retrying the full
568 // initialization sequence.
569 case Action::READ_START_TRACING_ACK: 494 case Action::READ_START_TRACING_ACK:
570 if (num_start_tracing_attempts_ < kMaxStartTracingAttempts) { 495 case Action::READ_EEPROM:
571 // OnMessageRead() will fail and retry StartTracing. 496 case Action::READ_CALIBRATION_FRAME:
572 connection_->CancelReadMessage(); 497 case Action::READ_DATA_FRAME:
573 } else { 498 case Action::READ_GIT_HASH:
574 CompleteCommand(BATTOR_ERROR_TOO_MANY_START_TRACING_RETRIES); 499 connection_->CancelReadMessage();
575 }
576 return; 500 return;
577 501
578 default: 502 default:
579 CompleteCommand(BATTOR_ERROR_TIMEOUT); 503 CompleteCommand(BATTOR_ERROR_TIMEOUT);
580 timeout_callback_.Cancel(); 504 timeout_callback_.Cancel();
581 } 505 }
582 } 506 }
583 507
584 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, 508 void BattOrAgent::SendControlMessage(BattOrControlMessageType type,
585 uint16_t param1, 509 uint16_t param1,
586 uint16_t param2) { 510 uint16_t param2) {
587 DCHECK(thread_checker_.CalledOnValidThread()); 511 DCHECK(thread_checker_.CalledOnValidThread());
588 512
513 SetActionTimeout(kBattOrControlMessageTimeoutSeconds);
514
589 BattOrControlMessage msg{type, param1, param2}; 515 BattOrControlMessage msg{type, param1, param2};
590 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); 516 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg));
591 } 517 }
592 518
519 void BattOrAgent::RetryCommand() {
520 if (++num_command_attempts_ >= kMaxCommandAttempts) {
521 CompleteCommand(BATTOR_ERROR_TOO_MANY_COMMAND_RETRIES);
522 return;
523 }
524
525 // Failed to read response to message, retry current command.
526 base::Callback<void()> next_command;
527 switch (command_) {
528 case Command::START_TRACING:
529 next_command = base::Bind(&BattOrAgent::StartTracing, AsWeakPtr());
530 return;
531 case Command::STOP_TRACING:
532 next_command = base::Bind(&BattOrAgent::StopTracing, AsWeakPtr());
533 return;
534 case Command::GET_FIRMWARE_GIT_HASH:
535 next_command = base::Bind(&BattOrAgent::GetFirmwareGitHash, AsWeakPtr());
536 return;
537 default:
538 NOTREACHED();
539 return;
540 }
541
542 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
charliea (OOO until 10-5) 2017/05/16 16:13:08 Ah, looks like the presubmit caught a bug that I d
543 FROM_HERE, next_command,
544 base::TimeDelta::FromSeconds(kCommandRetryDelaySeconds));
545 }
546
593 void BattOrAgent::CompleteCommand(BattOrError error) { 547 void BattOrAgent::CompleteCommand(BattOrError error) {
594 switch (command_) { 548 switch (command_) {
595 case Command::START_TRACING: 549 case Command::START_TRACING:
596 base::ThreadTaskRunnerHandle::Get()->PostTask( 550 base::ThreadTaskRunnerHandle::Get()->PostTask(
597 FROM_HERE, base::Bind(&Listener::OnStartTracingComplete, 551 FROM_HERE, base::Bind(&Listener::OnStartTracingComplete,
598 base::Unretained(listener_), error)); 552 base::Unretained(listener_), error));
599 break; 553 break;
600 case Command::STOP_TRACING: 554 case Command::STOP_TRACING:
601 base::ThreadTaskRunnerHandle::Get()->PostTask( 555 base::ThreadTaskRunnerHandle::Get()->PostTask(
602 FROM_HERE, 556 FROM_HERE,
603 base::Bind(&Listener::OnStopTracingComplete, 557 base::Bind(&Listener::OnStopTracingComplete,
604 base::Unretained(listener_), SamplesToString(), error)); 558 base::Unretained(listener_), SamplesToString(), error));
605 break; 559 break;
606 case Command::RECORD_CLOCK_SYNC_MARKER: 560 case Command::RECORD_CLOCK_SYNC_MARKER:
607 base::ThreadTaskRunnerHandle::Get()->PostTask( 561 base::ThreadTaskRunnerHandle::Get()->PostTask(
608 FROM_HERE, base::Bind(&Listener::OnRecordClockSyncMarkerComplete, 562 FROM_HERE, base::Bind(&Listener::OnRecordClockSyncMarkerComplete,
609 base::Unretained(listener_), error)); 563 base::Unretained(listener_), error));
610 break; 564 break;
611 case Command::GET_FIRMWARE_GIT_HASH: 565 case Command::GET_FIRMWARE_GIT_HASH:
612 base::ThreadTaskRunnerHandle::Get()->PostTask( 566 base::ThreadTaskRunnerHandle::Get()->PostTask(
613 FROM_HERE, base::Bind(&Listener::OnGetFirmwareGitHashComplete, 567 FROM_HERE, base::Bind(&Listener::OnGetFirmwareGitHashComplete,
614 base::Unretained(listener_), 568 base::Unretained(listener_),
615 firmware_git_hash_, error)); 569 firmware_git_hash_, error));
616 break; 570 break;
617 case Command::INVALID: 571 case Command::INVALID:
618 NOTREACHED(); 572 NOTREACHED();
573 return;
619 } 574 }
620 575
621 last_action_ = Action::INVALID; 576 last_action_ = Action::INVALID;
622 command_ = Command::INVALID; 577 command_ = Command::INVALID;
623 pending_clock_sync_marker_.clear(); 578 pending_clock_sync_marker_.clear();
624 battor_eeprom_.reset(); 579 battor_eeprom_.reset();
625 calibration_frame_.clear(); 580 calibration_frame_.clear();
626 samples_.clear(); 581 samples_.clear();
627 next_sequence_number_ = 0; 582 next_sequence_number_ = 0;
583 num_command_attempts_ = 0;
628 } 584 }
629 585
630 std::string BattOrAgent::SamplesToString() { 586 std::string BattOrAgent::SamplesToString() {
631 if (calibration_frame_.empty() || samples_.empty() || !battor_eeprom_) 587 if (calibration_frame_.empty() || samples_.empty() || !battor_eeprom_)
632 return ""; 588 return "";
633 589
634 BattOrSampleConverter converter(*battor_eeprom_, calibration_frame_); 590 BattOrSampleConverter converter(*battor_eeprom_, calibration_frame_);
635 591
636 std::stringstream trace_stream; 592 std::stringstream trace_stream;
637 trace_stream << std::fixed; 593 trace_stream << std::fixed;
(...skipping 22 matching lines...) Expand all
660 static_cast<uint32_t>(calibration_frame_.size() + i)); 616 static_cast<uint32_t>(calibration_frame_.size() + i));
661 if (clock_sync_marker != clock_sync_markers_.end()) 617 if (clock_sync_marker != clock_sync_markers_.end())
662 trace_stream << " <" << clock_sync_marker->second << ">"; 618 trace_stream << " <" << clock_sync_marker->second << ">";
663 619
664 trace_stream << std::endl; 620 trace_stream << std::endl;
665 } 621 }
666 622
667 return trace_stream.str(); 623 return trace_stream.str();
668 } 624 }
669 625
626 void BattOrAgent::SetActionTimeout(uint16_t timeout_seconds) {
627 timeout_callback_.Reset(
628 base::Bind(&BattOrAgent::OnActionTimeout, AsWeakPtr()));
629 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
630 FROM_HERE, timeout_callback_.callback(),
631 base::TimeDelta::FromSeconds(timeout_seconds));
632 }
633
670 } // namespace battor 634 } // namespace battor
OLDNEW
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | tools/battor_agent/battor_agent_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698