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