James Kuszmaul | 0de4feb | 2022-04-15 12:16:59 -0700 | [diff] [blame] | 1 | #ifndef AOS_UTIL_FOXGLOVE_WEBSOCKET_LIB_H_ |
| 2 | #define AOS_UTIL_FOXGLOVE_WEBSOCKET_LIB_H_ |
| 3 | #include <map> |
| 4 | #include <set> |
| 5 | |
James Kuszmaul | 0de4feb | 2022-04-15 12:16:59 -0700 | [diff] [blame] | 6 | #include "foxglove/websocket/server.hpp" |
| 7 | |
Philipp Schrader | 790cb54 | 2023-07-05 21:06:52 -0700 | [diff] [blame] | 8 | #include "aos/events/event_loop.h" |
| 9 | |
James Kuszmaul | 0de4feb | 2022-04-15 12:16:59 -0700 | [diff] [blame] | 10 | namespace aos { |
| 11 | // This class implements a live AOS -> Foxglove Websocket Protocol connection, |
| 12 | // making use of the implementation at |
| 13 | // https://github.com/foxglove/ws-protocol/tree/main/cpp to send JSON messages |
| 14 | // to a foxglove studio client. |
| 15 | // See foxglove_websocket.cc for some usage notes. |
| 16 | class FoxgloveWebsocketServer { |
| 17 | public: |
James Kuszmaul | f1dbaff | 2023-02-08 21:17:32 -0800 | [diff] [blame] | 18 | // Whether to serialize the messages into the MCAP file as JSON or |
| 19 | // flatbuffers. |
| 20 | enum class Serialization { |
| 21 | kJson, |
| 22 | kFlatbuffer, |
| 23 | }; |
| 24 | enum class FetchPinnedChannels { |
| 25 | kYes, |
| 26 | kNo, |
| 27 | }; |
James Kuszmaul | 1e418f6 | 2023-02-26 14:40:20 -0800 | [diff] [blame] | 28 | // Whether to attempt to shorten channel names. |
| 29 | enum class CanonicalChannelNames { |
| 30 | // Just use the full, unambiguous, channel names. |
| 31 | kCanonical, |
| 32 | // Use GetChannelAliases() to determine the shortest possible name for the |
| 33 | // channel for the current node, and use that in the MCAP file. This makes |
| 34 | // it so that the channels in the resulting file are more likely to match |
| 35 | // the channel names that are used in "real" applications. |
| 36 | kShortened, |
| 37 | }; |
James Kuszmaul | f1dbaff | 2023-02-08 21:17:32 -0800 | [diff] [blame] | 38 | FoxgloveWebsocketServer(aos::EventLoop *event_loop, uint32_t port, |
| 39 | Serialization serialization, |
James Kuszmaul | 1e418f6 | 2023-02-26 14:40:20 -0800 | [diff] [blame] | 40 | FetchPinnedChannels fetch_pinned_channels, |
| 41 | CanonicalChannelNames canonical_channels); |
James Kuszmaul | 0de4feb | 2022-04-15 12:16:59 -0700 | [diff] [blame] | 42 | ~FoxgloveWebsocketServer(); |
| 43 | |
| 44 | private: |
| 45 | typedef foxglove::websocket::ChannelId ChannelId; |
| 46 | |
| 47 | struct FetcherState { |
| 48 | std::unique_ptr<aos::RawFetcher> fetcher; |
| 49 | // Whether the current message in the fetcher has been sent to the client. |
| 50 | // Starts as true because the fetcher starts with no data. |
| 51 | // This is necessary because we have to send all of our messages out |
| 52 | // in order, which we can only do once we know the timestamp of each |
| 53 | // message. And we can only know the timestamp after having called Fetch() |
| 54 | // on the fetcher. Once we get around to actually sending the data, we can |
| 55 | // set this to true so that we know it is safe to call FetchNext() again. |
| 56 | bool sent_current_message = true; |
| 57 | }; |
| 58 | |
| 59 | aos::EventLoop *event_loop_; |
James Kuszmaul | f1dbaff | 2023-02-08 21:17:32 -0800 | [diff] [blame] | 60 | const Serialization serialization_; |
| 61 | const FetchPinnedChannels fetch_pinned_channels_; |
James Kuszmaul | 1e418f6 | 2023-02-26 14:40:20 -0800 | [diff] [blame] | 62 | const CanonicalChannelNames canonical_channels_; |
James Kuszmaul | 0de4feb | 2022-04-15 12:16:59 -0700 | [diff] [blame] | 63 | foxglove::websocket::Server server_; |
| 64 | // A map of fetchers for every single channel that could be subscribed to. |
| 65 | std::map<ChannelId, FetcherState> fetchers_; |
| 66 | // The set of channels that we have clients actively subscribed to. |
| 67 | std::set<ChannelId> active_channels_; |
| 68 | }; |
| 69 | } // namespace aos |
| 70 | #endif // AOS_UTIL_FOXGLOVE_WEBSOCKET_LIB_H_ |