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