blob: 793ddcc8efc23a678d8e5d142c19bd241b404f85 [file] [log] [blame]
Brian Silverman26e4e522015-12-17 01:56:40 -05001#include "LiveWindow/LiveWindow.h"
2#include "networktables/NetworkTable.h"
3#include <algorithm>
4#include <sstream>
5
6/**
7 * Get an instance of the LiveWindow main class
8 * This is a singleton to guarantee that there is only a single instance
9 * regardless of
10 * how many times GetInstance is called.
11 */
12LiveWindow *LiveWindow::GetInstance() {
13 static LiveWindow instance;
14 return &instance;
15}
16
17/**
18 * LiveWindow constructor.
19 * Allocate the necessary tables.
20 */
21LiveWindow::LiveWindow() : m_scheduler(Scheduler::GetInstance()) {
22 m_liveWindowTable = NetworkTable::GetTable("LiveWindow");
23 m_statusTable = m_liveWindowTable->GetSubTable("~STATUS~");
24}
25
26/**
27 * Change the enabled status of LiveWindow
28 * If it changes to enabled, start livewindow running otherwise stop it
29 */
30void LiveWindow::SetEnabled(bool enabled) {
31 if (m_enabled == enabled) return;
32 if (enabled) {
33 if (m_firstTime) {
34 InitializeLiveWindowComponents();
35 m_firstTime = false;
36 }
37 m_scheduler->SetEnabled(false);
38 m_scheduler->RemoveAll();
39 for (auto& elem : m_components) {
40 elem.first->StartLiveWindowMode();
41 }
42 } else {
43 for (auto& elem : m_components) {
44 elem.first->StopLiveWindowMode();
45 }
46 m_scheduler->SetEnabled(true);
47 }
48 m_enabled = enabled;
49 m_statusTable->PutBoolean("LW Enabled", m_enabled);
50}
51
52/**
53 * @name AddSensor(subsystem, name, component)
54 * Add a Sensor associated with the subsystem and call it by the given name.
55 * @param subsystem The subsystem this component is part of.
56 * @param name The name of this component.
57 * @param component A LiveWindowSendable component that represents a sensor.
58 */
59//@{
60/**
61 * @brief Use a STL smart pointer to share ownership of component.
62 */
63void LiveWindow::AddSensor(const std::string &subsystem, const std::string &name,
64 std::shared_ptr<LiveWindowSendable> component) {
65 m_components[component].subsystem = subsystem;
66 m_components[component].name = name;
67 m_components[component].isSensor = true;
68}
69
70/**
71 * @brief Pass a reference to LiveWindow and retain ownership of the component.
72 */
73void LiveWindow::AddSensor(const std::string &subsystem,
74 const std::string &name,
75 LiveWindowSendable &component) {
76 AddSensor(subsystem, name, std::shared_ptr<LiveWindowSendable>(
77 &component, [](LiveWindowSendable*){}));
78}
79
80/**
81 * @brief Use a raw pointer to the LiveWindow.
82 * @deprecated Prefer smart pointers or references.
83 */
84void LiveWindow::AddSensor(const std::string &subsystem,
85 const std::string &name,
86 LiveWindowSendable *component) {
87 AddSensor(subsystem, name, std::shared_ptr<LiveWindowSendable>(
88 component, NullDeleter<LiveWindowSendable>()));
89}
90//@}
91
92/**
93 * @name AddActuator(subsystem, name, component)
94 * Add an Actuator associated with the subsystem and call it by the given name.
95 * @param subsystem The subsystem this component is part of.
96 * @param name The name of this component.
97 * @param component A LiveWindowSendable component that represents a actuator.
98 */
99//@{
100/**
101 * @brief Use a STL smart pointer to share ownership of component.
102 */
103void LiveWindow::AddActuator(const std::string &subsystem, const std::string &name,
104 std::shared_ptr<LiveWindowSendable> component) {
105 m_components[component].subsystem = subsystem;
106 m_components[component].name = name;
107 m_components[component].isSensor = false;
108}
109
110/**
111 * @brief Pass a reference to LiveWindow and retain ownership of the component.
112 */
113void LiveWindow::AddActuator(const std::string &subsystem,
114 const std::string &name,
115 LiveWindowSendable &component) {
116 AddActuator(subsystem, name, std::shared_ptr<LiveWindowSendable>(
117 &component, [](LiveWindowSendable*){}));
118}
119
120/**
121 * @brief Use a raw pointer to the LiveWindow.
122 * @deprecated Prefer smart pointers or references.
123 */
124void LiveWindow::AddActuator(const std::string &subsystem, const std::string &name,
125 LiveWindowSendable *component) {
126 AddActuator(subsystem, name,
127 std::shared_ptr<LiveWindowSendable>(
128 component, NullDeleter<LiveWindowSendable>()));
129}
130//@}
131
132/**
133 * Meant for internal use in other WPILib classes.
134 */
135void LiveWindow::AddSensor(std::string type, int channel,
136 LiveWindowSendable *component) {
137 std::ostringstream oss;
138 oss << type << "[" << channel << "]";
139 AddSensor("Ungrouped", oss.str(), component);
140 std::shared_ptr<LiveWindowSendable> component_stl(
141 component, NullDeleter<LiveWindowSendable>());
142 if (std::find(m_sensors.begin(), m_sensors.end(), component_stl) ==
143 m_sensors.end())
144 m_sensors.push_back(component_stl);
145}
146
147/**
148 * Meant for internal use in other WPILib classes.
149 */
150void LiveWindow::AddActuator(std::string type, int channel,
151 LiveWindowSendable *component) {
152 std::ostringstream oss;
153 oss << type << "[" << channel << "]";
154 AddActuator("Ungrouped", oss.str(), std::shared_ptr<LiveWindowSendable>(
155 component, [](LiveWindowSendable *) {}));
156}
157
158/**
159 * Meant for internal use in other WPILib classes.
160 */
161void LiveWindow::AddActuator(std::string type, int module, int channel,
162 LiveWindowSendable *component) {
163 std::ostringstream oss;
164 oss << type << "[" << module << "," << channel << "]";
165 AddActuator("Ungrouped", oss.str(), std::shared_ptr<LiveWindowSendable>(
166 component, [](LiveWindowSendable *) {}));
167}
168
169/**
170 * Tell all the sensors to update (send) their values
171 * Actuators are handled through callbacks on their value changing from the
172 * SmartDashboard widgets.
173 */
174void LiveWindow::UpdateValues() {
175 for (auto& elem : m_sensors) {
176 elem->UpdateTable();
177 }
178}
179
180/**
181 * This method is called periodically to cause the sensors to send new values
182 * to the SmartDashboard.
183 */
184void LiveWindow::Run() {
185 if (m_enabled) {
186 UpdateValues();
187 }
188}
189
190/**
191 * Initialize all the LiveWindow elements the first time we enter LiveWindow
192 * mode. By holding off creating the NetworkTable entries, it allows them to be
193 * redefined before the first time in LiveWindow mode. This allows default
194 * sensor and actuator values to be created that are replaced with the custom
195 * names from users calling addActuator and addSensor.
196 */
197void LiveWindow::InitializeLiveWindowComponents() {
198 for (auto& elem : m_components) {
199 std::shared_ptr<LiveWindowSendable> component = elem.first;
200 LiveWindowComponent c = elem.second;
201 std::string subsystem = c.subsystem;
202 std::string name = c.name;
203 m_liveWindowTable->GetSubTable(subsystem)
204 ->PutString("~TYPE~", "LW Subsystem");
205 std::shared_ptr<ITable> table(
206 m_liveWindowTable->GetSubTable(subsystem)->GetSubTable(name));
207 table->PutString("~TYPE~", component->GetSmartDashboardType());
208 table->PutString("Name", name);
209 table->PutString("Subsystem", subsystem);
210 component->InitTable(table);
211 if (c.isSensor) {
212 m_sensors.push_back(component);
213 }
214 }
215}