15
15
#include < wpi/StringExtras.h>
16
16
#include < wpi/json.h>
17
17
#include < wpi/raw_istream.h>
18
- #include < wpi/raw_ostream.h>
19
18
20
19
#include " cameraserver/CameraServer.h"
21
20
@@ -85,8 +84,15 @@ std::vector<CameraConfig> cameraConfigs;
85
84
std::vector<SwitchedCameraConfig> switchedCameraConfigs;
86
85
std::vector<cs::VideoSource> cameras;
87
86
88
- void ParseError (std::string_view msg) {
89
- fmt::print (stderr, " config error in '{}': {}\n " , configFile, msg);
87
+ void ParseErrorV (fmt::string_view format, fmt::format_args args) {
88
+ fmt::print (stderr, " config error in '{}': " , configFile);
89
+ fmt::vprint (stderr, format, args);
90
+ fmt::print (stderr, " \n " );
91
+ }
92
+
93
+ template <typename ... Args>
94
+ void ParseError (fmt::string_view format, Args&&... args) {
95
+ ParseErrorV (format, fmt::make_format_args (args...));
90
96
}
91
97
92
98
bool ReadCameraConfig (const wpi::json& config) {
@@ -96,15 +102,15 @@ bool ReadCameraConfig(const wpi::json& config) {
96
102
try {
97
103
c.name = config.at (" name" ).get <std::string>();
98
104
} catch (const wpi::json::exception & e) {
99
- ParseError (fmt::format ( " could not read camera name: {}" , e.what () ));
105
+ ParseError (" could not read camera name: {}" , e.what ());
100
106
return false ;
101
107
}
102
108
103
109
// path
104
110
try {
105
111
c.path = config.at (" path" ).get <std::string>();
106
112
} catch (const wpi::json::exception & e) {
107
- ParseError (fmt::format ( " camera '{}': could not read path: {}" , c.name , e.what () ));
113
+ ParseError (" camera '{}': could not read path: {}" , c.name , e.what ());
108
114
return false ;
109
115
}
110
116
@@ -124,17 +130,16 @@ bool ReadSwitchedCameraConfig(const wpi::json& config) {
124
130
try {
125
131
c.name = config.at (" name" ).get <std::string>();
126
132
} catch (const wpi::json::exception & e) {
127
- ParseError (fmt::format (" could not read switched camera name: {}" ,
128
- e.what ()));
133
+ ParseError (" could not read switched camera name: {}" , e.what ());
129
134
return false ;
130
135
}
131
136
132
137
// key
133
138
try {
134
139
c.key = config.at (" key" ).get <std::string>();
135
140
} catch (const wpi::json::exception & e) {
136
- ParseError (fmt::format ( " switched camera '{}': could not read key: {}" ,
137
- c. name , e.what () ));
141
+ ParseError (" switched camera '{}': could not read key: {}" , c. name ,
142
+ e.what ());
138
143
return false ;
139
144
}
140
145
@@ -147,8 +152,7 @@ bool ReadConfig() {
147
152
std::error_code ec;
148
153
wpi::raw_fd_istream is (configFile, ec);
149
154
if (ec) {
150
- wpi::errs () << " could not open '" << configFile << " ': " << ec.message ()
151
- << ' \n ' ;
155
+ fmt::print (stderr, " could not open '{}': {}" , configFile, ec.message ());
152
156
return false ;
153
157
}
154
158
@@ -157,7 +161,7 @@ bool ReadConfig() {
157
161
try {
158
162
j = wpi::json::parse (is);
159
163
} catch (const wpi::json::parse_error& e) {
160
- ParseError (fmt::format ( " byte {}: {}" , e.byte , e.what () ));
164
+ ParseError (" byte {}: {}" , e.byte , e.what ());
161
165
return false ;
162
166
}
163
167
@@ -171,7 +175,7 @@ bool ReadConfig() {
171
175
try {
172
176
team = j.at (" team" ).get <unsigned int >();
173
177
} catch (const wpi::json::exception & e) {
174
- ParseError (fmt::format ( " could not read team number: {}" , e.what () ));
178
+ ParseError (" could not read team number: {}" , e.what ());
175
179
return false ;
176
180
}
177
181
@@ -184,10 +188,10 @@ bool ReadConfig() {
184
188
} else if (wpi::equals_lower (str, " server" )) {
185
189
server = true ;
186
190
} else {
187
- ParseError (fmt::format ( " could not understand ntmode value '{}'" , str) );
191
+ ParseError (" could not understand ntmode value '{}'" , str);
188
192
}
189
193
} catch (const wpi::json::exception & e) {
190
- ParseError (fmt::format ( " could not read ntmode: {}" , e.what () ));
194
+ ParseError (" could not read ntmode: {}" , e.what ());
191
195
}
192
196
}
193
197
@@ -197,7 +201,7 @@ bool ReadConfig() {
197
201
if (!ReadCameraConfig (camera)) return false ;
198
202
}
199
203
} catch (const wpi::json::exception & e) {
200
- ParseError (fmt::format ( " could not read cameras: {}" , e.what () ));
204
+ ParseError (" could not read cameras: {}" , e.what ());
201
205
return false ;
202
206
}
203
207
@@ -208,7 +212,7 @@ bool ReadConfig() {
208
212
if (!ReadSwitchedCameraConfig (camera)) return false ;
209
213
}
210
214
} catch (const wpi::json::exception & e) {
211
- ParseError (fmt::format ( " could not read switched cameras: {}" , e.what () ));
215
+ ParseError (" could not read switched cameras: {}" , e.what ());
212
216
return false ;
213
217
}
214
218
}
@@ -234,24 +238,29 @@ cs::MjpegServer StartSwitchedCamera(const SwitchedCameraConfig& config) {
234
238
fmt::print (" Starting switched camera '{}' on {}\n " , config.name , config.key );
235
239
auto server = frc::CameraServer::AddSwitchedCamera (config.name );
236
240
237
- nt::NetworkTableInstance::GetDefault ()
238
- .GetEntry (config.key )
239
- .AddListener (
240
- [server](const auto & event) mutable {
241
- if (event.value ->IsDouble ()) {
242
- int i = event.value ->GetDouble ();
243
- if (i >= 0 && i < cameras.size ()) server.SetSource (cameras[i]);
244
- } else if (event.value ->IsString ()) {
245
- auto str = event.value ->GetString ();
246
- for (int i = 0 ; i < cameraConfigs.size (); ++i) {
247
- if (str == cameraConfigs[i].name ) {
248
- server.SetSource (cameras[i]);
249
- break ;
250
- }
251
- }
241
+ auto inst = nt::NetworkTableInstance::GetDefault ();
242
+ inst.AddListener (
243
+ inst.GetTopic (config.key ),
244
+ nt::EventFlags::kImmediate | nt::EventFlags::kValueAll ,
245
+ [server](const auto & event) mutable {
246
+ if (auto data = event.GetValueEventData ()) {
247
+ if (data->value .IsInteger ()) {
248
+ int i = data->value .GetInteger ();
249
+ if (i >= 0 && i < cameras.size ()) server.SetSource (cameras[i]);
250
+ } else if (data->value .IsDouble ()) {
251
+ int i = data->value .GetDouble ();
252
+ if (i >= 0 && i < cameras.size ()) server.SetSource (cameras[i]);
253
+ } else if (data->value .IsString ()) {
254
+ auto str = data->value .GetString ();
255
+ for (int i = 0 ; i < cameraConfigs.size (); ++i) {
256
+ if (str == cameraConfigs[i].name ) {
257
+ server.SetSource (cameras[i]);
258
+ break ;
252
259
}
253
- },
254
- NT_NOTIFY_IMMEDIATE | NT_NOTIFY_NEW | NT_NOTIFY_UPDATE);
260
+ }
261
+ }
262
+ }
263
+ });
255
264
256
265
return server;
257
266
}
@@ -280,7 +289,8 @@ int main(int argc, char* argv[]) {
280
289
ntinst.StartServer ();
281
290
} else {
282
291
fmt::print (" Setting up NetworkTables client for team {}\n " , team);
283
- ntinst.StartClientTeam (team);
292
+ ntinst.StartClient4 (" multiCameraServer" );
293
+ ntinst.SetServerTeam (team);
284
294
ntinst.StartDSClient ();
285
295
}
286
296
0 commit comments