blob: 9ce8dcb18536f4fbb72eaed032872431f15b2db0 [file] [log] [blame]
Comran Morshedc4ce9512015-03-08 11:51:09 +00001#include "seasocks/PageHandler.h"
2#include "seasocks/PrintfLogger.h"
3#include "seasocks/StringUtil.h"
4
5#include <iostream>
6#include <memory>
7#include <sstream>
8#include <string>
9#include <thread>
10#include <atomic>
11#include <vector>
12
13#include "aos/linux_code/init.h"
14#include "aos/common/time.h"
15#include "aos/common/util/phased_loop.h"
16#include "aos/common/mutex.h"
17
18#include "frc971/control_loops/claw/claw.q.h"
19#include "frc971/control_loops/fridge/fridge.q.h"
20
21#include "frc971/http_status/embedded.h"
22
23namespace frc971 {
24namespace http_status {
25
26// A class for storing data from DataCollector and packaging it as a custom
27// message for the websocket.
28// Samples are stored in a vector that wraps around at a certain point to avoid
29// clogging up memory. These samples should be already on all clients before
30// they are overwritten. To avoid losing samples, there must be a balance
31// between the rate samples are being recorded at and the speed of the link
32// between the robot and client.
33
34class HTTPStatusMessage {
35 public:
36 HTTPStatusMessage();
37
38 // Stores an individual measurement in the current sample.
39 void AddMeasure(::std::string name, double value);
40
41 // Starts a new sample that contains measurements for all the states at a
42 // timestep, and lock mutex to synchronize measures.
43 void NextSample();
44
45 // Unlock mutex.
46 void EndSample();
47
48 // Method called by the websocket to get a JSON-packaged string containing,
49 // at most, a constant number of samples, starting at "from_sample".
50 // "from_sample" is a specific index for a sample that is not wrapped.
51 ::std::string Fetch(size_t from_sample);
52
53 private:
54 // Returns the vector index of the sample given.
55 // Since the vectors wrap, multiple sample_ids may refer to the same vector
56 // index.
57 int32_t GetIndex(int32_t sample_id);
58
59 // Vectors of vectors to store samples at indexes determined by GetIndex.
60 ::std::vector<::std::string> data_names_;
61 ::std::vector<::std::vector<double>> data_values_;
62 ::std::vector<::aos::time::Time> sample_times_;
63
64 int32_t sample_id_; // Last sample id used.
65 int32_t measure_index_; // Last measure index used.
66 const int32_t overflow_id_; // Vector wrapping size.
67 // Number of samples to include in each JSON packet.
68 const int32_t num_samples_per_packet_;
69
70 // Mutex used to synchronize data.
71 ::aos::Mutex mutex_;
72};
73
74class DataCollector {
75 public:
76 DataCollector();
77 void RunIteration();
78 ::std::string GetData(int32_t from);
79
80 void operator()(); // Will be called by ::std::thread internally.
81 void Quit() { run_ = false; }
82
83 private:
84 ::std::string cur_raw_data_;
85 HTTPStatusMessage message_;
86 ::std::atomic<bool> run_{true};
87};
88
89class SocketHandler : public seasocks::WebSocket::Handler {
90 public:
91 SocketHandler();
92 void onConnect(seasocks::WebSocket* connection) override;
93 void onData(seasocks::WebSocket* connection, const char* data) override;
94 void onDisconnect(seasocks::WebSocket* connection) override;
95 void Quit();
96
97 private:
98 ::std::set<seasocks::WebSocket*> connections_;
99 DataCollector data_collector_;
100 ::std::thread data_collector_thread_;
101};
102
103class SeasocksLogger : public seasocks::PrintfLogger {
104 public:
105 SeasocksLogger(Level min_level_to_log);
106 void log(Level level, const char* message) override;
107};
108
109} // namespace http_status
110} // namespace frc971