RDMnet  HEAD (unstable)
Implementation of ANSI E1.33 (RDMnet)
View other versions:
controller.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2020 ETC Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************
16  * This file is a part of RDMnet. For more information, go to:
17  * https://github.com/ETCLabs/RDMnet
18  *****************************************************************************/
19 
22 
23 #ifndef RDMNET_CPP_CONTROLLER_H_
24 #define RDMNET_CPP_CONTROLLER_H_
25 
26 #include <algorithm>
27 #include <string>
28 #include <vector>
29 #include "etcpal/common.h"
30 #include "etcpal/cpp/error.h"
31 #include "etcpal/cpp/inet.h"
32 #include "etcpal/cpp/uuid.h"
33 #include "etcpal/cpp/log.h"
34 #include "etcpal/cpp/opaque_id.h"
35 #include "rdm/cpp/uid.h"
36 #include "rdm/cpp/message.h"
37 #include "rdmnet/cpp/client.h"
38 #include "rdmnet/cpp/common.h"
39 #include "rdmnet/cpp/message.h"
40 #include "rdmnet/controller.h"
41 
42 namespace rdmnet
43 {
54 
55 namespace detail
56 {
58 {
59 };
60 }; // namespace detail
61 
67 {
68 public:
71 
77  {
78  public:
79  virtual ~NotifyHandler() = default;
80 
85  virtual void HandleConnectedToBroker(Handle controller_handle,
86  ScopeHandle scope_handle,
87  const ClientConnectedInfo& info) = 0;
88 
93  virtual void HandleBrokerConnectFailed(Handle controller_handle,
94  ScopeHandle scope_handle,
95  const ClientConnectFailedInfo& info) = 0;
96 
101  virtual void HandleDisconnectedFromBroker(Handle controller_handle,
102  ScopeHandle scope_handle,
103  const ClientDisconnectedInfo& info) = 0;
104 
111  virtual void HandleClientListUpdate(Handle controller_handle,
112  ScopeHandle scope_handle,
113  client_list_action_t list_action,
114  const RptClientList& list) = 0;
115 
122  virtual bool HandleRdmResponse(Handle controller_handle, ScopeHandle scope_handle, const RdmResponse& resp) = 0;
123 
128  virtual void HandleRptStatus(Handle controller_handle, ScopeHandle scope_handle, const RptStatus& status) = 0;
129 
138  virtual void HandleResponderIdsReceived(Handle controller_handle,
139  ScopeHandle scope_handle,
140  const DynamicUidAssignmentList& list)
141  {
142  ETCPAL_UNUSED_ARG(controller_handle);
143  ETCPAL_UNUSED_ARG(scope_handle);
144  ETCPAL_UNUSED_ARG(list);
145  }
146  };
147 
153  {
154  public:
160  virtual RdmResponseAction HandleRdmCommand(Handle controller_handle,
161  ScopeHandle scope_handle,
162  const RdmCommand& cmd) = 0;
163 
168  virtual RdmResponseAction HandleLlrpRdmCommand(Handle controller_handle, const llrp::RdmCommand& cmd)
169  {
170  ETCPAL_UNUSED_ARG(controller_handle);
171  ETCPAL_UNUSED_ARG(cmd);
172  return rdmnet::RdmResponseAction::SendNack(kRdmNRActionNotSupported);
173  }
174  };
175 
181  struct Settings
182  {
184  rdm::Uid uid;
186 
188  bool create_llrp_target{false};
189 
191  Settings() = default;
192  Settings(const etcpal::Uuid& new_cid, const rdm::Uid& new_uid);
193  Settings(const etcpal::Uuid& new_cid, uint16_t manufacturer_id);
194 
195  bool IsValid() const;
196  };
197 
200  struct RdmData
201  {
204  uint16_t model_id{0};
207  uint32_t software_version_id{0};
210  uint16_t product_category{E120_PRODUCT_CATEGORY_CONTROL_CONTROLLER};
211 
216  bool device_label_settable{false};
217 
219  RdmData() = default;
220  RdmData(uint16_t new_model_id,
221  uint32_t new_software_version_id,
222  const char* new_manufacturer_label,
223  const char* new_device_model_description,
224  const char* new_software_version_label,
225  const char* new_device_label);
226  RdmData(uint16_t new_model_id,
227  uint32_t new_software_version_id,
228  const std::string& new_manufacturer_label,
229  const std::string& new_device_model_description,
230  const std::string& new_software_version_label,
231  const std::string& new_device_label);
232 
233  bool IsValid() const;
234  };
235 
236  Controller() = default;
237  Controller(const Controller& other) = delete;
238  Controller& operator=(const Controller& other) = delete;
239  Controller(Controller&& other) = default;
240  Controller& operator=(Controller&& other) = default;
241 
244  const Settings& settings,
245  RdmCommandHandler& rdm_handler,
246  uint8_t* rdm_response_buf = nullptr);
248 
250  const etcpal::SockAddr& static_broker_addr = etcpal::SockAddr{});
252  const etcpal::SockAddr& static_broker_addr = etcpal::SockAddr{});
253  etcpal::Expected<ScopeHandle> AddScope(const Scope& scope_config);
255  etcpal::Error RemoveScope(ScopeHandle scope_handle, rdmnet_disconnect_reason_t disconnect_reason);
257  const char* new_scope_id_str,
258  rdmnet_disconnect_reason_t disconnect_reason,
259  const etcpal::SockAddr& new_static_broker_addr = etcpal::SockAddr{});
261  const Scope& new_scope_config,
262  rdmnet_disconnect_reason_t disconnect_reason);
263  etcpal::Error ChangeSearchDomain(const char* new_search_domain, rdmnet_disconnect_reason_t disconnect_reason);
264 
266  const DestinationAddr& destination,
267  rdmnet_command_class_t command_class,
268  uint16_t param_id,
269  const uint8_t* data = nullptr,
270  uint8_t data_len = 0);
272  const DestinationAddr& destination,
273  uint16_t param_id,
274  const uint8_t* data = nullptr,
275  uint8_t data_len = 0);
277  const DestinationAddr& destination,
278  uint16_t param_id,
279  const uint8_t* data = nullptr,
280  uint8_t data_len = 0);
281 
283  etcpal::Error RequestResponderIds(ScopeHandle scope_handle, const rdm::Uid* uids, size_t num_uids);
285 
286  etcpal::Error SendRdmAck(ScopeHandle scope_handle,
287  const SavedRdmCommand& received_cmd,
288  const uint8_t* response_data = nullptr,
289  size_t response_data_len = 0);
291  const SavedRdmCommand& received_cmd,
292  rdm_nack_reason_t nack_reason);
293  etcpal::Error SendRdmNack(ScopeHandle scope_handle, const SavedRdmCommand& received_cmd, uint16_t raw_nack_reason);
295  uint16_t param_id,
296  const uint8_t* data = nullptr,
297  size_t data_len = 0);
298 
299  etcpal::Error SendLlrpAck(const llrp::SavedRdmCommand& received_cmd,
300  const uint8_t* response_data = nullptr,
301  uint8_t response_data_len = 0);
302  etcpal::Error SendLlrpNack(const llrp::SavedRdmCommand& received_cmd, rdm_nack_reason_t nack_reason);
303  etcpal::Error SendLlrpNack(const llrp::SavedRdmCommand& received_cmd, uint16_t raw_nack_reason);
304 
305  Handle handle() const;
306  const RdmData& rdm_data() const;
307  Controller::NotifyHandler* notify_handler() const;
308  Controller::RdmCommandHandler* rdm_command_handler() const;
309  etcpal::Expected<Scope> scope(ScopeHandle scope_handle) const;
310 
311  void UpdateRdmData(const RdmData& new_data);
312 
313 private:
314  Handle handle_;
315  RdmData my_rdm_data_;
316 
317  RdmCommandHandler* rdm_cmd_handler_{nullptr};
318  NotifyHandler* notify_{nullptr};
319 };
320 
323 
324 namespace internal
325 {
326 extern "C" inline void ControllerLibCbConnected(rdmnet_controller_t controller_handle,
327  rdmnet_client_scope_t scope_handle,
328  const RdmnetClientConnectedInfo* info,
329  void* context)
330 {
331  if (info && context)
332  {
333  static_cast<Controller::NotifyHandler*>(context)->HandleConnectedToBroker(Controller::Handle(controller_handle),
334  ScopeHandle(scope_handle), *info);
335  }
336 }
337 
338 extern "C" inline void ControllerLibCbConnectFailed(rdmnet_controller_t controller_handle,
339  rdmnet_client_scope_t scope_handle,
340  const RdmnetClientConnectFailedInfo* info,
341  void* context)
342 {
343  if (info && context)
344  {
345  static_cast<Controller::NotifyHandler*>(context)->HandleBrokerConnectFailed(Controller::Handle(controller_handle),
346  ScopeHandle(scope_handle), *info);
347  }
348 }
349 
350 extern "C" inline void ControllerLibCbDisconnected(rdmnet_controller_t controller_handle,
351  rdmnet_client_scope_t scope_handle,
352  const RdmnetClientDisconnectedInfo* info,
353  void* context)
354 {
355  if (info && context)
356  {
357  static_cast<Controller::NotifyHandler*>(context)->HandleDisconnectedFromBroker(
358  Controller::Handle(controller_handle), ScopeHandle(scope_handle), *info);
359  }
360 }
361 
362 extern "C" inline void ControllerLibCbClientListUpdate(rdmnet_controller_t controller_handle,
363  rdmnet_client_scope_t scope_handle,
364  client_list_action_t list_action,
365  const RdmnetRptClientList* list,
366  void* context)
367 {
368  if (list && context)
369  {
370  static_cast<Controller::NotifyHandler*>(context)->HandleClientListUpdate(
371  Controller::Handle(controller_handle), ScopeHandle(scope_handle), list_action, *list);
372  }
373 }
374 
375 extern "C" inline bool ControllerLibCbRdmResponseReceived(rdmnet_controller_t controller_handle,
376  rdmnet_client_scope_t scope_handle,
377  const RdmnetRdmResponse* resp,
378  void* context)
379 {
380  if (resp && context)
381  {
382  return static_cast<Controller::NotifyHandler*>(context)->HandleRdmResponse(Controller::Handle(controller_handle),
383  ScopeHandle(scope_handle), *resp);
384  }
385 
386  return true; // Error condition, drop response.
387 }
388 
389 extern "C" inline void ControllerLibCbStatusReceived(rdmnet_controller_t controller_handle,
390  rdmnet_client_scope_t scope_handle,
391  const RdmnetRptStatus* status,
392  void* context)
393 {
394  if (status && context)
395  {
396  static_cast<Controller::NotifyHandler*>(context)->HandleRptStatus(Controller::Handle(controller_handle),
397  ScopeHandle(scope_handle), *status);
398  }
399 }
400 
401 extern "C" inline void ControllerLibCbResponderIdsReceived(rdmnet_controller_t controller_handle,
402  rdmnet_client_scope_t scope_handle,
403  const RdmnetDynamicUidAssignmentList* list,
404  void* context)
405 {
406  if (list && context)
407  {
408  static_cast<Controller::NotifyHandler*>(context)->HandleResponderIdsReceived(Controller::Handle(controller_handle),
409  ScopeHandle(scope_handle), *list);
410  }
411 }
412 
413 extern "C" inline void ControllerLibCbRdmCommandReceived(rdmnet_controller_t controller_handle,
414  rdmnet_client_scope_t scope_handle,
415  const RdmnetRdmCommand* cmd,
416  RdmnetSyncRdmResponse* response,
417  void* context)
418 {
419  if (cmd && response && context)
420  {
421  *response = static_cast<Controller::RdmCommandHandler*>(context)
422  ->HandleRdmCommand(Controller::Handle(controller_handle), ScopeHandle(scope_handle), *cmd)
423  .get();
424  }
425 }
426 
427 extern "C" inline void ControllerLibCbLlrpRdmCommandReceived(rdmnet_controller_t controller_handle,
428  const LlrpRdmCommand* cmd,
429  RdmnetSyncRdmResponse* response,
430  void* context)
431 {
432  if (cmd && response && context)
433  {
434  *response = static_cast<Controller::RdmCommandHandler*>(context)
435  ->HandleLlrpRdmCommand(Controller::Handle(controller_handle), *cmd)
436  .get();
437  }
438 }
439 
440 }; // namespace internal
441 
443 
446 inline Controller::Settings::Settings(const etcpal::Uuid& new_cid, const rdm::Uid& new_uid) : cid(new_cid), uid(new_uid)
447 {
448 }
449 
454 inline Controller::Settings::Settings(const etcpal::Uuid& new_cid, uint16_t manufacturer_id)
455  : cid(new_cid), uid(rdm::Uid::DynamicUidRequest(manufacturer_id))
456 {
457 }
458 
460 inline bool Controller::Settings::IsValid() const
461 {
462  return (!cid.IsNull() && (uid.IsStatic() || uid.IsDynamicUidRequest()));
463 }
464 
466 inline Controller::RdmData::RdmData(uint16_t new_model_id,
467  uint32_t new_software_version_id,
468  const char* new_manufacturer_label,
469  const char* new_device_model_description,
470  const char* new_software_version_label,
471  const char* new_device_label)
472  : model_id(new_model_id), software_version_id(new_software_version_id)
473 {
474  if (new_manufacturer_label)
475  manufacturer_label = std::string(new_manufacturer_label);
476 
477  if (new_device_model_description)
478  device_model_description = std::string(new_device_model_description);
479 
480  if (new_software_version_label)
481  software_version_label = std::string(new_software_version_label);
482 
483  if (new_device_label)
484  device_label = std::string(new_device_label);
485 }
486 
488 inline Controller::RdmData::RdmData(uint16_t new_model_id,
489  uint32_t new_software_version_id,
490  const std::string& new_manufacturer_label,
491  const std::string& new_device_model_description,
492  const std::string& new_software_version_label,
493  const std::string& new_device_label)
494  : model_id(new_model_id)
495  , software_version_id(new_software_version_id)
496  , manufacturer_label(new_manufacturer_label)
497  , device_model_description(new_device_model_description)
498  , software_version_label(new_software_version_label)
499  , device_label(new_device_label)
500 {
501 }
502 
504 inline bool Controller::RdmData::IsValid() const
505 {
506  return ((!manufacturer_label.empty()) && (!device_model_description.empty()) && (!software_version_label.empty()) &&
507  (!device_label.empty()));
508 }
509 
522  const Settings& settings,
523  const RdmData& rdm_data)
524 {
525  if (!settings.IsValid() || !rdm_data.IsValid())
526  return kEtcPalErrInvalid;
527 
528  notify_ = &notify_handler;
529  my_rdm_data_ = rdm_data;
530 
531  // clang-format off
532  RdmnetControllerConfig config = {
533  settings.cid.get(), // CID
534  { // Callback shims
535  internal::ControllerLibCbConnected,
536  internal::ControllerLibCbConnectFailed,
537  internal::ControllerLibCbDisconnected,
538  internal::ControllerLibCbClientListUpdate,
539  internal::ControllerLibCbRdmResponseReceived,
540  internal::ControllerLibCbStatusReceived,
541  internal::ControllerLibCbResponderIdsReceived,
542  &notify_handler // Context
543  },
544  { // RDM command callback shims
545  nullptr, nullptr, nullptr, nullptr
546  },
547  { // RDM data
556  },
557  settings.uid.get(), // UID
558  settings.search_domain.c_str(), // Search domain
559  settings.create_llrp_target, // Create LLRP target
560  };
561  // clang-format on
562 
564  etcpal::Error result = rdmnet_controller_create(&config, &c_handle);
565 
566  handle_.SetValue(c_handle);
567 
568  return result;
569 }
570 
586  const Settings& settings,
587  RdmCommandHandler& rdm_handler,
588  uint8_t* rdm_response_buf)
589 {
590  if (!settings.IsValid())
591  return kEtcPalErrInvalid;
592 
593  notify_ = &notify_handler;
594  rdm_cmd_handler_ = &rdm_handler;
595 
596  // clang-format off
597  RdmnetControllerConfig config = {
598  settings.cid.get(), // CID
599  { // Callback shims
600  internal::ControllerLibCbConnected,
601  internal::ControllerLibCbConnectFailed,
602  internal::ControllerLibCbDisconnected,
603  internal::ControllerLibCbClientListUpdate,
604  internal::ControllerLibCbRdmResponseReceived,
605  internal::ControllerLibCbStatusReceived,
606  internal::ControllerLibCbResponderIdsReceived,
607  &notify_handler // Context
608  },
609  { // RDM command callback shims
610  internal::ControllerLibCbRdmCommandReceived,
611  internal::ControllerLibCbLlrpRdmCommandReceived,
612  rdm_response_buf,
613  &rdm_handler // Context
614  },
616  settings.uid.get(), // UID
617  settings.search_domain.c_str(), // Search domain
618  settings.create_llrp_target, // Create LLRP target
619  };
620  // clang-format on
621 
623  etcpal::Error result = rdmnet_controller_create(&config, &c_handle);
624 
625  handle_.SetValue(c_handle);
626 
627  return result;
628 }
629 
636 inline void Controller::Shutdown(rdmnet_disconnect_reason_t disconnect_reason)
637 {
638  rdmnet_controller_destroy(handle_.value(), disconnect_reason);
639  handle_.Clear();
640 }
641 
653 inline etcpal::Expected<ScopeHandle> Controller::AddScope(const char* id, const etcpal::SockAddr& static_broker_addr)
654 {
655  if (!id)
656  return kEtcPalErrInvalid;
657 
658  RdmnetScopeConfig scope_config = {id, static_broker_addr.get()};
659  rdmnet_client_scope_t scope_handle;
660  auto result = rdmnet_controller_add_scope(handle_.value(), &scope_config, &scope_handle);
661  if (result == kEtcPalErrOk)
662  return ScopeHandle(scope_handle);
663  else
664  return result;
665 }
666 
679  const etcpal::SockAddr& static_broker_addr)
680 {
681  return AddScope(id.c_str(), static_broker_addr);
682 }
683 
694 {
695  return AddScope(scope_config.id_string().c_str(), scope_config.static_broker_addr());
696 }
697 
708 {
709  return AddScope(E133_DEFAULT_SCOPE, static_broker_addr);
710 }
711 
721 {
722  return rdmnet_controller_remove_scope(handle_.value(), scope_handle.value(), disconnect_reason);
723 }
724 
741  const char* new_scope_id_str,
742  rdmnet_disconnect_reason_t disconnect_reason,
743  const etcpal::SockAddr& new_static_broker_addr)
744 {
745  if (!new_scope_id_str)
746  return kEtcPalErrInvalid;
747 
748  RdmnetScopeConfig new_scope_config = {new_scope_id_str, new_static_broker_addr.get()};
749  return rdmnet_controller_change_scope(handle_.value(), scope_handle.value(), &new_scope_config, disconnect_reason);
750 }
751 
766  const Scope& new_scope_config,
767  rdmnet_disconnect_reason_t disconnect_reason)
768 {
769  return ChangeScope(scope_handle, new_scope_config.id_string().c_str(), disconnect_reason,
770  new_scope_config.static_broker_addr());
771 }
772 
785 inline etcpal::Error Controller::ChangeSearchDomain(const char* new_search_domain,
786  rdmnet_disconnect_reason_t disconnect_reason)
787 {
788  if (!new_search_domain)
789  return kEtcPalErrInvalid;
790 
791  return rdmnet_controller_change_search_domain(handle_.value(), new_search_domain, disconnect_reason);
792 }
793 
807  const DestinationAddr& destination,
808  rdmnet_command_class_t command_class,
809  uint16_t param_id,
810  const uint8_t* data,
811  uint8_t data_len)
812 {
813  uint32_t seq_num;
814  etcpal_error_t res = rdmnet_controller_send_rdm_command(handle_.value(), scope_handle.value(), &destination.get(),
815  command_class, param_id, data, data_len, &seq_num);
816  if (res == kEtcPalErrOk)
817  return seq_num;
818  else
819  return res;
820 }
821 
834  const DestinationAddr& destination,
835  uint16_t param_id,
836  const uint8_t* data,
837  uint8_t data_len)
838 {
839  uint32_t seq_num;
840  etcpal_error_t res = rdmnet_controller_send_get_command(handle_.value(), scope_handle.value(), &destination.get(),
841  param_id, data, data_len, &seq_num);
842  if (res == kEtcPalErrOk)
843  return seq_num;
844  else
845  return res;
846 }
847 
860  const DestinationAddr& destination,
861  uint16_t param_id,
862  const uint8_t* data,
863  uint8_t data_len)
864 {
865  uint32_t seq_num;
866  etcpal_error_t res = rdmnet_controller_send_set_command(handle_.value(), scope_handle.value(), &destination.get(),
867  param_id, data, data_len, &seq_num);
868  if (res == kEtcPalErrOk)
869  return seq_num;
870  else
871  return res;
872 }
873 
883 {
884  return rdmnet_controller_request_client_list(handle_.value(), scope_handle.value());
885 }
886 
897 inline etcpal::Error Controller::RequestResponderIds(ScopeHandle scope_handle, const rdm::Uid* uids, size_t num_uids)
898 {
899  if (!uids || (num_uids == 0))
900  return kEtcPalErrInvalid;
901 
902  std::vector<RdmUid> c_uids;
903  c_uids.reserve(num_uids);
904  std::transform(uids, uids + num_uids, std::back_inserter(c_uids), [](const rdm::Uid& uid) { return uid.get(); });
905  return rdmnet_controller_request_responder_ids(handle_.value(), scope_handle.value(), c_uids.data(), c_uids.size());
906 }
907 
918 {
919  return RequestResponderIds(scope_handle, uids.data(), uids.size());
920 }
921 
934  const SavedRdmCommand& received_cmd,
935  const uint8_t* response_data,
936  size_t response_data_len)
937 {
938  return rdmnet_controller_send_rdm_ack(handle_.value(), scope_handle.value(), &received_cmd.get(), response_data,
939  response_data_len);
940 }
941 
953  const SavedRdmCommand& received_cmd,
954  rdm_nack_reason_t nack_reason)
955 {
956  return rdmnet_controller_send_rdm_nack(handle_.value(), scope_handle.value(), &received_cmd.get(), nack_reason);
957 }
958 
971  const SavedRdmCommand& received_cmd,
972  uint16_t raw_nack_reason)
973 {
974  return rdmnet_controller_send_rdm_nack(handle_.value(), scope_handle.value(), &received_cmd.get(),
975  static_cast<rdm_nack_reason_t>(raw_nack_reason));
976 }
977 
990  uint16_t param_id,
991  const uint8_t* data,
992  size_t data_len)
993 {
994  return rdmnet_controller_send_rdm_update(handle_.value(), scope_handle.value(), 0, param_id, data, data_len);
995 }
996 
1008  const uint8_t* response_data,
1009  uint8_t response_data_len)
1010 {
1011  return rdmnet_controller_send_llrp_ack(handle_.value(), &received_cmd.get(), response_data, response_data_len);
1012 }
1013 
1023 inline etcpal::Error Controller::SendLlrpNack(const llrp::SavedRdmCommand& received_cmd, rdm_nack_reason_t nack_reason)
1024 {
1025  return rdmnet_controller_send_llrp_nack(handle_.value(), &received_cmd.get(), nack_reason);
1026 }
1027 
1038 inline etcpal::Error Controller::SendLlrpNack(const llrp::SavedRdmCommand& received_cmd, uint16_t raw_nack_reason)
1039 {
1040  return rdmnet_controller_send_llrp_nack(handle_.value(), &received_cmd.get(),
1041  static_cast<rdm_nack_reason_t>(raw_nack_reason));
1042 }
1043 
1046 {
1047  return handle_;
1048 }
1049 
1053 {
1054  return my_rdm_data_;
1055 }
1056 
1059 {
1060  return notify_;
1061 }
1062 
1066 {
1067  return rdm_cmd_handler_;
1068 }
1069 
1075 {
1076  std::string scope_id(E133_SCOPE_STRING_PADDED_LENGTH, 0);
1077  EtcPalSockAddr static_broker_addr;
1078  etcpal_error_t res =
1079  rdmnet_controller_get_scope(handle_.value(), scope_handle.value(), &scope_id[0], &static_broker_addr);
1080 
1081  if (res == kEtcPalErrOk)
1082  return Scope(scope_id, static_broker_addr);
1083  else
1084  return res;
1085 }
1086 
1088 inline void Controller::UpdateRdmData(const RdmData& new_data)
1089 {
1090  // TODO implement
1091  ETCPAL_UNUSED_ARG(new_data);
1092 }
1093 
1094 }; // namespace rdmnet
1095 
1096 #endif // RDMNET_CPP_CONTROLLER_H_
T back_inserter(T... args)
T c_str(T... args)
ETCPAL_CONSTEXPR_14 void Clear()
ETCPAL_CONSTEXPR_14 void SetValue(const ValueType &new_value)
constexpr ValueType value() const
constexpr const EtcPalSockAddr & get() const noexcept
constexpr const EtcPalUuid & get() const noexcept
Information about a failed connection to a broker delivered to an RDMnet callback function.
Definition: client.h:228
Information about a successful connection to a broker delivered to an RDMnet callback function.
Definition: client.h:158
Information about a disconnect event from a broker delivered to an RDMnet callback function.
Definition: client.h:346
A base class for a class that receives notification callbacks from a controller.
Definition: controller.h:77
virtual void HandleRptStatus(Handle controller_handle, ScopeHandle scope_handle, const RptStatus &status)=0
An RPT status message has been received in response to a previously-sent RDM command.
virtual void HandleBrokerConnectFailed(Handle controller_handle, ScopeHandle scope_handle, const ClientConnectFailedInfo &info)=0
A connection attempt failed between a controller and a broker.
virtual void HandleConnectedToBroker(Handle controller_handle, ScopeHandle scope_handle, const ClientConnectedInfo &info)=0
A controller has successfully connected to a broker.
virtual void HandleResponderIdsReceived(Handle controller_handle, ScopeHandle scope_handle, const DynamicUidAssignmentList &list)
A set of previously-requested mappings of dynamic UIDs to responder IDs has been received.
Definition: controller.h:138
virtual void HandleDisconnectedFromBroker(Handle controller_handle, ScopeHandle scope_handle, const ClientDisconnectedInfo &info)=0
A controller which was previously connected to a broker has disconnected.
virtual void HandleClientListUpdate(Handle controller_handle, ScopeHandle scope_handle, client_list_action_t list_action, const RptClientList &list)=0
A client list update has been received from a broker.
virtual bool HandleRdmResponse(Handle controller_handle, ScopeHandle scope_handle, const RdmResponse &resp)=0
An RDM response has been received.
A base class for a class that receives RDM commands addressed to a controller.
Definition: controller.h:153
virtual RdmResponseAction HandleLlrpRdmCommand(Handle controller_handle, const llrp::RdmCommand &cmd)
An RDM command has been received over LLRP, addressed to a controller.
Definition: controller.h:168
virtual RdmResponseAction HandleRdmCommand(Handle controller_handle, ScopeHandle scope_handle, const RdmCommand &cmd)=0
An RDM command has been received addressed to a controller.
An instance of RDMnet controller functionality.
Definition: controller.h:67
Controller(Controller &&other)=default
Move a controller instance.
etcpal::Error SendRdmUpdate(ScopeHandle scope_handle, uint16_t param_id, const uint8_t *data=nullptr, size_t data_len=0)
Send an asynchronous RDM GET response to update the value of a local parameter.
Definition: controller.h:989
const RdmData & rdm_data() const
Retrieve the RDM data that this controller was configured with on startup.
Definition: controller.h:1052
etcpal::Error SendLlrpNack(const llrp::SavedRdmCommand &received_cmd, rdm_nack_reason_t nack_reason)
Send a negative acknowledge (NACK) response to an LLRP RDM command received by a controller.
Definition: controller.h:1023
etcpal::Expected< uint32_t > SendRdmCommand(ScopeHandle scope_handle, const DestinationAddr &destination, rdmnet_command_class_t command_class, uint16_t param_id, const uint8_t *data=nullptr, uint8_t data_len=0)
Send an RDM command from a controller on a scope.
Definition: controller.h:806
etcpal::Error Startup(NotifyHandler &notify_handler, const Settings &settings, const RdmData &rdm_data)
Allocate resources and start up this controller with the given configuration.
Definition: controller.h:521
etcpal::Expected< ScopeHandle > AddDefaultScope(const etcpal::SockAddr &static_broker_addr=etcpal::SockAddr{})
Shortcut to add the default RDMnet scope to a controller instance.
Definition: controller.h:707
etcpal::Error SendLlrpAck(const llrp::SavedRdmCommand &received_cmd, const uint8_t *response_data=nullptr, uint8_t response_data_len=0)
Send an acknowledge (ACK) response to an LLRP RDM command received by a controller.
Definition: controller.h:1007
Controller::RdmCommandHandler * rdm_command_handler() const
Retrieve the Controller::RdmCommandHandler reference that this controller was configured with.
Definition: controller.h:1065
etcpal::Error SendRdmNack(ScopeHandle scope_handle, const SavedRdmCommand &received_cmd, rdm_nack_reason_t nack_reason)
Send a negative acknowledge (NACK) response to an RDM command received by a controller.
Definition: controller.h:952
etcpal::Error RequestResponderIds(ScopeHandle scope_handle, const rdm::Uid *uids, size_t num_uids)
Request mappings from dynamic UIDs to Responder IDs (RIDs).
Definition: controller.h:897
etcpal::Expected< uint32_t > SendGetCommand(ScopeHandle scope_handle, const DestinationAddr &destination, uint16_t param_id, const uint8_t *data=nullptr, uint8_t data_len=0)
Send an RDM GET command from a controller on a scope.
Definition: controller.h:833
Controller & operator=(Controller &&other)=default
Move a controller instance.
Handle handle() const
Retrieve the handle of a controller instance.
Definition: controller.h:1045
void UpdateRdmData(const RdmData &new_data)
Update the data used to identify this controller to other controllers.
Definition: controller.h:1088
etcpal::Error RequestClientList(ScopeHandle scope_handle)
Request a client list from a broker.
Definition: controller.h:882
void Shutdown(rdmnet_disconnect_reason_t disconnect_reason=kRdmnetDisconnectShutdown)
Shut down this controller and deallocate resources.
Definition: controller.h:636
etcpal::Error ChangeScope(ScopeHandle scope_handle, const char *new_scope_id_str, rdmnet_disconnect_reason_t disconnect_reason, const etcpal::SockAddr &new_static_broker_addr=etcpal::SockAddr{})
Change the configuration of a scope on a controller.
Definition: controller.h:740
etcpal::Expected< Scope > scope(ScopeHandle scope_handle) const
Retrieve the scope configuration associated with a given scope handle.
Definition: controller.h:1074
Controller::NotifyHandler * notify_handler() const
Retrieve the Controller::NotifyHandler reference that this controller was configured with.
Definition: controller.h:1058
etcpal::Error ChangeSearchDomain(const char *new_search_domain, rdmnet_disconnect_reason_t disconnect_reason)
Change the controller's DNS search domain.
Definition: controller.h:785
etcpal::Error RemoveScope(ScopeHandle scope_handle, rdmnet_disconnect_reason_t disconnect_reason)
Remove a previously-added scope from this controller instance.
Definition: controller.h:720
etcpal::OpaqueId< detail::ControllerHandleType, rdmnet_controller_t, RDMNET_CONTROLLER_INVALID > Handle
A handle type used by the RDMnet library to identify controller instances.
Definition: controller.h:70
etcpal::Expected< ScopeHandle > AddScope(const char *id, const etcpal::SockAddr &static_broker_addr=etcpal::SockAddr{})
Add a new scope to this controller instance.
Definition: controller.h:653
etcpal::Error SendRdmAck(ScopeHandle scope_handle, const SavedRdmCommand &received_cmd, const uint8_t *response_data=nullptr, size_t response_data_len=0)
Send an acknowledge (ACK) response to an RDM command received by a controller.
Definition: controller.h:933
etcpal::Expected< uint32_t > SendSetCommand(ScopeHandle scope_handle, const DestinationAddr &destination, uint16_t param_id, const uint8_t *data=nullptr, uint8_t data_len=0)
Send an RDM SET command from a controller on a scope.
Definition: controller.h:859
A destination address for an RDM command in RDMnet's RPT protocol.
Definition: client.h:79
constexpr const RdmnetDestinationAddr & get() const noexcept
Get a const reference to the underlying C type.
Definition: client.h:139
A list of mappings from dynamic UIDs to responder IDs received from an RDMnet broker.
Definition: dynamic_uid.h:99
An RDM command received over RDMnet and delivered to an RDMnet callback function.
Definition: rdm_command.h:43
A class representing a synchronous action to take in response to a received RDM command.
Definition: common.h:146
static RdmResponseAction SendNack(rdm_nack_reason_t nack_reason)
Send an RDM NACK with a reason code.
Definition: common.h:172
An RDM response received over RDMnet and delivered to an RDMnet callback function.
Definition: rdm_response.h:47
A list of RPT client entries.
Definition: rpt_client.h:89
An RPT status message received over RDMnet and delivered to an RDMnet callback function.
Definition: rpt_status.h:42
An RDM command received over RDMnet by a local component and saved for a later response.
Definition: rdm_command.h:87
ETCPAL_CONSTEXPR_14 RdmnetSavedRdmCommand & get() noexcept
Get a mutable reference to the underlying C type.
Definition: rdm_command.h:374
An RDMnet scope configuration.
Definition: client.h:469
const etcpal::SockAddr & static_broker_addr() const noexcept
The static broker address associated with this scope.
Definition: client.h:524
const std::string & id_string() const noexcept
The ID string of this scope.
Definition: client.h:515
Definition: controller.h:58
An RDM command received over LLRP and delivered to an RDMnet callback function.
Definition: llrp_rdm_command.h:46
An RDM command received over LLRP by a local component and saved for a later response.
Definition: llrp_rdm_command.h:91
ETCPAL_CONSTEXPR_14 LlrpSavedRdmCommand & get() noexcept
Get a mutable reference to the underlying C type.
Definition: llrp_rdm_command.h:391
Definitions for the RDMnet Controller API.
C++ wrapper for RDMnet client API definitions.
C++ wrapper for the RDMnet init/deinit functions.
RDMnet C++ message type definitions.
T data(T... args)
etcpal_error_t
kEtcPalErrInvalid
kEtcPalErrOk
rdmnet_disconnect_reason_t
Definition: common.h:85
rdmnet_command_class_t
An RDM command class, for RDMnet purposes.
Definition: common.h:371
client_list_action_t
Definition: client.h:50
int rdmnet_client_scope_t
Definition: client.h:41
@ kRdmnetDisconnectShutdown
Definition: common.h:87
etcpal_error_t rdmnet_controller_change_scope(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetScopeConfig *new_scope_config, rdmnet_disconnect_reason_t disconnect_reason)
Change the configuration of a scope on a controller.
Definition: controller.c:436
etcpal_error_t rdmnet_controller_create(const RdmnetControllerConfig *config, rdmnet_controller_t *handle)
Create a new instance of RDMnet controller functionality.
Definition: controller.c:255
etcpal_error_t rdmnet_controller_send_llrp_ack(rdmnet_controller_t controller_handle, const LlrpSavedRdmCommand *received_cmd, const uint8_t *response_data, uint8_t response_data_len)
Send an LLRP RDM ACK response from a controller.
Definition: controller.c:869
etcpal_error_t rdmnet_controller_send_rdm_ack(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetSavedRdmCommand *received_cmd, const uint8_t *response_data, size_t response_data_len)
Send an RDM ACK response from a controller on a scope.
Definition: controller.c:756
etcpal_error_t rdmnet_controller_send_rdm_update(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, uint16_t subdevice, uint16_t param_id, const uint8_t *data, size_t data_len)
Send an asynchronous RDM GET response to update the value of a local parameter.
Definition: controller.c:836
etcpal_error_t rdmnet_controller_add_scope(rdmnet_controller_t controller_handle, const RdmnetScopeConfig *scope_config, rdmnet_client_scope_t *scope_handle)
Add a new scope to a controller instance.
Definition: controller.c:330
etcpal_error_t rdmnet_controller_destroy(rdmnet_controller_t controller_handle, rdmnet_disconnect_reason_t reason)
Destroy a controller instance.
Definition: controller.c:293
etcpal_error_t rdmnet_controller_send_set_command(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetDestinationAddr *destination, uint16_t param_id, const uint8_t *data, uint8_t data_len, uint32_t *seq_num)
Send an RDM SET command from a controller on a scope.
Definition: controller.c:713
etcpal_error_t rdmnet_controller_request_client_list(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle)
Request a client list from a broker.
Definition: controller.c:542
#define RDMNET_CONTROLLER_INVALID
Definition: controller.h:56
etcpal_error_t rdmnet_controller_send_get_command(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetDestinationAddr *destination, uint16_t param_id, const uint8_t *data, uint8_t data_len, uint32_t *seq_num)
Send an RDM GET command from a controller on a scope.
Definition: controller.c:666
etcpal_error_t rdmnet_controller_request_responder_ids(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmUid *uids, size_t num_uids)
Request a set of responder IDs corresponding with dynamic responder UIDs from a broker.
Definition: controller.c:574
etcpal_error_t rdmnet_controller_change_search_domain(rdmnet_controller_t controller_handle, const char *new_search_domain, rdmnet_disconnect_reason_t disconnect_reason)
Change the controller's DNS search domain.
Definition: controller.c:508
etcpal_error_t rdmnet_controller_get_scope(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, char *scope_str_buf, EtcPalSockAddr *static_broker_addr)
Retrieve the scope configuration of a previously-added scope.
Definition: controller.c:474
etcpal_error_t rdmnet_controller_send_rdm_command(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetDestinationAddr *destination, rdmnet_command_class_t command_class, uint16_t param_id, const uint8_t *data, uint8_t data_len, uint32_t *seq_num)
Send an RDM command from a controller on a scope.
Definition: controller.c:618
etcpal_error_t rdmnet_controller_send_rdm_nack(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, const RdmnetSavedRdmCommand *received_cmd, rdm_nack_reason_t nack_reason)
Send an RDM NACK response from a controller on a scope.
Definition: controller.c:795
etcpal_error_t rdmnet_controller_remove_scope(rdmnet_controller_t controller_handle, rdmnet_client_scope_t scope_handle, rdmnet_disconnect_reason_t reason)
Remove a previously-added scope from a controller instance.
Definition: controller.c:402
etcpal_error_t rdmnet_controller_send_llrp_nack(rdmnet_controller_t controller_handle, const LlrpSavedRdmCommand *received_cmd, rdm_nack_reason_t nack_reason)
Send an LLRP RDM NACK response from a controller.
Definition: controller.c:902
#define RDMNET_CONTROLLER_RDM_DATA_DEFAULT_INIT
A default-value initializer for an RdmnetControllerRdmData struct.
Definition: controller.h:261
int rdmnet_controller_t
Definition: controller.h:54
etcpal::OpaqueId< detail::ScopeHandleType, rdmnet_client_scope_t, RDMNET_CLIENT_SCOPE_INVALID > ScopeHandle
Definition: client.h:456
T internal(T... args)
A namespace which contains all C++ language definitions in the RDMnet library.
Definition: broker.h:45
T reserve(T... args)
T size(T... args)
Definition: message.h:440
Definition: client.h:164
Definition: client.h:151
Definition: client.h:196
A set of information that defines the startup parameters of an RDMnet Controller.
Definition: controller.h:273
Definition: message.h:246
Definition: message.h:54
Definition: message.h:91
Definition: message.h:399
Definition: message.h:194
Definition: client.h:224
Definition: common.h:217
A set of initial identifying RDM data to use for a controller.
Definition: controller.h:201
uint32_t software_version_id
A number representing the version of the controller software.
Definition: controller.h:207
uint16_t model_id
A number representing the product model which implements the controller.
Definition: controller.h:204
RdmData()=default
Create an empty, invalid structure by default - must be filled in before passing to Controller::Start...
bool device_label_settable
Whether the library should allow device_label to be changed remotely.
Definition: controller.h:216
std::string manufacturer_label
The manufacturer name of the controller.
Definition: controller.h:212
std::string software_version_label
The software version of the controller as a string.
Definition: controller.h:214
std::string device_label
A user-settable name for this controller instance.
Definition: controller.h:215
std::string device_model_description
The name of the product model which implements the controller.
Definition: controller.h:213
bool IsValid() const
Whether this data is valid (all string members are non-empty).
Definition: controller.h:504
uint16_t product_category
A number representing the product's primary function.
Definition: controller.h:210
A set of configuration settings that a controller needs to initialize.
Definition: controller.h:182
rdm::Uid uid
The controller's RDM UID. For a dynamic UID, use rdm::Uid::DynamicUidRequest().
Definition: controller.h:184
Settings()=default
Create an empty, invalid data structure by default.
std::string search_domain
(optional) The controller's search domain for discovering brokers.
Definition: controller.h:185
etcpal::Uuid cid
The controller's Component Identifier (CID).
Definition: controller.h:183
bool IsValid() const
Determine whether a controller Settings instance contains valid data for RDMnet operation.
Definition: controller.h:460
bool create_llrp_target
(optional) Whether to create an LLRP target associated with this controller.
Definition: controller.h:188
T transform(T... args)