diff --git a/Development/cmake/NmosCppLibraries.cmake b/Development/cmake/NmosCppLibraries.cmake index 6132e144b..ca49cd857 100644 --- a/Development/cmake/NmosCppLibraries.cmake +++ b/Development/cmake/NmosCppLibraries.cmake @@ -835,6 +835,91 @@ target_include_directories(nmos_is12_schemas PUBLIC list(APPEND NMOS_CPP_TARGETS nmos_is12_schemas) add_library(nmos-cpp::nmos_is12_schemas ALIAS nmos_is12_schemas) +# nmos_is14_schemas library + +set(NMOS_IS14_SCHEMAS_HEADERS + nmos/is14_schemas/is14_schemas.h + ) + +set(NMOS_IS14_V1_0_TAG v1.0.x) + +set(NMOS_IS14_V1_0_SCHEMAS_JSON + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/base.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/bulkProperties-get-response.json + + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/bulkProperties-patch-request.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/bulkProperties-patch-response.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/bulkProperties-put-request.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/bulkProperties-put-response.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/descriptor-get.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/method-patch-request.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/method-patch-response.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/methods-base.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/ms05-error.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/properties-base.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/property.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/property-descriptor.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/property-value-get.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/property-value-put-request.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/property-value-put-response.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/rolePath.json + third_party/is-14/${NMOS_IS14_V1_0_TAG}/APIs/schemas/rolePaths-base.json + ) + +set(NMOS_IS14_SCHEMAS_JSON_MATCH "third_party/is-14/([^/]+)/APIs/schemas/([^;]+)\\.json") +set(NMOS_IS14_SCHEMAS_SOURCE_REPLACE "${CMAKE_CURRENT_BINARY_DIR_REPLACE}/nmos/is14_schemas/\\1/\\2.cpp") +string(REGEX REPLACE "${NMOS_IS14_SCHEMAS_JSON_MATCH}(;|$)" "${NMOS_IS14_SCHEMAS_SOURCE_REPLACE}\\3" NMOS_IS14_V1_0_SCHEMAS_SOURCES "${NMOS_IS14_V1_0_SCHEMAS_JSON}") + +foreach(JSON ${NMOS_IS14_V1_0_SCHEMAS_JSON}) + string(REGEX REPLACE "${NMOS_IS14_SCHEMAS_JSON_MATCH}" "${NMOS_IS14_SCHEMAS_SOURCE_REPLACE}" SOURCE "${JSON}") + string(REGEX REPLACE "${NMOS_IS14_SCHEMAS_JSON_MATCH}" "\\1" NS "${JSON}") + string(REGEX REPLACE "${NMOS_IS14_SCHEMAS_JSON_MATCH}" "\\2" VAR "${JSON}") + string(MAKE_C_IDENTIFIER "${NS}" NS) + string(MAKE_C_IDENTIFIER "${VAR}" VAR) + + file(WRITE "${SOURCE}.in" "\ +// Auto-generated from: ${JSON}\n\ +\n\ +namespace nmos\n\ +{\n\ + namespace is14_schemas\n\ + {\n\ + namespace ${NS}\n\ + {\n\ + const char* ${VAR} = R\"-auto-generated-(") + + file(READ "${JSON}" RAW) + file(APPEND "${SOURCE}.in" "${RAW}") + + file(APPEND "${SOURCE}.in" ")-auto-generated-\";\n\ + }\n\ + }\n\ +}\n") + + configure_file("${SOURCE}.in" "${SOURCE}" COPYONLY) +endforeach() + +add_library( + nmos_is14_schemas STATIC + ${NMOS_IS14_SCHEMAS_HEADERS} + ${NMOS_IS14_V1_0_SCHEMAS_SOURCES} + ) + +source_group("nmos\\is14_schemas\\Header Files" FILES ${NMOS_IS14_SCHEMAS_HEADERS}) +source_group("nmos\\is14_schemas\\${NMOS_IS14_V1_0_TAG}\\Source Files" FILES ${NMOS_IS14_V1_0_SCHEMAS_SOURCES}) + +target_link_libraries( + nmos_is14_schemas PRIVATE + nmos-cpp::compile-settings + ) +target_include_directories(nmos_is14_schemas PUBLIC + $ + $ + ) + +list(APPEND NMOS_CPP_TARGETS nmos_is14_schemas) +add_library(nmos-cpp::nmos_is14_schemas ALIAS nmos_is14_schemas) + # nmos-cpp library if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") @@ -928,6 +1013,10 @@ set(NMOS_CPP_NMOS_SOURCES nmos/channels.cpp nmos/client_utils.cpp nmos/components.cpp + nmos/configuration_api.cpp + nmos/configuration_methods.cpp + nmos/configuration_resources.cpp + nmos/configuration_utils.cpp nmos/connection_activation.cpp nmos/connection_api.cpp nmos/connection_events_activation.cpp @@ -1022,6 +1111,11 @@ set(NMOS_CPP_NMOS_HEADERS nmos/colorspace.h nmos/components.h nmos/copyable_atomic.h + nmos/configuration_api.h + nmos/configuration_handlers.h + nmos/configuration_methods.h + nmos/configuration_resources.h + nmos/configuration_utils.h nmos/connection_activation.h nmos/connection_api.h nmos/connection_events_activation.h @@ -1057,6 +1151,7 @@ set(NMOS_CPP_NMOS_HEADERS nmos/is09_versions.h nmos/is10_versions.h nmos/is12_versions.h + nmos/is14_versions.h nmos/issuers.h nmos/json_fields.h nmos/json_schema.h @@ -1207,6 +1302,7 @@ target_link_libraries( nmos-cpp::nmos_is09_schemas nmos-cpp::nmos_is10_schemas nmos-cpp::nmos_is12_schemas + nmos-cpp::nmos_is14_schemas nmos-cpp::mdns nmos-cpp::slog nmos-cpp::OpenSSL diff --git a/Development/cmake/NmosCppTest.cmake b/Development/cmake/NmosCppTest.cmake index 9eb187fd4..b2328fd74 100644 --- a/Development/cmake/NmosCppTest.cmake +++ b/Development/cmake/NmosCppTest.cmake @@ -44,8 +44,11 @@ set(NMOS_CPP_TEST_NMOS_TEST_SOURCES nmos/test/capabilities_test.cpp nmos/test/channels_test.cpp nmos/test/condition_variable_test.cpp - nmos/test/control_protocol_test.cpp + nmos/test/configuration_methods_test.cpp + nmos/test/configuration_resources_test.cpp + nmos/test/configuration_utils_test.cpp nmos/test/control_protocol_methods_test.cpp + nmos/test/control_protocol_test.cpp nmos/test/control_protocol_utils_test.cpp nmos/test/did_sdid_test.cpp nmos/test/event_type_test.cpp diff --git a/Development/nmos-cpp-node/config.json b/Development/nmos-cpp-node/config.json index 1508d0bb9..c529de695 100644 --- a/Development/nmos-cpp-node/config.json +++ b/Development/nmos-cpp-node/config.json @@ -152,6 +152,7 @@ //"system_port": 10641, // control_protocol_ws_port [node]: used to construct request URLs for the Control Protocol websocket, or negative to disable the control protocol features //"control_protocol_ws_port": 3218, + //"configuration_port": 3219, // listen_backlog [registry, node]: the maximum length of the queue of pending connections, or zero for the implementation default (the implementation may not honour this value) //"listen_backlog": 0, diff --git a/Development/nmos-cpp-node/main.cpp b/Development/nmos-cpp-node/main.cpp index 9b9e23100..460ceb8ca 100644 --- a/Development/nmos-cpp-node/main.cpp +++ b/Development/nmos-cpp-node/main.cpp @@ -142,7 +142,7 @@ int main(int argc, char* argv[]) // only configure the following callbacks if IS-12/BCP-008-01 is required // Note: // the get_control_class_descriptor, get_control_datatype_descriptor and get_control_protocol_method_descriptor callbacks must be set up before executing the make_node_server - nmos::experimental::control_protocol_state control_protocol_state(node_implementation.get_lost_packet_counters, node_implementation.get_late_packet_counters, node_implementation.reset_monitor, node_implementation.control_protocol_property_changed); + nmos::experimental::control_protocol_state control_protocol_state(node_implementation.control_protocol_property_changed, node_implementation.create_validation_fingerprint, node_implementation.validate_validation_fingerprint, node_implementation.get_read_only_modification_allow_list, node_implementation.remove_device_model_object, node_implementation.create_device_model_object, node_implementation.get_lost_packet_counters, node_implementation.get_late_packet_counters, node_implementation.reset_monitor); if (0 <= nmos::fields::control_protocol_ws_port(node_model.settings)) { node_implementation diff --git a/Development/nmos-cpp-node/node_implementation.cpp b/Development/nmos-cpp-node/node_implementation.cpp index eadd30869..9661a1093 100644 --- a/Development/nmos-cpp-node/node_implementation.cpp +++ b/Development/nmos-cpp-node/node_implementation.cpp @@ -19,6 +19,10 @@ #include "nmos/channelmapping_resources.h" #include "nmos/clock_name.h" #include "nmos/colorspace.h" +#include "nmos/configuration_handlers.h" +#include "nmos/configuration_methods.h" +#include "nmos/configuration_resources.h" +#include "nmos/configuration_utils.h" #include "nmos/connection_resources.h" #include "nmos/connection_events_activation.h" #include "nmos/control_protocol_resources.h" @@ -298,7 +302,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr const auto is_control_protocol_resource = [&resource]() { return nmos::types::all_nc.end() != std::find(nmos::types::all_nc.begin(), nmos::types::all_nc.end(), resource.type); }; const std::pair id_type{ resource.id, resource.type }; - const bool success = is_control_protocol_resource() ? insert_control_protocol_resource(resources, std::move(resource)).second : insert_resource(resources, std::move(resource)).second; + const bool success = is_control_protocol_resource() ? nmos::nc::insert_resource(resources, std::move(resource)).second : insert_resource(resources, std::move(resource)).second; if (success) slog::log(gate, SLOG_FLF) << "Updated model with " << id_type; @@ -941,7 +945,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr if (0 <= nmos::fields::control_protocol_ws_port(model.settings)) { // example to create a non-standard Gain control class - const auto gain_control_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, 0, { 1 }); + const auto gain_control_class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 1 }); const web::json::field_as_number gain_value{ U("gainValue") }; { // Gain control class property descriptors @@ -956,14 +960,14 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // helper function to create Gain control instance auto make_gain_control = [&gain_value, &gain_control_class_id](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, float gain) { - auto data = nmos::details::make_nc_worker(gain_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); + auto data = nmos::nc::details::make_worker(gain_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); data[gain_value] = value::number(gain); return nmos::control_protocol_resource{ nmos::is12_versions::v1_0, nmos::types::nc_worker, std::move(data), true }; }; // example to create a non-standard Example control class - const auto example_control_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, 0, { 2 }); + const auto example_control_class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 2 }); const web::json::field_as_number enum_property{ U("enumProperty") }; const web::json::field_as_string string_property{ U("stringProperty") }; const web::json::field_as_number number_property{ U("numberProperty") }; @@ -992,17 +996,17 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr }; { // following constraints are used for the example control class level 0 datatype, level 1 property constraints and the method parameters constraints - auto make_string_example_argument_constraints = []() {return nmos::details::make_nc_parameter_constraints_string(10, U("^[a-z]+$")); }; - auto make_number_example_argument_constraints = []() {return nmos::details::make_nc_parameter_constraints_number(0, 1000, 1); }; + auto make_string_example_argument_constraints = []() {return nmos::nc::details::make_parameter_constraints_string(10, U("^[a-z]+$")); }; + auto make_number_example_argument_constraints = []() {return nmos::nc::details::make_parameter_constraints_number(0, 1000, 1); }; // Example control class property descriptors std::vector example_control_property_descriptors = { nmos::experimental::make_control_class_property_descriptor(U("Example enum property"), { 3, 1 }, enum_property, U("ExampleEnum")), // create "Example string property" with level 1: property constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_string to create property constraints + // use nmos::nc::details::make_parameter_constraints_string to create property constraints nmos::experimental::make_control_class_property_descriptor(U("Example string property"), { 3, 2 }, string_property, U("NcString"), false, false, false, false, make_string_example_argument_constraints()), // create "Example numeric property" with level 1: property constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_number to create property constraints + // use nmos::nc::details::make_parameter_constraints_number to create property constraints nmos::experimental::make_control_class_property_descriptor(U("Example numeric property"), { 3, 3 }, number_property, U("NcUint64"), false, false, false, false, make_number_example_argument_constraints()), nmos::experimental::make_control_class_property_descriptor(U("Example deprecated numeric property"), { 3, 4 }, deprecated_number_property, U("NcUint64"), false, false, false, true, make_number_example_argument_constraints()), nmos::experimental::make_control_class_property_descriptor(U("Example boolean property"), { 3, 5 }, boolean_property, U("NcBoolean")), @@ -1011,12 +1015,12 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr nmos::experimental::make_control_class_property_descriptor(U("Example method simple args invoke counter"), { 3, 8 }, method_simple_args_count, U("NcUint64"), true), nmos::experimental::make_control_class_property_descriptor(U("Example method obj arg invoke counter"), { 3, 9 }, method_object_arg_count, U("NcUint64"), true), // create "Example sequence string property" with level 1: property constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_string to create sequence property constraints + // use nmos::nc::details::make_parameter_constraints_string to create sequence property constraints nmos::experimental::make_control_class_property_descriptor(U("Example string sequence property"), { 3, 10 }, string_sequence, U("NcString"), false, false, true, false, make_string_example_argument_constraints()), nmos::experimental::make_control_class_property_descriptor(U("Example boolean sequence property"), { 3, 11 }, boolean_sequence, U("NcBoolean"), false, false, true), nmos::experimental::make_control_class_property_descriptor(U("Example enum sequence property"), { 3, 12 }, enum_sequence, U("ExampleEnum"), false, false, true), // create "Example sequence numeric property" with level 1: property constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_number to create sequence property constraints + // use nmos::nc::details::make_parameter_constraints_number to create sequence property constraints nmos::experimental::make_control_class_property_descriptor(U("Example number sequence property"), { 3, 13 }, number_sequence, U("NcUint64"), false, false, true, false, make_number_example_argument_constraints()), nmos::experimental::make_control_class_property_descriptor(U("Example object sequence property"), { 3, 14 }, object_sequence, U("ExampleDataType"), false, false, true) }; @@ -1027,7 +1031,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr slog::log(gate, SLOG_FLF) << "Executing the example method with no arguments"; - return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::nc::details::make_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; auto example_method_with_simple_args = [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { @@ -1036,7 +1040,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr slog::log(gate, SLOG_FLF) << "Executing the example method with simple arguments: " << arguments.serialize(); - return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::nc::details::make_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; auto example_method_with_object_args = [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { @@ -1045,7 +1049,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr slog::log(gate, SLOG_FLF) << "Executing the example method with object argument: " << arguments.serialize(); - return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); + return nmos::nc::details::make_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::nc_method_status::ok }); }; // Example control class method descriptors std::vector example_control_method_descriptors = @@ -1081,32 +1085,32 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr using web::json::value; auto items = value::array(); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Undefined"), U("Undefined"), example_enum::Undefined)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Alpha"), U("Alpha"), example_enum::Alpha)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Beta"), U("Beta"), example_enum::Beta)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Gamma"), U("Gamma"), example_enum::Gamma)); - return nmos::details::make_nc_datatype_descriptor_enum(U("Example enum datatype"), U("ExampleEnum"), items, value::null()); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Undefined"), U("Undefined"), example_enum::Undefined)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Alpha"), U("Alpha"), example_enum::Alpha)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Beta"), U("Beta"), example_enum::Beta)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Gamma"), U("Gamma"), example_enum::Gamma)); + return nmos::nc::details::make_datatype_descriptor_enum(U("Example enum datatype"), U("ExampleEnum"), items, value::null()); }; auto make_example_datatype_datatype = [&]() { using web::json::value; auto fields = value::array(); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Enum property example"), enum_property, U("ExampleEnum"), false, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Enum property example"), enum_property, U("ExampleEnum"), false, false, value::null())); { // level 0: datatype constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_string to create datatype constraints + // use nmos::nc::details::make_parameter_constraints_string to create datatype constraints value datatype_constraints = make_string_example_argument_constraints(); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("String property example"), string_property, U("NcString"), false, false, datatype_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("String property example"), string_property, U("NcString"), false, false, datatype_constraints)); } { // level 0: datatype constraints, See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use nmos::details::make_nc_parameter_constraints_number to create datatype constraints + // use nmos::nc::details::make_parameter_constraints_number to create datatype constraints value datatype_constraints = make_number_example_argument_constraints(); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Number property example"), number_property, U("NcUint64"), false, false, datatype_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Number property example"), number_property, U("NcUint64"), false, false, datatype_constraints)); } - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Boolean property example"), boolean_property, U("NcBoolean"), false, false, value::null())); - return nmos::details::make_nc_datatype_descriptor_struct(U("Example data type"), U("ExampleDataType"), fields, value::null()); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Boolean property example"), boolean_property, U("NcBoolean"), false, false, value::null())); + return nmos::nc::details::make_datatype_descriptor_struct(U("Example data type"), U("ExampleDataType"), fields, value::null()); }; control_protocol_state.insert(nmos::experimental::datatype_descriptor{ make_example_enum_datatype() }); control_protocol_state.insert(nmos::experimental::datatype_descriptor{ make_example_datatype_datatype() }); @@ -1126,7 +1130,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // helper function to create Example control instance auto make_example_control = [&](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const value& touchpoints, const value& runtime_property_constraints, // level 2: runtime constraints. See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use of make_nc_property_constraints_string and make_nc_property_constraints_number to create runtime constraints + // use of make_property_constraints_string and make_property_constraints_number to create runtime constraints example_enum enum_property_, const utility::string_t& string_property_, uint64_t number_property_, @@ -1142,7 +1146,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr std::vector number_sequence_, std::vector object_sequence_) { - auto data = nmos::details::make_nc_worker(example_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); + auto data = nmos::nc::details::make_worker(example_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); data[enum_property] = value::number(enum_property_); data[string_property] = value::string(string_property_); data[number_property] = value::number(number_property_); @@ -1182,7 +1186,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr }; // example to create a non-standard Temperature Sensor control class - const auto temperature_sensor_control_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, 0, { 3 }); // hmm, maybe pull in out to impl namespace + const auto temperature_sensor_control_class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 3 }); // hmm, maybe pull in out to impl namespace const web::json::field_as_number temperature{ U("temperature") }; // hmm, maybe pull in out to impl namespace const web::json::field_as_string unit{ U("uint") }; // hmm, maybe pull in out to impl namespace { @@ -1201,7 +1205,7 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // helper function to create Temperature Sensor control instance auto make_temperature_sensor = [&temperature, &unit, temperature_sensor_control_class_id](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, float temperature_, const utility::string_t& unit_) { - auto data = nmos::details::make_nc_worker(temperature_sensor_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); + auto data = nmos::nc::details::make_worker(temperature_sensor_control_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true); data[temperature] = value::number(temperature_); data[unit] = value::string(unit_); @@ -1219,6 +1223,9 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // example class manager auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + // example bulk properties manager + auto bulk_properties_manager = nmos::make_bulk_properties_manager(++oid); + // example stereo gain const auto stereo_gain_oid = ++oid; auto stereo_gain = nmos::make_block(stereo_gain_oid, nmos::root_block_oid, U("stereo-gain"), U("Stereo gain"), U("Stereo gain block")); @@ -1229,24 +1236,25 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // example left/right gains auto left_gain = make_gain_control(++oid, channel_gain_oid, U("left-gain"), U("Left gain"), U("Left channel gain"), value::null(), value::null(), 0.0); auto right_gain = make_gain_control(++oid, channel_gain_oid, U("right-gain"), U("Right gain"), U("Right channel gain"), value::null(), value::null(), 0.0); + // add left-gain and right-gain to channel gain - nmos::push_back(channel_gain, left_gain); - nmos::push_back(channel_gain, right_gain); + nmos::nc::push_back(channel_gain, left_gain); + nmos::nc::push_back(channel_gain, right_gain); // example master-gain auto master_gain = make_gain_control(++oid, stereo_gain_oid, U("master-gain"), U("Master gain"), U("Master gain block"), value::null(), value::null(), 0.0); // add channel-gain and master-gain to stereo-gain - nmos::push_back(stereo_gain, channel_gain); - nmos::push_back(stereo_gain, master_gain); + nmos::nc::push_back(stereo_gain, channel_gain); + nmos::nc::push_back(stereo_gain, master_gain); // example example-control auto example_control = make_example_control(++oid, nmos::root_block_oid, U("ExampleControl"), U("Example control worker"), U("Example control worker"), value::null(), // specify the level 2: runtime constraints, see https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - // use of make_nc_property_constraints_string and make_nc_property_constraints_number to create runtime constraints + // use of make_property_constraints_string and make_property_constraints_number to create runtime constraints value_of({ - { nmos::details::make_nc_property_constraints_string({3, 2}, 5, U("^[a-z]+$")) }, - { nmos::details::make_nc_property_constraints_number({3, 3}, 10, 100, 2) } + { nmos::nc::details::make_property_constraints_string({3, 2}, 5, U("^[a-z]+$")) }, + { nmos::nc::details::make_property_constraints_number({3, 3}, 10, 100, 2) } }), example_enum::Undefined, U("test"), @@ -1264,6 +1272,16 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr { make_example_datatype(example_enum::Alpha, U("example"), 50, false), make_example_datatype(example_enum::Gamma, U("different"), 75, true) } ); + // making an object rebuildable allows read only properties to be modified by the Configuration API in Rebuild mode + nmos::make_rebuildable(example_control); + + const auto receivers_block_oid = ++oid; + auto receivers_block = nmos::make_block(receivers_block_oid, nmos::root_block_oid, U("receivers"), U("Receiver Monitors"), U("Receiver Monitors")); + // making a block rebuildable allows block members to be added or removed by the Configuration API in Rebuild mode + nmos::make_rebuildable(receivers_block); + // restrict the allowed classes for members of this block + nmos::set_block_allowed_member_classes(receivers_block, {nmos::nc_receiver_monitor_class_id}); + // example receiver-monitor(s) { int count = 0; @@ -1276,10 +1294,11 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr utility::ostringstream_t role; role << U("receiver-monitor-") << ++count; const auto& receiver = nmos::find_resource(model.node_resources, receiver_id); - const auto receiver_monitor = nmos::make_receiver_monitor(++oid, true, nmos::root_block_oid, role.str(), nmos::fields::label(receiver->data), nmos::fields::description(receiver->data), value_of({ { nmos::details::make_nc_touchpoint_nmos({nmos::ncp_nmos_resource_types::receiver, receiver_id}) } })); - - // add receiver-monitor to root-block - nmos::push_back(root_block, receiver_monitor); + auto receiver_monitor = nmos::make_receiver_monitor(++oid, true, receivers_block_oid, role.str(), nmos::fields::label(receiver->data), nmos::fields::description(receiver->data), value_of({ { nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, receiver_id}) } })); + // optionally indicate dependencies within the device model + nmos::set_object_dependency_paths(receiver_monitor, {{U("root"), U("receivers")}}); + // add receiver-monitor to receivers-block + nmos::nc::push_back(receivers_block, receiver_monitor); } } } @@ -1296,10 +1315,10 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr utility::ostringstream_t role; role << U("sender-monitor-") << ++count; const auto& sender = nmos::find_resource(model.node_resources, sender_id); - const auto sender_monitor = nmos::make_sender_monitor(++oid, true, nmos::root_block_oid, role.str(), nmos::fields::label(sender->data), nmos::fields::description(sender->data), value_of({ { nmos::details::make_nc_touchpoint_nmos({nmos::ncp_nmos_resource_types::sender, sender_id}) } })); + const auto sender_monitor = nmos::make_sender_monitor(++oid, true, nmos::root_block_oid, role.str(), nmos::fields::label(sender->data), nmos::fields::description(sender->data), value_of({ { nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::sender, sender_id}) } })); // add sender-monitor to root-block - nmos::push_back(root_block, sender_monitor); + nmos::nc::push_back(root_block, sender_monitor); } } } @@ -1307,16 +1326,20 @@ void node_implementation_init(nmos::node_model& model, nmos::experimental::contr // example temperature-sensor const auto temperature_sensor = make_temperature_sensor(++oid, nmos::root_block_oid, U("temperature-sensor"), U("Temperature Sensor"), U("Temperature Sensor block"), value::null(), value::null(), 0.0, U("Celsius")); + // add receivers-block to root-block + nmos::nc::push_back(root_block, receivers_block); // add temperature-sensor to root-block - nmos::push_back(root_block, temperature_sensor); + nmos::nc::push_back(root_block, temperature_sensor); // add example-control to root-block - nmos::push_back(root_block, example_control); + nmos::nc::push_back(root_block, example_control); // add stereo-gain to root-block - nmos::push_back(root_block, stereo_gain); + nmos::nc::push_back(root_block, stereo_gain); // add class-manager to root-block - nmos::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, class_manager); // add device-manager to root-block - nmos::push_back(root_block, device_manager); + nmos::nc::push_back(root_block, device_manager); + // add bulk-properties-manager to root-block + nmos::nc::push_back(root_block, bulk_properties_manager); // insert control protocol resources to model insert_root_after(delay_millis, root_block, gate); @@ -1347,6 +1370,8 @@ void node_implementation_run(nmos::node_model& model, nmos::experimental::contro auto& control_protocol_resources = model.control_protocol_resources; auto get_control_protocol_property = nmos::make_get_control_protocol_property_handler(control_protocol_resources, control_protocol_state, gate); + auto set_control_protocol_property = nmos::make_set_control_protocol_property_handler(control_protocol_resources, control_protocol_state, gate); + auto set_receiver_monitor_link_status = nmos::make_set_receiver_monitor_link_status_handler(control_protocol_resources, control_protocol_state, gate); auto set_receiver_monitor_connection_status = nmos::make_set_receiver_monitor_connection_status_handler(control_protocol_resources, control_protocol_state, gate); auto set_receiver_monitor_external_synchronization_status = nmos::make_set_receiver_monitor_external_synchronization_status_handler(control_protocol_resources, control_protocol_state, gate); @@ -1367,10 +1392,10 @@ void node_implementation_run(nmos::node_model& model, nmos::experimental::contro auto cancellation_source = pplx::cancellation_token_source(); auto token = cancellation_source.get_token(); - auto events = pplx::do_while([&model, seed_id, how_many, simulate_status_monitor_activity, ws_sender_ports, rtp_receiver_ports, rtp_sender_ports, get_control_protocol_property, set_receiver_monitor_link_status, set_receiver_monitor_connection_status, set_receiver_monitor_external_synchronization_status, set_receiver_monitor_stream_status, set_receiver_monitor_synchronization_source_id, set_sender_monitor_link_status, set_sender_monitor_transmission_status, set_sender_monitor_external_synchronization_status, set_sender_monitor_essence_status, set_sender_monitor_synchronization_source_id, events_engine, &gate, token] + auto events = pplx::do_while([&model, seed_id, how_many, simulate_status_monitor_activity, ws_sender_ports, rtp_receiver_ports, rtp_sender_ports, get_control_protocol_property, set_receiver_monitor_link_status, set_receiver_monitor_connection_status, set_receiver_monitor_external_synchronization_status, set_receiver_monitor_stream_status, set_receiver_monitor_synchronization_source_id, set_sender_monitor_link_status, set_sender_monitor_transmission_status, set_sender_monitor_external_synchronization_status, set_sender_monitor_essence_status, set_sender_monitor_synchronization_source_id, set_control_protocol_property, events_engine, &gate, token] { const auto event_interval = std::uniform_real_distribution<>(0.5, 5.0)(*events_engine); - return pplx::complete_after(std::chrono::milliseconds(std::chrono::milliseconds::rep(1000 * event_interval)), token).then([&model, seed_id, how_many, simulate_status_monitor_activity, ws_sender_ports, rtp_receiver_ports, rtp_sender_ports, get_control_protocol_property, set_receiver_monitor_link_status, set_receiver_monitor_connection_status, set_receiver_monitor_external_synchronization_status, set_receiver_monitor_stream_status, set_receiver_monitor_synchronization_source_id, set_sender_monitor_link_status, set_sender_monitor_transmission_status, set_sender_monitor_external_synchronization_status, set_sender_monitor_essence_status, set_sender_monitor_synchronization_source_id, events_engine, &gate] + return pplx::complete_after(std::chrono::milliseconds(std::chrono::milliseconds::rep(1000 * event_interval)), token).then([&model, seed_id, how_many, simulate_status_monitor_activity, ws_sender_ports, rtp_receiver_ports, rtp_sender_ports, get_control_protocol_property, set_receiver_monitor_link_status, set_receiver_monitor_connection_status, set_receiver_monitor_external_synchronization_status, set_receiver_monitor_stream_status, set_receiver_monitor_synchronization_source_id, set_sender_monitor_link_status, set_sender_monitor_transmission_status, set_sender_monitor_external_synchronization_status, set_sender_monitor_essence_status, set_sender_monitor_synchronization_source_id, set_control_protocol_property, events_engine, &gate] { auto lock = model.write_lock(); @@ -1413,28 +1438,19 @@ void node_implementation_run(nmos::node_model& model, nmos::experimental::contro // update temperature sensor { - const auto temperature_sensor_control_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, 0, { 3 }); // hmm, maybe pull out temperature_sensor_control_class_id to impl namespace - const web::json::field_as_number temperature{ U("temperature") }; // hmm, maybe pull out temperature field to impl namespace + const auto temperature_sensor_control_class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 3 }); // hmm, maybe pull out temperature_sensor_control_class_id to impl namespace + const auto temperature_value_property_id = nmos::nc_property_id({3, 1}); auto& resources = model.control_protocol_resources; auto found = nmos::find_resource_if(resources, nmos::types::nc_worker, [&temperature_sensor_control_class_id](const nmos::resource& resource) { - return temperature_sensor_control_class_id == nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)); + return temperature_sensor_control_class_id == nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource.data)); }); if (resources.end() != found) { - const auto property_changed_event = nmos::make_property_changed_event(nmos::fields::nc::oid(found->data), - { - { {3, 1}, nmos::nc_property_change_type::type::value_changed, web::json::value(temp.scaled_value()) } // hmm, maybe pull out {3, 1} temperature property id to impl namespace - }); - - nmos::modify_control_protocol_resource(model.control_protocol_resources, found->id, [&](nmos::resource& resource) - { - resource.data[temperature] = temp.scaled_value(); - - }, property_changed_event); + set_control_protocol_property(nmos::fields::nc::oid(found->data), temperature_value_property_id, web::json::value(temp.scaled_value())); } } @@ -1456,7 +1472,7 @@ void node_implementation_run(nmos::node_model& model, nmos::experimental::contro { const auto receiver_id = impl::make_id(seed_id, nmos::types::receiver, port, index); - auto receiver_monitor = nmos::find_control_protocol_resource(resources, nmos::types::nc_status_monitor, receiver_id); + auto receiver_monitor = nmos::nc::find_resource(resources, nmos::types::nc_status_monitor, receiver_id); if (resources.end() != receiver_monitor) { const auto& oid = nmos::fields::nc::oid(receiver_monitor->data); @@ -1527,7 +1543,7 @@ void node_implementation_run(nmos::node_model& model, nmos::experimental::contro { const auto sender_id = impl::make_id(seed_id, nmos::types::sender, port, index); - auto sender_monitor = nmos::find_control_protocol_resource(resources, nmos::types::nc_status_monitor, sender_id); + auto sender_monitor = nmos::nc::find_resource(resources, nmos::types::nc_status_monitor, sender_id); if (resources.end() != sender_monitor) { const auto& oid = nmos::fields::nc::oid(sender_monitor->data); @@ -1927,7 +1943,7 @@ nmos::control_protocol_property_changed_handler make_node_implementation_control // Example Control Protocol WebSocket API Receiver Status Monitor callback to get network interface controller lost packet counters nmos::get_packet_counters_handler make_node_implementation_get_lost_packet_counters_handler() { - return [&]() + return []() { return boost::copy_range>(impl::nic_packet_counters | boost::adaptors::transformed([](const impl::nic_packet_counter& counter) { @@ -1939,7 +1955,7 @@ nmos::get_packet_counters_handler make_node_implementation_get_lost_packet_count // Example Control Protocol WebSocket API Receiver Status Monitor callback to get network interface controller late packet counters nmos::get_packet_counters_handler make_node_implementation_get_late_packet_counters_handler() { - return [&]() + return []() { return boost::copy_range>(impl::nic_packet_counters | boost::adaptors::transformed([](const impl::nic_packet_counter& counter) { @@ -1951,7 +1967,7 @@ nmos::get_packet_counters_handler make_node_implementation_get_late_packet_count // Example Control Protocol WebSocket API Receiver Status Monitor callback to reset network interface controller packet counters nmos::reset_monitor_handler make_node_implementation_reset_monitor_handler() { - return [&]() + return []() { for (auto& counter : impl::nic_packet_counters) { @@ -1961,6 +1977,82 @@ nmos::reset_monitor_handler make_node_implementation_reset_monitor_handler() }; } +// Example Device Configuration callbacks called when a rebuildable object is modified in Rebuild mode. + +// IS-14 Device Configuration callback +// This function should generate a fingerprint that can be used for subsequent validation. +nmos::create_validation_fingerprint_handler make_create_validation_fingerprint_handler() +{ + return [](const nmos::resources& resources, const nmos::resource& resource) + { + return U("Sony nmos-cpp node"); + }; +} + +// IS-14 Device Configuration callback +// This function called by a validate or restore and can be used to validate a validation fingerprint. Returning false will fail the validate or restore operation. +nmos::validate_validation_fingerprint_handler make_validate_validation_fingerprint_handler() +{ + return [](const nmos::resources& resources, const nmos::resource& resource, const utility::string_t& validation_fingerprint) + { + return true; + }; +} + +// IS-14 Device Configuration callback +// This function is called when the Device Configuration API is attempting to modify +// the read only properties of a rebuildable Device Model object. This callback returns an "allow list" of property ids +// for properties that can be updated - the "allowed" read only property will be updated according to backup dataset received. +nmos::get_read_only_modification_allow_list_handler make_get_read_only_modification_allow_list_handler(slog::base_gate& gate) +{ + return [&gate](const nmos::resources& resources, const nmos::resource& resource, const std::vector& target_role_path, const std::vector& property_ids) + { + // Use this function to create allow list of property ids for properties in the object should be modified by the configuration API + slog::log(gate, SLOG_FLF) << nmos::stash_category(impl::categories::node_implementation) << "Do filter_property_holders"; + + // Filter out any read only properties that should not be modified + return property_ids; + }; +} + +// IS-14 Device Configuration callback +// This function is called before an object is deleted from the device model. +// If this function returns true and validate is false then the object will be deleted. +// If this function returns true/false or validate is true then the object will not be deleted. +// If this function returns false an appropriate error will be passed to the calling client. +nmos::remove_device_model_object_handler make_remove_device_model_object_handler() +{ + return [](const nmos::resource& resource, const std::vector& role_path, bool validate) + { + // Perform application code functions here + // resource - device model object about to be deleted + // role_path - role path of device object about to be deleted + // validate - true when only checks are performed, false when checks and deletion are performed + return true; + }; +} + +// IS-14 Device Configuration callback +// This function is called when an object is to be created. +// The returned object is then added to the Device Model +// This example shows the creation of a receiver monitor resource +// In the Device Model the receivers block that contains the monitors must be rebuildable +nmos::create_device_model_object_handler make_create_device_model_object_handler(slog::base_gate& gate) +{ + return[&gate](const nmos::nc_class_id& class_id, nmos::nc_oid oid, bool constant_oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const web::json::value& touchpoints, bool validate, const std::map& property_values) + { + if (touchpoints.size() != 1) + { + slog::log(gate, SLOG_FLF) << "Either zero or more than one touchpoint found (ambiguous) when attempting to create " << role; + return nmos::control_protocol_resource(); // return empty resource on error + } + const auto& touchpoint_uuid = nmos::fields::nc::id(nmos::fields::nc::resource(*touchpoints.as_array().begin())); + + // In the case of validate = true, the object created will not be added to the device model, but it's values will be checked against the backup dataset + return nmos::make_receiver_monitor(oid, true, owner, role, user_label, U(""), web::json::value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, touchpoint_uuid.as_string()})} })); + }; +} + namespace impl { nmos::interlace_mode get_interlace_mode(const nmos::settings& settings) @@ -2116,6 +2208,11 @@ nmos::experimental::node_implementation make_node_implementation(nmos::node_mode .on_validate_channelmapping_output_map(make_node_implementation_map_validator()) // may be omitted if not required .on_channelmapping_activated(make_node_implementation_channelmapping_activation_handler(gate)) .on_control_protocol_property_changed(make_node_implementation_control_protocol_property_changed_handler(gate)) // may be omitted if IS-12 not required + .on_create_validation_fingerprint(make_create_validation_fingerprint_handler()) + .on_validate_validation_fingerprint(make_validate_validation_fingerprint_handler()) + .on_get_read_only_modification_allow_list(make_get_read_only_modification_allow_list_handler(gate)) // may be omitted if either IS-14 not required, or IS-14 Rebuild functionality not required + .on_remove_device_model_object(make_remove_device_model_object_handler()) // may be omitted if either IS-14 not required, or IS-14 Rebuild functionality not required + .on_create_device_model_object(make_create_device_model_object_handler(gate)) // may be omitted if either IS-14 not required, or IS-14 Rebuild functionality not required .on_get_lost_packet_counters(make_node_implementation_get_lost_packet_counters_handler()) // may be omitted if IS-12/BCP-008-1 not required .on_get_late_packet_counters(make_node_implementation_get_late_packet_counters_handler()) // may be omitted if IS-12/BCP-008-1 not required .on_reset_monitor(make_node_implementation_reset_monitor_handler()); // may be omitted if IS-12/BCP-008-1 not required diff --git a/Development/nmos/api_utils.h b/Development/nmos/api_utils.h index 0f8b132a3..f6ef29e62 100644 --- a/Development/nmos/api_utils.h +++ b/Development/nmos/api_utils.h @@ -57,6 +57,8 @@ namespace nmos const route_pattern channelmapping_api = make_route_pattern(U("api"), U("channelmapping")); // IS-09 System API (originally specified in JT-NM TR-1001-1:2018 Annex A) const route_pattern system_api = make_route_pattern(U("api"), U("system")); + // IS-14 Configuration API + const route_pattern configuration_api = make_route_pattern(U("api"), U("configuration")); // API version pattern const route_pattern version = make_route_pattern(U("version"), U("v[0-9]+\\.[0-9]+")); @@ -87,6 +89,11 @@ namespace nmos const route_pattern outputSubroute = make_route_pattern(U("outputSubroute"), U("properties|sourceid|channels|caps")); const route_pattern activationId = make_route_pattern(U("activationId"), U("[a-zA-Z0-9\\-_]+")); + // Configuration API + const route_pattern rolePath = make_route_pattern(U("rolePath"), U("root|root\\.[a-zA-Z0-9\\-_\\.]+")); + const route_pattern propertyId = make_route_pattern(U("propertyId"), U("[0-9]+p[0-9]+")); + const route_pattern methodId = make_route_pattern(U("methodId"), U("[0-9]+m[0-9]+")); + // Common patterns const route_pattern resourceId = make_route_pattern(U("resourceId"), U("[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}")); } diff --git a/Development/nmos/configuration_api.cpp b/Development/nmos/configuration_api.cpp new file mode 100644 index 000000000..90f30635a --- /dev/null +++ b/Development/nmos/configuration_api.cpp @@ -0,0 +1,804 @@ +#include "nmos/configuration_api.h" + +#include +#include +#include "cpprest/json_validator.h" +#include "nmos/api_utils.h" +#include "nmos/configuration_methods.h" +#include "nmos/control_protocol_handlers.h" +#include "nmos/control_protocol_methods.h" +#include "nmos/control_protocol_resource.h" +#include "nmos/control_protocol_state.h" +#include "nmos/control_protocol_typedefs.h" +#include "nmos/control_protocol_utils.h" +#include "nmos/is14_versions.h" +#include "nmos/json_schema.h" +#include "nmos/log_manip.h" +#include "nmos/model.h" + +namespace nmos +{ + inline web::http::experimental::listener::api_router make_unmounted_configuration_api(node_model& model, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, create_validation_fingerprint_handler create_validation_fingerprint, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + + web::http::experimental::listener::api_router make_configuration_api(node_model& model, web::http::experimental::listener::route_handler validate_authorization, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, create_validation_fingerprint_handler create_validation_fingerprint, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + { + using namespace web::http::experimental::listener::api_router_using_declarations; + + api_router configuration_api; + + configuration_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("x-nmos/") }, req, res)); + return pplx::task_from_result(true); + }); + + configuration_api.support(U("/x-nmos/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("configuration/") }, req, res)); + return pplx::task_from_result(true); + }); + + if (validate_authorization) + { + configuration_api.support(U("/x-nmos/") + nmos::patterns::configuration_api.pattern + U("/?"), validate_authorization); + configuration_api.support(U("/x-nmos/") + nmos::patterns::configuration_api.pattern + U("/.*"), validate_authorization); + } + + const auto versions = with_read_lock(model.mutex, [&model] { return nmos::is14_versions::from_settings(model.settings); }); + configuration_api.support(U("/x-nmos/") + nmos::patterns::configuration_api.pattern + U("/?"), methods::GET, [versions](http_request req, http_response res, const string_t&, const route_parameters&) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body(nmos::make_api_version_sub_routes(versions), req, res)); + return pplx::task_from_result(true); + }); + + configuration_api.mount(U("/x-nmos/") + nmos::patterns::configuration_api.pattern + U("/") + nmos::patterns::version.pattern, make_unmounted_configuration_api(model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor, create_validation_fingerprint, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object, property_changed, gate)); + + return configuration_api; + } + + namespace details + { + void build_role_paths(const resources& resources, const nmos::resource& resource, const utility::string_t& base_role_path, std::set& role_paths) + { + if (resource.data.has_field(nmos::fields::nc::members)) + { + const auto& members = nmos::fields::nc::members(resource.data); + + for (const auto& member : members) + { + const auto role_path = base_role_path + U(".") + nmos::fields::nc::role(member); + role_paths.insert(role_path + U("/")); + + // get members on all NcBlock(s) + if (nmos::nc::is_block(nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(member)))) + { + // get resource based on the oid + const auto& oid = nmos::fields::nc::oid(member); + const auto& found = nmos::find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + build_role_paths(resources, *found, role_path, role_paths); + } + } + } + } + } + + nc_property_id parse_formatted_property_id(const utility::string_t& property_id) + { + // Assume that property_id is in form "p" as validated by the propertyId regular expression pattern + const utility::string_t::size_type delimiter = property_id.find('p'); + auto level = property_id.substr(0, delimiter); + auto index = property_id.substr(delimiter + 1); + return { uint16_t(web::json::value::parse(level).as_integer()), uint16_t(web::json::value::parse(index).as_integer()) }; + } + + // format nc_property_id to the form of "p" + utility::string_t make_formatted_property_id(const web::json::value& property_descriptor) + { + auto property_id = nmos::fields::nc::id(property_descriptor); + utility::ostringstream_t os; + os << nmos::fields::nc::level(property_id) << 'p' << nmos::fields::nc::index(property_id); + return os.str(); + } + + nc_method_id parse_formatted_method_id(const utility::string_t& method_id) + { + // Assume that method_id is in form "m" as validated by the methodId regular expression pattern + const utility::string_t::size_type delimiter = method_id.find('m'); + auto level = method_id.substr(0, delimiter); + auto index = method_id.substr(delimiter + 1); + return { uint16_t(web::json::value::parse(level).as_integer()), uint16_t(web::json::value::parse(index).as_integer()) }; + } + + // format nc_method_id to the form of "m" + utility::string_t make_formatted_method_id(const web::json::value& method_descriptor) + { + auto method_id = nmos::fields::nc::id(method_descriptor); + utility::ostringstream_t os; + os << nmos::fields::nc::level(method_id) << 'm' << nmos::fields::nc::index(method_id); + return os.str(); + } + + static const web::json::experimental::json_validator& configurationapi_validator() + { + // hmm, could be based on supported API versions from settings, like other APIs' validators? + static const web::json::experimental::json_validator validator + { + nmos::experimental::load_json_schema, + boost::copy_range>(boost::range::join(boost::range::join(boost::range::join( + is14_versions::all | boost::adaptors::transformed(experimental::make_configurationapi_method_patch_request_schema_uri), + is14_versions::all | boost::adaptors::transformed(experimental::make_configurationapi_property_value_put_request_schema_uri)), + is14_versions::all | boost::adaptors::transformed(experimental::make_configurationapi_bulkProperties_patch_request_schema_uri)), + is14_versions::all | boost::adaptors::transformed(experimental::make_configurationapi_bulkProperties_put_request_schema_uri))) + }; + return validator; + } + + bool parse_recurse_query_parameter(const utility::string_t& query) + { + web::json::value arguments = web::json::value_from_query(query); + + if (arguments.has_field(fields::nc::recurse)) + { + return U("false") != arguments.at(fields::nc::recurse).as_string(); + } + + return true; + } + + bool parse_include_descriptors_query_parameter(const utility::string_t& query) + { + web::json::value arguments = web::json::value_from_query(query); + + if (arguments.has_field(fields::nc::include_descriptors)) + { + return U("false") != arguments.at(fields::nc::include_descriptors).as_string(); + } + + return true; + } + } + + inline web::http::experimental::listener::api_router make_unmounted_configuration_api(node_model& model, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, create_validation_fingerprint_handler create_validation_fingerprint, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object, control_protocol_property_changed_handler property_changed, slog::base_gate& gate_) + { + using namespace web::http::experimental::listener::api_router_using_declarations; + + api_router configuration_api; + + // check for supported API version + const auto versions = with_read_lock(model.mutex, [&model] { return nmos::is14_versions::from_settings(model.settings); }); + configuration_api.support(U(".*"), details::make_api_version_handler(versions, gate_)); + + configuration_api.support(U("/?"), methods::GET, [](http_request req, http_response res, const string_t&, const route_parameters&) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("rolePaths/") }, req, res)); + return pplx::task_from_result(true); + }); + + // GET /rolePaths + configuration_api.support(U("/rolePaths/?"), methods::GET, [&model](http_request req, http_response res, const string_t&, const route_parameters&) + { + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + std::set role_paths; + + // start at the root block resource + auto resource = nmos::find_resource(resources, utility::s2us(std::to_string(nmos::root_block_oid))); + if (resources.end() != resource) + { + // add root to role_paths + const auto role_path = nmos::fields::nc::role(resource->data); + role_paths.insert(role_path + U("/")); + + // add rest to the role_paths + details::build_role_paths(resources, *resource, role_path, role_paths); + } + + set_reply(res, status_codes::OK, nmos::make_sub_routes_body(role_paths, req, res)); + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath} + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/?"), methods::GET, [&model, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + + if (resources.end() != resource) + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("bulkProperties/"), U("descriptor/"), U("methods/"), U("properties/") }, req, res)); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/properties + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/properties/?"), methods::GET, [&model, get_control_protocol_class_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + std::set properties_routes; + + auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)); + while (!class_id.empty()) + { + const auto& control_class = get_control_protocol_class_descriptor(class_id); + auto& property_descriptors = control_class.property_descriptors.as_array(); + + auto properties_route = boost::copy_range>(property_descriptors | boost::adaptors::transformed([](const web::json::value& property_descriptor) + { + return details::make_formatted_property_id(property_descriptor) + U("/"); + })); + + properties_routes.insert(properties_route.begin(), properties_route.end()); + + class_id.pop_back(); + } + + set_reply(res, status_codes::OK, nmos::make_sub_routes_body(properties_routes, req, res)); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/methods + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/methods/?"), methods::GET, [&model, get_control_protocol_class_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + std::set methods_routes; + + auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)); + while (!class_id.empty()) + { + const auto& control_class = get_control_protocol_class_descriptor(class_id); + auto& method_descriptors = control_class.method_descriptors; + + auto methods_route = boost::copy_range>(method_descriptors | boost::adaptors::transformed([](const nmos::experimental::method& method) + { + auto make_method_id = [](const nmos::experimental::method& method) + { + // method tuple definition described in control_protocol_handlers.h + auto& nc_method_descriptor = std::get<0>(method); + return details::make_formatted_method_id(nc_method_descriptor); + }; + + return make_method_id(method) + U("/"); + })); + + methods_routes.insert(methods_route.begin(), methods_route.end()); + + class_id.pop_back(); + } + + set_reply(res, status_codes::OK, nmos::make_sub_routes_body(methods_routes, req, res)); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/descriptor + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/descriptor/?"), methods::GET, [&model, get_control_protocol_class_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + nc_class_id class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)); + + if (!class_id.empty()) + { + // Hmmm, this feels like it should be a utility function, or we just parameterize the handler to include inherited + const auto& control_class = get_control_protocol_class_descriptor(class_id); + + auto& description = control_class.description; + auto& name = control_class.name; + auto& fixed_role = control_class.fixed_role; + auto property_descriptors = control_class.property_descriptors; + auto method_descriptors = value::array(); + for (const auto& method_descriptor : control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } + auto event_descriptors = control_class.event_descriptors; + + auto inherited_class_id = class_id; + inherited_class_id.pop_back(); + + while (!inherited_class_id.empty()) + { + const auto& inherited_control_class = get_control_protocol_class_descriptor(inherited_class_id); + { + for (const auto& property_descriptor : inherited_control_class.property_descriptors.as_array()) { web::json::push_back(property_descriptors, property_descriptor); } + for (const auto& method_descriptor : inherited_control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } + for (const auto& event_descriptor : inherited_control_class.event_descriptors.as_array()) { web::json::push_back(event_descriptors, event_descriptor); } + } + inherited_class_id.pop_back(); + } + + auto class_descriptor = fixed_role.is_null() + ? nc::details::make_class_descriptor(description, class_id, name, property_descriptors, method_descriptors, event_descriptors) + : nc::details::make_class_descriptor(description, class_id, name, fixed_role.as_string(), property_descriptors, method_descriptors, event_descriptors); + + auto method_result = nc::details::make_method_result({ nmos::nc_method_status::ok }, class_descriptor); + set_reply(res, status_codes::OK, method_result); + } + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/properties/{propertyId} + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/properties/") + nmos::patterns::propertyId.pattern + U("/?"), methods::GET, [&model, get_control_protocol_class_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto property_id = parameters.at(nmos::patterns::propertyId.name); + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + // find the relevant nc_property_descriptor + const auto& property_descriptor = nc::find_property_descriptor(details::parse_formatted_property_id(property_id), nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)), get_control_protocol_class_descriptor); + if (property_descriptor.is_null()) + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::property_not_implemented }, U("Not Found; ") + property_id); + set_reply(res, status_codes::NotFound, method_result); + } + else + { + set_reply(res, status_codes::OK, nmos::make_sub_routes_body({ U("descriptor/"), U("value/") }, req, res)); + } + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/properties/{propertyId}/descriptor + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/properties/") + nmos::patterns::propertyId.pattern + U("/descriptor/?"), methods::GET, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto property_id = parameters.at(nmos::patterns::propertyId.name); + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + // find the relevant nc_property_descriptor + const auto& property_descriptor = nc::find_property_descriptor(details::parse_formatted_property_id(property_id), nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)), get_control_protocol_class_descriptor); + const auto& property_type = nmos::fields::nc::type_name(property_descriptor); + auto datatype_descriptor = nc::details::get_datatype_descriptor(value::string(property_type), get_control_protocol_datatype_descriptor); + + if (nmos::nc_datatype_type::Struct == nmos::fields::nc::type(datatype_descriptor)) + { + auto inherited_struct = datatype_descriptor; + + while (!nmos::fields::nc::parent_type(inherited_struct).is_null()) + { + auto parent_type = nmos::fields::nc::parent_type(datatype_descriptor).as_string(); + + inherited_struct = nc::details::get_datatype_descriptor(value::string(parent_type), get_control_protocol_datatype_descriptor); + + for (const auto& field : nmos::fields::nc::fields(inherited_struct)) + { + web::json::push_back(datatype_descriptor[nmos::fields::nc::fields], field); + } + } + } + + if (property_descriptor.is_null()) + { + // property not found + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::property_not_implemented }, U("Not Found; ") + property_id); + set_reply(res, status_codes::NotFound, method_result); + } + else + { + auto method_result = nc::details::make_method_result({ nmos::nc_method_status::ok }, datatype_descriptor); + set_reply(res, status_codes::OK, method_result); + } + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/properties/{propertyId}/value - invokes get method + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/properties/") + nmos::patterns::propertyId.pattern + U("/value/?"), methods::GET, [&model, get_control_protocol_class_descriptor, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto property_id = parameters.at(nmos::patterns::propertyId.name); + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + auto arguments = value_of({ + { nmos::fields::nc::id, nc::details::make_property_id(details::parse_formatted_property_id(property_id))}, + }); + + auto result = nc::get(*resource, arguments, false, get_control_protocol_class_descriptor, gate_); + auto status = nmos::fields::nc::status(result); + auto code = (nc_method_status::ok == status || nc_method_status::property_deprecated == status) ? status_codes::OK : status_codes::InternalError; + set_reply(res, code, result); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // GET /rolePaths/{rolePath}/methods/{methodId} - invokes method specified by {methodId} + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/methods/") + nmos::patterns::methodId.pattern + U("/?"), methods::PATCH, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor, property_changed, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + nmos::api_gate gate(gate_, req, parameters); + return details::extract_json(req, gate).then([&model, req, res, parameters, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate](value body) mutable + { + auto lock = model.write_lock(); + + const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); + + // Validate JSON syntax according to the schema + details::configurationapi_validator().validate(body, experimental::make_configurationapi_method_patch_request_schema_uri(version)); + + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + const auto method_id = parameters.at(nmos::patterns::methodId.name); + + auto& resources = model.control_protocol_resources; + auto& arguments = nmos::fields::nc::arguments(body); + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + auto method = get_control_protocol_method_descriptor(nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)), details::parse_formatted_method_id(method_id)); + auto& nc_method_descriptor = method.first; + auto& control_method_handler = method.second; + web::http::status_code code{ status_codes::BadRequest }; + value method_result; + + if (control_method_handler) + { + try + { + // do method arguments constraints validation + nc::method_parameters_contraints_validation(arguments, nc_method_descriptor, get_control_protocol_datatype_descriptor); + + // execute the relevant control method handler, then accumulating up their response to responses + method_result = control_method_handler(resources, *resource, arguments, nmos::fields::nc::is_deprecated(nc_method_descriptor), gate); + + auto status = nmos::fields::nc::status(method_result); + if (nc_method_status::ok == status || nc_method_status::method_deprecated == status) { code = status_codes::OK; } + else if (status / 100 == 4) { code = status_codes::BadRequest; } // 4xx error + else if (status / 100 == 5) { code = status_codes::InternalError; } // 5xx error + else { code = static_cast(status); } + } + catch (const nmos::control_protocol_exception& e) + { + // invalid arguments + utility::stringstream_t ss; + ss << U("invalid argument: ") << arguments.serialize() << " error: " << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + } + else + { + // unknown methodId + utility::stringstream_t ss; + ss << U("unsupported method_id: ") << method_id + << U(" for control class class_id: ") << resource->data.at(nmos::fields::nc::class_id).serialize(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::method_not_implemented }, ss.str()); + + code = status_codes::NotFound; + } + set_reply(res, code, method_result); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return true; + }); + }); + + // PUT /rolePaths/{rolePath}/properties/{propertyId}/value - invokes set method + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/properties/") + nmos::patterns::propertyId.pattern + U("/value/?"), methods::PUT, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + nmos::api_gate gate(gate_, req, parameters); + return details::extract_json(req, gate).then([&model, req, res, parameters, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate](value body) mutable + { + auto lock = model.write_lock(); + + const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); + + // Validate JSON syntax according to the schema + details::configurationapi_validator().validate(body, experimental::make_configurationapi_property_value_put_request_schema_uri(version)); + + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + const auto property_id = parameters.at(nmos::patterns::propertyId.name); + + auto& resources = model.control_protocol_resources; + + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + // find the relevant nc_property_descriptor + const auto& property_descriptor = nc::find_property_descriptor(details::parse_formatted_property_id(property_id), nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)), get_control_protocol_class_descriptor); + if (property_descriptor.is_null()) + { + // property not found + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + property_id); + set_reply(res, status_codes::NotFound, method_result); + } + else + { + auto arguments = value_of({ + { nmos::fields::nc::id, nc::details::make_property_id(details::parse_formatted_property_id(property_id))}, + { nmos::fields::nc::value, nmos::fields::nc::value(body)} + }); + + auto result = nc::set(resources, *resource, arguments, false, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + + auto status = nmos::fields::nc::status(result); + auto code = (nc_method_status::ok == status || nc_method_status::property_deprecated == status) ? status_codes::OK : status_codes::InternalError; + set_reply(res, code, result); + model.notify(); + } + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return true; + }); + }); + + // GET /rolePaths/{rolePath}/bulkProperties - invokes get_properties_by_path method + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/bulkProperties/?"), methods::GET, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + + if (resources.end() != resource) + { + web::http::status_code code{ status_codes::BadRequest }; + value method_result; + + try + { + bool recurse = details::parse_recurse_query_parameter(req.request_uri().query()); + bool include_descriptors = details::parse_include_descriptors_query_parameter(req.request_uri().query()); + + method_result = get_properties_by_path(resources, *resource, recurse, include_descriptors, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint); + + auto status = nmos::fields::nc::status(method_result); + if (nc_method_status::ok == status || nc_method_status::method_deprecated == status) { code = status_codes::OK; } + else if (status / 100 == 4) { code = status_codes::BadRequest; } // 4xx error + else if (status / 100 == 5) { code = status_codes::InternalError; } // 5xx error + else { code = static_cast(status); } + } + catch (const nmos::control_protocol_exception& e) + { + // invalid arguments + utility::stringstream_t ss; + ss << U("parameter error: ") << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + set_reply(res, code, method_result); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return pplx::task_from_result(true); + }); + + // PATCH /rolePaths/{rolePath}/bulkProperties - invokes validation_set_properties_by_path method + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/bulkProperties/?"), methods::PATCH, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, validate_validation_fingerprint, remove_device_model_object, create_device_model_object, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); + + return details::extract_json(req, gate_).then([res, &model, role_path, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, validate_validation_fingerprint, remove_device_model_object, create_device_model_object, version, &gate_](value body) mutable + { + auto lock = model.read_lock(); + auto& resources = model.control_protocol_resources; + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + web::http::status_code code{ status_codes::BadRequest }; + value method_result; + + try + { + // Validate JSON syntax according to the schema + details::configurationapi_validator().validate(body, experimental::make_configurationapi_bulkProperties_patch_request_schema_uri(version)); + + const auto& arguments = nmos::fields::nc::arguments(body); + bool recurse = nmos::fields::nc::recurse(arguments); + const auto& restore_mode = nmos::fields::nc::restore_mode(arguments); + const auto& backup_data_set = nmos::fields::nc::data_set(arguments); + + method_result = validate_set_properties_by_path(resources, *resource, backup_data_set, recurse, static_cast(restore_mode), get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + auto status = nmos::fields::nc::status(method_result); + if (nc_method_status::ok == status || nc_method_status::method_deprecated == status) { code = status_codes::OK; } + else if (status / 100 == 4) { code = status_codes::BadRequest; } // 4xx error + else if (status / 100 == 5) { code = status_codes::InternalError; } // 5xx error + else { code = static_cast(status); } + } + catch (const nmos::control_protocol_exception& e) + { + // invalid arguments + utility::stringstream_t ss; + ss << U("parameter error: ") << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + catch (const web::json::json_exception& e) + { + // JSON validation error + utility::stringstream_t ss; + ss << U("JSON validation error: ") << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + set_reply(res, code, method_result); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + return true; + }); + }); + + // PUT /rolePaths/{rolePath}/bulkProperties - invokes set_properties_by_path method + configuration_api.support(U("/rolePaths/") + nmos::patterns::rolePath.pattern + U("/bulkProperties/?"), methods::PUT, [&model, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object, &gate_](http_request req, http_response res, const string_t&, const route_parameters& parameters) + { + const auto role_path = parameters.at(nmos::patterns::rolePath.name); + const nmos::api_version version = nmos::parse_api_version(parameters.at(nmos::patterns::version.name)); + + return details::extract_json(req, gate_).then([res, &model, role_path, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object, version, &gate_](value body) mutable + { + auto lock = model.write_lock(); + auto& resources = model.control_protocol_resources; + const auto& resource = nc::find_resource_by_role_path(resources, role_path); + if (resources.end() != resource) + { + web::http::status_code code{ status_codes::BadRequest }; + value method_result; + + try + { + // Validate JSON syntax according to the schema + details::configurationapi_validator().validate(body, experimental::make_configurationapi_bulkProperties_put_request_schema_uri(version)); + + const auto& arguments = nmos::fields::nc::arguments(body); + bool recurse = nmos::fields::nc::recurse(arguments); + const auto& restore_mode = nmos::fields::nc::restore_mode(arguments); + const auto& backup_data_set = nmos::fields::nc::data_set(arguments); + + method_result = set_properties_by_path(resources, *resource, backup_data_set, recurse, static_cast(restore_mode), get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + code = status_codes::OK; + + model.notify(); + } + catch (const nmos::control_protocol_exception& e) + { + // invalid arguments + utility::stringstream_t ss; + ss << U("parameter error: ") << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + catch (const web::json::json_exception& e) + { + // JSON validation error + utility::stringstream_t ss; + ss << U("JSON validation error: ") << e.what(); + method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + + code = status_codes::BadRequest; + } + set_reply(res, code, method_result); + } + else + { + // resource not found for the role path + auto method_result = nc::details::make_method_result_error({ nmos::nc_method_status::bad_oid }, U("Not Found; ") + role_path); + set_reply(res, status_codes::NotFound, method_result); + } + + return true; + }); + }); + + return configuration_api; + } +} diff --git a/Development/nmos/configuration_api.h b/Development/nmos/configuration_api.h new file mode 100644 index 000000000..c11b16082 --- /dev/null +++ b/Development/nmos/configuration_api.h @@ -0,0 +1,22 @@ +#ifndef NMOS_CONFIGURATION_API_H +#define NMOS_CONFIGURATION_API_H + +#include "cpprest/api_router.h" +#include "nmos/control_protocol_handlers.h" +#include "nmos/configuration_handlers.h" + +namespace slog +{ + class base_gate; +} + +// Configuration API implementation +// See https://specs.amwa.tv/is-device-configuration/branches/publish-CR/docs/API_requests.html +namespace nmos +{ + struct node_model; + + web::http::experimental::listener::api_router make_configuration_api(nmos::node_model& model, web::http::experimental::listener::route_handler validate_authorization, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, create_validation_fingerprint_handler create_validation_fingerprint, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); +} + +#endif diff --git a/Development/nmos/configuration_handlers.h b/Development/nmos/configuration_handlers.h new file mode 100644 index 000000000..186347387 --- /dev/null +++ b/Development/nmos/configuration_handlers.h @@ -0,0 +1,41 @@ +#ifndef NMOS_CONFIGURATION_HANDLERS_H +#define NMOS_CONFIGURATION_HANDLERS_H + +#include +#include "nmos/control_protocol_handlers.h" +#include "nmos/resources.h" +#include "nmos/control_protocol_resource.h" + +namespace slog +{ + class base_gate; +} + +namespace nmos +{ + namespace experimental + { + struct control_protocol_state; + } + // This callback is invoked when getting a backup dataset to generate a validation fingerprint + // This function should generate a fingerprint that can be used for subsequent validation + typedef std::function create_validation_fingerprint_handler; + + // This callback is invoked when validating or restoring a backup dataset + // This function should validate the validation fingerprint + typedef std::function validate_validation_fingerprint_handler; + + // This callback is invoked if attempting to modify read only properties when restoring a configuration. + // This function return a vector of property ids of the read only properties allowed to be modified + typedef std::function(const nmos::resources& resources, const nmos::resource& resource, const std::vector& role_path, const std::vector& property_ids)> get_read_only_modification_allow_list_handler; + + // This callback is invoked if attempting to remove a device model object when restoring a configuration. + // This function calls back before an object is removed from the device model. + typedef std::function& role_path, bool validate)> remove_device_model_object_handler; + + // This callback is invoked if attempting to add a device model object to a rebuildable block when restoring a configuration. + // This function should return the newly created device model object. + typedef std::function& property_values)> create_device_model_object_handler; +} + +#endif diff --git a/Development/nmos/configuration_methods.cpp b/Development/nmos/configuration_methods.cpp new file mode 100644 index 000000000..5d795d369 --- /dev/null +++ b/Development/nmos/configuration_methods.cpp @@ -0,0 +1,138 @@ +#include "nmos/configuration_methods.h" + +#include +#include "cpprest/json_utils.h" +#include "nmos/configuration_handlers.h" +#include "nmos/configuration_utils.h" +#include "nmos/control_protocol_resource.h" +#include "nmos/control_protocol_resources.h" +#include "nmos/control_protocol_state.h" +#include "nmos/control_protocol_utils.h" + +namespace nmos +{ + namespace details + { + web::json::array make_property_holders(const nmos::resource& resource, bool include_descriptors, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + using web::json::value; + + value property_holders = value::array(); + + nmos::nc_class_id class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource.data)); + + // make NcPropertyHolder objects + while (!class_id.empty()) + { + const auto& control_class_descriptor = get_control_protocol_class_descriptor(class_id); + + for (const auto& property_descriptor : control_class_descriptor.property_descriptors.as_array()) + { + const auto descriptor = include_descriptors ? property_descriptor : value::null(); + value property_holder = nmos::nc::details::make_property_holder(nmos::nc::details::parse_property_id(nmos::fields::nc::id(property_descriptor)), descriptor, resource.data.at(nmos::fields::nc::name(property_descriptor))); + + web::json::push_back(property_holders, property_holder); + } + class_id.pop_back(); + } + return property_holders.as_array(); + } + + void populate_object_property_holder(const nmos::resources& resources, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, const nmos::resource& resource, bool recurse, bool include_descriptors, web::json::value& object_properties_holders) + { + using web::json::value; + + // Get property_holders for this resource + const auto& property_holders = make_property_holders(resource, include_descriptors, get_control_protocol_class_descriptor); + + const auto role_path = get_role_path(resources, resource); + + // when include_descriptors = false, don't include the Class Manager + if (!include_descriptors && role_path.size() > 1 && role_path.at(0).as_string() == U("root") && role_path.at(1).as_string() == U("ClassManager")) + { + return; + } + const auto& dependency_paths = nmos::fields::nc::dependency_paths(resource.data); + const auto& allowed_member_classes = nmos::fields::nc::allowed_members_classes(resource.data); + + auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path, property_holders, dependency_paths, allowed_member_classes, nmos::fields::nc::is_rebuildable(resource.data)); + + web::json::push_back(object_properties_holders, object_properties_holder); + + // Recurse into members...if we want to...and the object has them + if (recurse && nmos::nc::is_block(nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(resource.data)))) + { + if (resource.data.has_field(nmos::fields::nc::members)) + { + const auto& members = nmos::fields::nc::members(resource.data); + + for (const auto& member : members) + { + const auto& found = find_resource(resources, utility::s2us(std::to_string(nmos::fields::nc::oid(member)))); + + if (resources.end() != found) + { + populate_object_property_holder(resources, get_control_protocol_class_descriptor, *found, recurse, include_descriptors, object_properties_holders); + } + } + } + } + } + } + + web::json::value get_properties_by_path(const nmos::resources& resources, const nmos::resource& resource, bool recurse, bool include_descriptors, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::create_validation_fingerprint_handler create_validation_fingerprint) + { + using web::json::value; + + value object_properties_holders = value::array(); + + details::populate_object_property_holder(resources, get_control_protocol_class_descriptor, resource, recurse, include_descriptors, object_properties_holders); + + utility::string_t validation_fingerprint = U(""); + + if (create_validation_fingerprint) + { + validation_fingerprint = create_validation_fingerprint(resources, resource); + } + + auto bulk_properties_holder = nmos::nc::details::make_bulk_properties_holder(validation_fingerprint, object_properties_holders); + + return nmos::nc::details::make_method_result({ nmos::nc_method_status::ok }, bulk_properties_holder); + } + + web::json::value validate_set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::validate_validation_fingerprint_handler validate_validation_fingerprint, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object) + { + if (validate_validation_fingerprint) + { + const auto& validation_fingerprint = nmos::fields::nc::validation_fingerprint(backup_data_set); + + if (!validate_validation_fingerprint(resources, resource, validation_fingerprint.c_str())) + { + return nmos::nc::details::make_method_result_error({ nmos::nc_method_status::invalid_request }, U("Invalid validation fingerprint")); + } + } + const auto& object_properties_holders = nmos::fields::nc::values(backup_data_set); + + const auto object_properties_set_validation = apply_backup_data_set(resources, resource, object_properties_holders, recurse, restore_mode, true, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + return nmos::nc::details::make_method_result({ nmos::nc_method_status::ok }, object_properties_set_validation); + } + + web::json::value set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::validate_validation_fingerprint_handler validate_validation_fingerprint, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object) + { + if (validate_validation_fingerprint) + { + const auto& validation_fingerprint = nmos::fields::nc::validation_fingerprint(backup_data_set); + + if (!validate_validation_fingerprint(resources, resource, validation_fingerprint.c_str())) + { + return nmos::nc::details::make_method_result_error({ nmos::nc_method_status::invalid_request }, U("Invalid validation fingerprint")); + } + } + const auto& object_properties_holders = nmos::fields::nc::values(backup_data_set); + + const auto object_properties_set_validation = apply_backup_data_set(resources, resource, object_properties_holders, recurse, restore_mode, false, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + return nmos::nc::details::make_method_result({ nmos::nc_method_status::ok }, object_properties_set_validation); + } +} \ No newline at end of file diff --git a/Development/nmos/configuration_methods.h b/Development/nmos/configuration_methods.h new file mode 100644 index 000000000..46df83cda --- /dev/null +++ b/Development/nmos/configuration_methods.h @@ -0,0 +1,25 @@ +#ifndef NMOS_CONFIGURATION_METHODS_H +#define NMOS_CONFIGURATION_METHODS_H + +#include "nmos/configuration_handlers.h" +#include "nmos/control_protocol_handlers.h" +#include "nmos/resources.h" + +namespace slog +{ + class base_gate; +} + +namespace nmos +{ + struct control_protocol_resource; + + // Implementation of IS-14 function for creating backup dataset from a Device Model + web::json::value get_properties_by_path(const nmos::resources& resources, const nmos::resource& resource, bool recurse, bool include_descriptors, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::create_validation_fingerprint_handler create_validation_fingerprint); + + web::json::value validate_set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::validate_validation_fingerprint_handler validate_validation_fingerprint, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object); + + web::json::value set_properties_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& backup_data_set, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::validate_validation_fingerprint_handler validate_validation_fingerprint, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object); +} + +#endif diff --git a/Development/nmos/configuration_resources.cpp b/Development/nmos/configuration_resources.cpp new file mode 100644 index 000000000..4e24a7f55 --- /dev/null +++ b/Development/nmos/configuration_resources.cpp @@ -0,0 +1,28 @@ +#include "nmos/configuration_resources.h" + +#include "cpprest/json_utils.h" +#include "nmos/control_protocol_resource.h" +#include "nmos/slog.h" + +namespace nmos +{ + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices, const utility::string_t& status_message) + { + return nc::details::make_object_properties_set_validation(role_path, status, notices, web::json::value::string(status_message)); + } + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices) + { + return nc::details::make_object_properties_set_validation(role_path, status, notices, web::json::value::null()); + } + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status) + { + return nc::details::make_object_properties_set_validation(role_path, status, web::json::value::array().as_array(), web::json::value::null()); + } + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const utility::string_t& status_message) + { + return nc::details::make_object_properties_set_validation(role_path, status, web::json::value::array().as_array(), web::json::value::string(status_message)); + } +} diff --git a/Development/nmos/configuration_resources.h b/Development/nmos/configuration_resources.h new file mode 100644 index 000000000..c4569233d --- /dev/null +++ b/Development/nmos/configuration_resources.h @@ -0,0 +1,18 @@ +#ifndef NMOS_CONFIGURATION_RESOURCES_H +#define NMOS_CONFIGURATION_RESOURCES_H + +#include "nmos/control_protocol_typedefs.h" +#include "nmos/resources.h" + +namespace nmos +{ + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices, const utility::string_t& status_message); + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const web::json::array& notices); + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status); + + web::json::value make_object_properties_set_validation(const web::json::array& role_path, const nmos::nc_restore_validation_status::status status, const utility::string_t& status_message); +} + +#endif diff --git a/Development/nmos/configuration_utils.cpp b/Development/nmos/configuration_utils.cpp new file mode 100644 index 000000000..849befb3a --- /dev/null +++ b/Development/nmos/configuration_utils.cpp @@ -0,0 +1,788 @@ +#include "nmos/configuration_methods.h" + +#include +#include "cpprest/json_utils.h" +#include "nmos/configuration_handlers.h" +#include "nmos/configuration_resources.h" +#include "nmos/configuration_utils.h" +#include "nmos/control_protocol_resource.h" +#include "nmos/control_protocol_resources.h" +#include "nmos/control_protocol_state.h" +#include "nmos/control_protocol_utils.h" +#include "nmos/slog.h" + +namespace nmos +{ + namespace details + { + bool is_property_value_valid(web::json::value& property_restore_notices, const web::json::value& property_value, const web::json::value& property_descriptor, nmos::nc_restore_mode::restore_mode restore_mode, bool is_rebuildable) + { + const nmos::nc_property_id& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_descriptor)); + bool is_valid = true; + // Only allow modification of read only properties when in Rebuild mode + if (bool(nmos::fields::nc::is_read_only(property_descriptor)) + && restore_mode != nmos::nc_restore_mode::restore_mode::rebuild) + { + const auto& property_restore_notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::error, U("read only properties can not be modified in Modify restore mode.")); + web::json::push_back(property_restore_notices, property_restore_notice); + is_valid = false; + } + // Only allow modification of read only properties when object is rebuildable + if (bool(nmos::fields::nc::is_read_only(property_descriptor)) + && !is_rebuildable) + { + const auto& property_restore_notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::error, U("object must be rebuildable to allow modification of read only properties.")); + web::json::push_back(property_restore_notices, property_restore_notice); + is_valid = false; + } + + return is_valid; + } + + bool is_contains_read_only_property(const web::json::array& property_values, const nmos::nc_class_id& class_id, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + for (const auto& property_value : property_values) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + const auto& property_descriptor = nmos::nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); + + if (bool(nmos::fields::nc::is_read_only(property_descriptor))) + { + return true; + } + } + return false; + } + + web::json::value modify_device_model_object(nmos::resources& resources, const nmos::resource& resource, const web::json::array& target_role_path, const web::json::value& target_object_properties_holder, nmos::nc_restore_mode::restore_mode restore_mode, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list) + { + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(resource.data)); + + auto object_properties_set_validation_values = web::json::value::array(); + + auto property_restore_notices = web::json::value::array(); + // Validate property_values - filter out the incorrect, ignored or unallowed values + // notices are created for any properties that can't be modified according to restore mode + // and whether this object is rebuildable + const auto& filtered_property_values = boost::copy_range>(nmos::fields::nc::values(target_object_properties_holder) + | boost::adaptors::filtered([&property_restore_notices, &resource, class_id, get_control_protocol_class_descriptor, restore_mode](const web::json::value& property_value) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + const auto& property_descriptor = nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); + + return resource.data.at(nmos::fields::nc::name(property_descriptor)) != nmos::fields::nc::value(property_value) + && details::is_property_value_valid(property_restore_notices, property_value, property_descriptor, restore_mode, bool(nmos::fields::nc::is_rebuildable(resource.data))); + }) + ); + auto property_modify_list = web::json::value_from_elements(filtered_property_values).as_array(); + + if (nmos::nc_restore_mode::rebuild == restore_mode) + { + // Find any read only properties + const auto& read_only_property_values = boost::copy_range>(filtered_property_values + | boost::adaptors::filtered([class_id, get_control_protocol_class_descriptor](const web::json::value& property_value) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + const auto& property_descriptor = nmos::nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); + + return nmos::fields::nc::is_read_only(property_descriptor); + }) + ); + if (read_only_property_values.size() > 0) // Call back to user code + { + if (get_read_only_modification_allow_list) + { + // If the property_modify_list contains read only properties then we call back to the application code to + // check that it's OK to change those value. Bear in mind that these could be the class Id, or the oid or some other + // property that we don't want changed ordinarily + std::vector target_role_path_array; + for (const auto& element: target_role_path) + { + target_role_path_array.push_back(element.as_string()); + } + std::vector read_only_property_ids; + for (const auto& property_value: read_only_property_values) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + // Don't include structural properties - changing these could break the device model + if (property_id != nmos::nc_object_class_id_property_id && + property_id != nmos::nc_object_oid_property_id && + property_id != nmos::nc_object_constant_oid_property_id && + property_id != nmos::nc_object_owner_property_id && + property_id != nmos::nc_object_role_property_id) + { + read_only_property_ids.push_back(nc::details::parse_property_id(nmos::fields::nc::id(property_value))); + } + } + + const auto allow_list_read_only_property_ids = get_read_only_modification_allow_list(resources, resource, target_role_path_array, read_only_property_ids); + + const auto& allowed_property_values = boost::copy_range>(filtered_property_values + | boost::adaptors::filtered([&property_restore_notices, get_control_protocol_class_descriptor, class_id, allow_list_read_only_property_ids](const web::json::value& property_value) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + const auto& property_descriptor = nmos::nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); + // if it's read only and in the allow list then add it + if (!nmos::fields::nc::is_read_only(property_descriptor)) + { + return true; + } + + for (const auto& allowed_property_id: allow_list_read_only_property_ids) + { + if (nmos::fields::nc::id(property_value) == nc::details::make_property_id(allowed_property_id)) + { + return true; + } + } + // Create a warning notice for any read only property not allowed by the allow list + const auto& property_restore_notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::warning, U("This read only property can not be modified.")); + web::json::push_back(property_restore_notices, property_restore_notice); + + return false; + }) + ); + + property_modify_list = web::json::value_from_elements(allowed_property_values).as_array(); + } + else + { + // Modify of read only properties not supported + return nmos::make_object_properties_set_validation(target_role_path, nmos::nc_restore_validation_status::failed, property_restore_notices.as_array(), U("Modification of read only properties not supported")); + } + } + } + for (const auto& property_value : property_modify_list) + { + const auto& property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_value)); + const auto& property_descriptor = nmos::nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); + + // hmmm, ideally we would pass the value into modify_resource with the validate + // flag, so that it's subject to property contraints and also the application code can decide if it's a legal value + const auto& value = nmos::fields::nc::value(property_value); + try + { + nmos::nc::details::constraints_validation(value, nc::details::get_runtime_property_constraints(property_id, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property_descriptor), {nc::details::get_datatype_descriptor(property_descriptor.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor}); + + if (!validate) + { + // modify control protocol resources + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource_) + { + resource_.data[nmos::fields::nc::name(property_descriptor)] = value; + + }, nc::make_property_changed_event(nmos::fields::nc::oid(resource.data), {{property_id, nmos::nc_property_change_type::type::value_changed, value}})); + } + } + catch(const nmos::control_protocol_exception& e) + { + // Generate notice for this property + utility::stringstream_t ss; + ss << U("property error: ") << e.what(); + const auto& property_restore_notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::error, ss.str()); + web::json::push_back(property_restore_notices, property_restore_notice); + } + } + // If there are any error notices, then give an overall error status for object properties set validation + const auto& error_notices = boost::copy_range>(property_restore_notices.as_array() + | boost::adaptors::filtered([&](const web::json::value& notice) + { + return nmos::fields::nc::notice_type(notice) == nmos::nc_property_restore_notice_type::error; + }) + ); + const auto object_status = error_notices.size() ? nmos::nc_restore_validation_status::failed : nmos::nc_restore_validation_status::ok; + return nmos::make_object_properties_set_validation(target_role_path, object_status, property_restore_notices.as_array(), U("OK")); + } + + web::json::value modify_rebuildable_block(nmos::resources& resources, object_properties_map& object_properties_holder_map, const nmos::resource& resource, const web::json::array& target_role_path, const web::json::value& block_object_properties_holder, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object) + { + auto object_properties_set_validations = web::json::value::array(); + + // Find object_properties_holder for resource + // the calling function guarantees that this target role path is in the object_properties_holders + // and property_holder for block members exists + const auto& block_members_properties_holder = nmos::get_property_holder(block_object_properties_holder, nmos::nc_block_members_property_id); + + const auto& restore_members = nmos::fields::nc::value(block_members_properties_holder); + const auto& reference_members = nmos::fields::nc::members(resource.data); + + const auto& block_oid = nmos::fields::nc::oid(resource.data); + const auto& allowed_member_classes = nmos::fields::nc::allowed_members_classes(resource.data); + + std::vector members_to_remove; + std::vector members_to_add; + + // If there are any data problems they should be reported as warning/error notices + auto block_notices = web::json::value::array(); + + // Iterate through the members of the block and compare to the members in the backup dataset + for (const auto& reference_member : reference_members) + { + auto child_role_path = target_role_path; + web::json::push_back(child_role_path, nmos::fields::nc::role(reference_member)); + + const auto& filtered_members = boost::copy_range>(restore_members.as_array() + | boost::adaptors::filtered([&reference_member](const web::json::value& member) + { + return nmos::fields::nc::role(reference_member) == nmos::fields::nc::role(member); + }) + ); + if (filtered_members.size() != 1) + { + // can't find this role in restore dataset, so member has been removed + + // get the associated resource to remove + auto found = nmos::find_resource(resources, utility::conversions::details::to_string_t(nmos::fields::nc::oid(reference_member))); + + if (resources.end() != found) + { + // callback to user code + const auto child_role_path_array = boost::copy_range>(child_role_path | boost::adaptors::transformed([](const web::json::value& element) + { + return element.as_string(); + })); + if (!remove_device_model_object(*found, child_role_path_array, validate)) + { + // error in user code + web::json::push_back(block_notices, nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, U("Application error."))); + continue; + } + + if (!validate) // If validate is true then delete the object, just indicate whether it's possible given the data supplied + { + auto erase_count = nmos::nc::erase_resource(resources, found->id); + if (erase_count > 0) + { + members_to_remove.push_back(nmos::fields::nc::oid(reference_member)); + } + else + { + // unable to delete resource so report the error and don't update block + web::json::push_back(block_notices, nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, U("Unable to delete resource in Device Model."))); + } + } + } + else + { + // unable to delete resource so report the error and don't update block + web::json::push_back(block_notices, nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, U("Unable to find resource in Device Model."))); + } + } + } + + for (const auto& restore_member : restore_members.as_array()) + { + auto child_role_path = target_role_path; + web::json::push_back(child_role_path, nmos::fields::nc::role(restore_member)); + + const auto& filtered_members = boost::copy_range>(reference_members + | boost::adaptors::filtered([&restore_member](const web::json::value& member) + { + return nmos::fields::nc::role(restore_member) == nmos::fields::nc::role(member); + }) + ); + if (filtered_members.size() != 1) + { + // can't find this role in existing members, so member need to be added + + // find the object_properties_holder that describes the object + if (object_properties_holder_map.find(child_role_path) == object_properties_holder_map.end()) + { + auto status_message = U("Cannot find NcObjectPropertiesHolder for new resource"); + auto object_properties_set_validation = nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::failed, status_message); + web::json::push_back(object_properties_set_validations, object_properties_set_validation); + + continue; + } + + const auto& child_object_properties_holder = object_properties_holder_map.find(child_role_path); + + // Get member descriptor properties + auto role = nmos::fields::nc::role(restore_member); + auto owner = nmos::fields::nc::owner(restore_member); + auto constant_oid = nmos::fields::nc::constant_oid(restore_member); + auto oid = nmos::fields::nc::oid(restore_member); + const auto& block_member_description = nmos::fields::nc::description(restore_member); + const auto& block_member_user_label = nmos::fields::nc::user_label(restore_member); + + auto added_object_notices = web::json::value::array(); + + const auto& oid_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_oid_property_id); + oid = oid_property_holder == web::json::value::null() ? oid : nmos::fields::nc::value(oid_property_holder).as_integer(); + + if (oid_property_holder != web::json::value::null() && oid != nmos::fields::nc::value(oid_property_holder).as_integer()) + { + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::warning, U("OID value in block member inconsistent with value in property holder. Property holder value takes precidence.")); + web::json::push_back(block_notices, notice); + } + + if (constant_oid) + { + // If constant oid then check oid from property holder and verify with oid from block member + // Is this oid already in use? + const auto& child = find_resource(resources, utility::s2us(std::to_string(oid))); + + if (resources.end() != child) + { + // oid already in use! + // create device error for new object + auto status_message = U("Constant OID error. OID already in use"); + auto object_properties_set_validation = nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::device_error, status_message); + web::json::push_back(object_properties_set_validations, object_properties_set_validation); + // also create error notice for the block + const auto block_notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, status_message); + web::json::push_back(block_notices, block_notice); + // erase object from object_properties_holder_map so it isn't processed subsequently + object_properties_holder_map.erase(child_role_path); + continue; + } + } + else + { + // Ignore specified OID and generate new one + int max_oid = -1; + for (const auto& r: resources) + { + max_oid = std::max(max_oid, nmos::fields::nc::oid(r.data)); + } + oid = ++max_oid; + const auto block_notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::warning, U("Dynamically generating new OID for new block member.")); + web::json::push_back(block_notices, block_notice); + } + + // The values in the block member object properties holder will take precidence over the block member descriptor values + // If the block member values are inconsistant then warn - description and user label values can be independant + const auto& role_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_role_property_id); + role = role_property_holder == web::json::value::null() ? role : nmos::fields::nc::value(role_property_holder).as_string(); + + if (role_property_holder != web::json::value::null() && role != nmos::fields::nc::value(role_property_holder).as_string()) + { + utility::stringstream_t ss; + ss << U("Role value in block member inconsistent with value in property holder. Property holder value takes precidence for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::warning, ss.str()); + web::json::push_back(block_notices, notice); + } + if (owner != block_oid) + { + utility::stringstream_t ss; + ss << U("Owner value in block member inconsistent with oid of Block. Block oid takes precidence for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::warning, ss.str()); + web::json::push_back(block_notices, notice); + } + const auto& owner_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_owner_property_id); + if (owner_property_holder != web::json::value::null() && block_oid != nmos::fields::nc::value(owner_property_holder).as_integer()) + { + utility::stringstream_t ss; + ss << U("Owner value in block property holder inconsistent with oid of Block. Block oid takes precidence for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("owner"), nmos::nc_property_restore_notice_type::warning, ss.str()); + web::json::push_back(added_object_notices, notice); + } + const auto& constant_oid_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_constant_oid_property_id); + constant_oid = constant_oid_property_holder == web::json::value::null() ? constant_oid : nmos::fields::nc::value(constant_oid_property_holder).as_bool(); + + if (constant_oid_property_holder != web::json::value::null() && constant_oid != nmos::fields::nc::value(constant_oid_property_holder).as_bool()) + { + utility::stringstream_t ss; + ss << U("Constant OID value in block property holder inconsistent with oid of Block. Block oid takes precidence for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::warning, ss.str()); + web::json::push_back(block_notices, notice); + } + + const auto& class_id_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_class_id_property_id); + + if (class_id_property_holder == web::json::value::null()) + { + utility::stringstream_t ss; + ss << U("Class ID property value holder missing for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("class_id"), nmos::nc_property_restore_notice_type::error, ss.str()); + web::json::push_back(added_object_notices, notice); + auto object_properties_set_validation = nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::failed, added_object_notices.as_array(), ss.str()); + web::json::push_back(object_properties_set_validations, object_properties_set_validation); + // also create error notice for the block + const auto block_notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, ss.str()); + web::json::push_back(block_notices, block_notice); + + // erase object from object_properties_holder_map so it isn't processed subsequently + object_properties_holder_map.erase(child_role_path); + + continue; + } + + const auto& class_id = nmos::fields::nc::value(class_id_property_holder); + + // Validate that the class of the object to add is allowed + if (allowed_member_classes.size() > 0) + { + const auto& filtered_classes = boost::copy_range>(allowed_member_classes + | boost::adaptors::filtered([&](const web::json::value& member) + { + return member.as_array() == class_id.as_array(); + }) + ); + + // If the class not allowed then return with error + if (filtered_classes.size() == 0) + { + utility::stringstream_t ss; + ss << U("Device model error: attempting to add unexpected class for role=") << role; + const auto notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("class_id"), nmos::nc_property_restore_notice_type::error, ss.str()); + web::json::push_back(added_object_notices, notice); + auto object_properties_set_validation = nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::failed, added_object_notices.as_array(), ss.str()); + web::json::push_back(object_properties_set_validations, object_properties_set_validation); + // also create error notice for the block + const auto block_notice = nc::details::make_property_restore_notice(nmos::nc_block_members_property_id, U("members"), nmos::nc_property_restore_notice_type::error, ss.str()); + web::json::push_back(block_notices, block_notice); + + // erase object from object_properties_holder_map so it isn't processed subsequently + object_properties_holder_map.erase(child_role_path); + + continue; + } + } + + const auto& user_label_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_user_label_property_id); + const auto& user_label = (user_label_property_holder == web::json::value::null()) ? block_member_user_label : nmos::fields::nc::value(user_label_property_holder).as_string(); + + const auto& touchpoints_property_holder = nmos::get_property_holder(child_object_properties_holder->second, nmos::nc_object_touchpoints_property_id); + const auto& touchpoints = (touchpoints_property_holder == web::json::value::null()) ? web::json::value::null() : nmos::fields::nc::value(touchpoints_property_holder); + + std::map property_values; + + for (const auto& property_holder: nmos::fields::nc::values(child_object_properties_holder->second)) + { + property_values.insert(std::pair(nc::details::parse_property_id(nmos::fields::nc::id(property_holder)), nmos::fields::nc::value(property_holder))); + } + auto parsed_class_id = nc::details::parse_class_id(class_id.as_array()); + + auto device_model_object = create_device_model_object(parsed_class_id, oid, constant_oid, owner, role, user_label, touchpoints, validate, property_values); + + if (device_model_object.has_data()) + { + for (const auto& property_holder : nmos::fields::nc::values(child_object_properties_holder->second)) + { + const auto property_id = nc::details::parse_property_id(nmos::fields::nc::id(property_holder)); + const auto& property_descriptor = nmos::nc::find_property_descriptor(property_id, parsed_class_id, get_control_protocol_class_descriptor); + + if (device_model_object.data.has_field(nmos::fields::nc::name(property_descriptor))) + { + const auto& object_value = device_model_object.data[nmos::fields::nc::name(property_descriptor)]; + const auto& property_holder_value = nmos::fields::nc::value(property_holder); + //if (device_model_object.data[nmos::fields::nc::name(property_descriptor)] != nmos::fields::nc::value(property_holder)) + if (object_value != property_holder_value) + { + // warn + const auto notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::warning, U("Property not updated.")); + web::json::push_back(added_object_notices, notice); + } + } + else + { + // error doesn't have this property + const auto notice = nc::details::make_property_restore_notice(property_id, nmos::fields::nc::name(property_descriptor), nmos::nc_property_restore_notice_type::warning, U("Property not member of created object.")); + web::json::push_back(added_object_notices, notice); + } + } + + if (!validate) + { + // Add object to device model + nmos::nc::insert_resource(resources, std::move(device_model_object)); + + auto block_member_descriptor = nc::details::make_block_member_descriptor(block_member_description, role, oid, constant_oid, nmos::nc_receiver_monitor_class_id, block_member_user_label, owner); + members_to_add.push_back(block_member_descriptor); + } + web::json::push_back(object_properties_set_validations, nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::ok, added_object_notices.as_array())); + } + else + { + // An error has occurred + web::json::push_back(object_properties_set_validations, nmos::make_object_properties_set_validation(child_role_path, nmos::nc_restore_validation_status::device_error, U("Unable to create Device Model object. This may be due to missing property values."))); + } + // erase object from object_properties_holder_map so it isn't processed subsequently + object_properties_holder_map.erase(child_role_path); + } + } + // If there are any error notices, then give an overall error status for object properties set validation + const auto& error_notices = boost::copy_range>(block_notices.as_array() + | boost::adaptors::filtered([&](const web::json::value& notice) + { + return nmos::fields::nc::notice_type(notice) == nmos::nc_property_restore_notice_type::error; + }) + ); + const auto block_status = error_notices.size() ? nmos::nc_restore_validation_status::failed : nmos::nc_restore_validation_status::ok; + auto block_set_validation = nmos::make_object_properties_set_validation(target_role_path, block_status, block_notices.as_array()); + web::json::push_back(object_properties_set_validations, block_set_validation); + + // Update the members of the receivers block + if (members_to_remove.size() > 0 || members_to_add.size() > 0) + { + auto modified_members = web::json::value::array(); + + for (const auto& member : reference_members) + { + // Is this member in the members_to_remove array? + const auto& remove_member = boost::copy_range>(members_to_remove | boost::adaptors::filtered([&member](int oid) + { + return oid == nmos::fields::nc::oid(member); + }) + ); + + // If not add it to the members array + if (remove_member.size() == 0) + { + web::json::push_back(modified_members, member); + } + } + // Then add the members_to_add + for (const auto& member : members_to_add) + { + web::json::push_back(modified_members, member); + } + + // Update the block in the device model + nmos::nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) + { + resource.data[nmos::fields::nc::members] = modified_members; + + }, nc::make_property_changed_event(nmos::fields::nc::oid(resource.data), { { nmos::nc_block_members_property_id, nmos::nc_property_change_type::type::value_changed, modified_members } })); + } + + return object_properties_set_validations; + } + } + + web::json::array get_role_path(const nmos::resources& resources, const nmos::resource& resource) + { + // Find role path for object + // Hmmm do we not have a library function to do this? + using web::json::value; + + auto role_path = value::array(); + web::json::push_back(role_path, nmos::fields::nc::role(resource.data)); + + auto oid = nmos::fields::nc::id(resource.data); + nmos::resource found_resource = resource; + + while (utility::s2us(std::to_string(nmos::root_block_oid)) != oid.as_string()) + { + const auto& found = nmos::find_resource(resources, utility::s2us(std::to_string(nmos::fields::nc::owner(found_resource.data)))); + if (resources.end() == found) + { + break; + } + + found_resource = (*found); + web::json::push_back(role_path, nmos::fields::nc::role(found_resource.data)); + oid = nmos::fields::nc::id(found_resource.data); + } + + std::reverse(role_path.as_array().begin(), role_path.as_array().end()); + + return role_path.as_array(); + } + + web::json::value get_property_holder(const web::json::value& object_properties_holder, const nmos::nc_property_id& property_id) + { + const auto& filtered_property_holders = boost::copy_range>(nmos::fields::nc::values(object_properties_holder) + | boost::adaptors::filtered([&property_id](const web::json::value& property_holder) + { + return property_id == nc::details::parse_property_id(nmos::fields::nc::id(property_holder)); + }) + ); + // There should only be a single property holder for the members + if (filtered_property_holders.size() != 1) + { + // Error + return web::json::value::null(); + } + + return *filtered_property_holders.begin(); + } + + // Check to see if root_role_path is root of role_path + bool is_role_path_root(const web::json::array& role_path_root, const web::json::array& role_path) + { + if (role_path_root.size() > role_path.size()) + { + // root can't be longed that the path + return false; + } + for (size_t i = 0; i < role_path_root.size(); ++i) + { + if (role_path_root.at(i) != role_path.at(i)) + { + return false; + } + } + return true; + } + + bool is_block_modified(const nmos::resource& resource, const web::json::value& object_properties_holder) + { + // Are they blocks? + nmos::nc_class_id class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(resource.data)); + if (!nmos::nc::is_block(class_id)) + { + return false; + } + const auto& block_members_properties_holders = boost::copy_range>(nmos::fields::nc::values(object_properties_holder) + | boost::adaptors::filtered([](const web::json::value& property_holder) + { + return nmos::nc_block_members_property_id == nc::details::parse_property_id(nmos::fields::nc::id(property_holder)); + }) + ); + // There should only be a single property holder for the members + if (block_members_properties_holders.size() == 1) + { + const auto& members_property_holder = *block_members_properties_holders.begin(); + const auto& restore_members = nmos::fields::nc::value(members_property_holder); + const auto& reference_members = nmos::fields::nc::members(resource.data); + + if (reference_members.size() != restore_members.as_array().size()) + { + return true; + } + for (const auto& reference_member : reference_members) + { + const auto& filtered_members = boost::copy_range>(restore_members.as_array() + | boost::adaptors::filtered([&reference_member](const web::json::value& member) + { + return nmos::fields::nc::oid(reference_member) == nmos::fields::nc::oid(member); + }) + ); + if (filtered_members.size() != 1) + { + // can't find this oid, so member has been removed + return true; + } + const auto& restore_member = *filtered_members.begin(); + // We ignore the description and user label as these are non-normative + if (nmos::fields::nc::role(reference_member) != nmos::fields::nc::role(restore_member) + || nmos::fields::nc::constant_oid(reference_member) != nmos::fields::nc::constant_oid(restore_member) + || nmos::fields::nc::class_id(reference_member) != nmos::fields::nc::class_id(restore_member) + || nmos::fields::nc::owner(reference_member) != nmos::fields::nc::owner(restore_member)) + { + return true; + } + } + } + + return false; + } + + web::json::array get_object_properties_holder(const web::json::array& object_properties_holders, const web::json::array& target_role_path) + { + const auto& target_object_properties_holders = boost::copy_range>(object_properties_holders + | boost::adaptors::filtered([&target_role_path](const web::json::value& object_properties_holder) + { + return target_role_path == nmos::fields::nc::path(object_properties_holder); + }) + ); + return web::json::value_from_elements(target_object_properties_holders).as_array(); + } + + web::json::value apply_backup_data_set(nmos::resources& resources, const nmos::resource& resource, const web::json::array& object_properties_holders, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object) + { + auto object_properties_set_validation_values = web::json::value::array(); + + const auto target_role_path = get_role_path(resources, resource); + + // Process blocks and objects separately. + object_properties_map object_properties_holder_map; + std::vector< web::json::array > role_paths; + + utility::stringstream_t seed; + + for (const auto& object_properties_holder: object_properties_holders) + { + const auto& role_path = nmos::fields::nc::path(object_properties_holder); + // Only process role paths within the restore scope, or target_role_path only + if ((recurse && is_role_path_root(target_role_path, role_path)) || (!recurse && target_role_path == role_path)) + { + const auto& find_role_paths = get_object_properties_holder(object_properties_holders, role_path); + + // Make errors for duplicate role paths + if (find_role_paths.size() > 1) + { + seed << "."; // to avoid making identical objects + utility::stringstream_t ss; + ss << U("Duplicate object_properties_holder for role path: "); + for (const auto& element: role_path) + { + ss << element << "."; + } + ss << seed.str(); + const auto& object_properties_set_validation = nmos::make_object_properties_set_validation(nmos::fields::nc::path(object_properties_holder), nmos::nc_restore_validation_status::failed, ss.str()); + web::json::push_back(object_properties_set_validation_values, object_properties_set_validation); + } + else + { + object_properties_holder_map.insert({ role_path, object_properties_holder }); + role_paths.push_back(role_path); + } + } + } + + // Order role paths by length so we implicitly process blocks before the child objects of that block + std::sort(role_paths.begin(), role_paths.end(), [](auto a, auto b) { return a.size() < b.size(); }); + + for (const auto& role_path: role_paths) + { + const auto& r = nc::find_resource_by_role_path(resources, role_path); + + if (r == resources.end()) + { + // This could be a resource that's yet to be created in Rebuild mode (OK), or referencing a resource that doesn't exist (not OK) + // Ignore for now and we will check again once all role paths have been processed + continue; + } + if (object_properties_holder_map.find(role_path) == object_properties_holder_map.end()) + { + // If this role_path is no longer in the map it may have been erased by modify_rebuildable_block + continue; + } + + const auto& object_properties_holder = object_properties_holder_map.at(role_path); + + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(r->data)); + + if (nmos::nc::is_block(class_id) && nmos::fields::nc::is_rebuildable(r->data) && restore_mode == nmos::nc_restore_mode::rebuild && is_block_modified(*r, object_properties_holder)) + { + // Modify rebuildable block + if (remove_device_model_object && create_device_model_object) + { + // Process this block to add / remove device model objects as members of this block + // the object properties holder for any added objects will be erased from the object_properties_holder_map to avoid double processing + const auto child_object_properties_set_validations = details::modify_rebuildable_block(resources, object_properties_holder_map, *r, role_path, object_properties_holder, validate, get_control_protocol_class_descriptor, remove_device_model_object, create_device_model_object); + for (const auto& validation_values : child_object_properties_set_validations.as_array()) + { + web::json::push_back(object_properties_set_validation_values, validation_values); + } + + } + else + { + // Rebuilding blocks not supported + const auto& object_properties_set_validation = nmos::make_object_properties_set_validation(role_path, nmos::nc_restore_validation_status::failed, U("Rebuilding of Device Model blocks not supported")); + web::json::push_back(object_properties_set_validation_values, object_properties_set_validation); + } + } + else + { + const auto object_properties_set_validation = details::modify_device_model_object(resources, *r, role_path, object_properties_holder, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list); + web::json::push_back(object_properties_set_validation_values, object_properties_set_validation); + } + + object_properties_holder_map.erase(role_path); + } + + // What ever remains is referencing an object not in the device model + for(const auto& object_properties_holder: object_properties_holder_map) + { + const auto& object_properties_set_validation = nmos::make_object_properties_set_validation(object_properties_holder.first, nmos::nc_restore_validation_status::not_found, U("Unknown role path")); + web::json::push_back(object_properties_set_validation_values, object_properties_set_validation); + } + + return object_properties_set_validation_values; + } +} diff --git a/Development/nmos/configuration_utils.h b/Development/nmos/configuration_utils.h new file mode 100644 index 000000000..8157d4173 --- /dev/null +++ b/Development/nmos/configuration_utils.h @@ -0,0 +1,35 @@ +#ifndef NMOS_CONFIGURATION_UTILS_H +#define NMOS_CONFIGURATION_UTILS_H + +#include "nmos/configuration_handlers.h" +#include "nmos/control_protocol_handlers.h" +#include "nmos/resources.h" + +namespace nmos +{ + typedef std::map object_properties_map; + + struct control_protocol_resource; + + namespace details + { + web::json::value modify_rebuildable_block(nmos::resources& resources, object_properties_map& object_properties_holder_map, const nmos::resource& resource, const web::json::array& target_role_path, const web::json::value& block_object_properties_holder, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object); + } + + // Check to see if role_path is sub path of parent_role_path + bool is_role_path_root(const web::json::array& role_path_, const web::json::array& parent_role_path); + + bool is_block_modified(const nmos::resource& resource, const web::json::value& object_properties_holder); + + // Get role path of resource given the Device Model resources + web::json::array get_role_path(const nmos::resources& resources, const nmos::resource& resource); + + // Get object_properties_holder for specified target_role_path + web::json::array get_object_properties_holder(const web::json::array& object_properties_holders, const web::json::array& target_role_path); + + web::json::value apply_backup_data_set(nmos::resources& resources, const nmos::resource& resource, const web::json::array& object_properties_holders, bool recurse, nmos::nc_restore_mode::restore_mode restore_mode, bool validate, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, nmos::remove_device_model_object_handler remove_device_model_object, nmos::create_device_model_object_handler create_device_model_object); + + web::json::value get_property_holder(const web::json::value& object_properties_holder, const nmos::nc_property_id& property_id); +} + +#endif diff --git a/Development/nmos/control_protocol_behaviour.cpp b/Development/nmos/control_protocol_behaviour.cpp index 868a7f08a..e3333a711 100644 --- a/Development/nmos/control_protocol_behaviour.cpp +++ b/Development/nmos/control_protocol_behaviour.cpp @@ -73,7 +73,7 @@ namespace nmos { // Get all status monitors - including receiver and sender monitors auto descriptors = web::json::value::array(); - nmos::find_members_by_class_id(control_protocol_resources, *found, nmos::nc_status_monitor_class_id, true, true, descriptors.as_array()); + nmos::nc::find_members_by_class_id(control_protocol_resources, *found, nmos::nc_status_monitor_class_id, true, true, descriptors.as_array()); bool monitors_updates_pending = false; @@ -87,15 +87,15 @@ namespace nmos for (const auto& descriptor : descriptors.as_array()) { auto oid = nmos::fields::nc::oid(descriptor); - const auto& class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(descriptor)); + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(descriptor)); - auto status_reporting_delay = get_control_protocol_property(control_protocol_resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); + auto status_reporting_delay = nc::get_property(control_protocol_resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); - const auto& domain_statuses = nmos::is_nc_sender_monitor(class_id) ? sender_monitor_domain_statuses : receiver_monitor_domain_statuses; + const auto& domain_statuses = nmos::nc::is_sender_monitor(class_id) ? sender_monitor_domain_statuses : receiver_monitor_domain_statuses; for (const auto& domain_status : domain_statuses) { - auto received_time = get_control_protocol_property(control_protocol_resources, oid, domain_status.status_pending_received_time_field_name, gate); + auto received_time = nc::get_property(control_protocol_resources, oid, domain_status.status_pending_received_time_field_name, gate); if (received_time.as_integer() > 0) { @@ -124,15 +124,15 @@ namespace nmos for (const auto& descriptor : descriptors.as_array()) { const auto& oid = nmos::fields::nc::oid(descriptor); - const auto& class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(descriptor)); + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(descriptor)); - const auto status_reporting_delay = get_control_protocol_property(control_protocol_resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); + const auto status_reporting_delay = nc::get_property(control_protocol_resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); - const auto& domain_statuses = nmos::is_nc_sender_monitor(class_id) ? sender_monitor_domain_statuses : receiver_monitor_domain_statuses; + const auto& domain_statuses = nmos::nc::is_sender_monitor(class_id) ? sender_monitor_domain_statuses : receiver_monitor_domain_statuses; for (const auto& domain_status : domain_statuses) { - const auto received_time = get_control_protocol_property(control_protocol_resources, oid, domain_status.status_pending_received_time_field_name, gate); + const auto received_time = nc::get_property(control_protocol_resources, oid, domain_status.status_pending_received_time_field_name, gate); if (received_time.as_integer() > 0) { @@ -141,10 +141,10 @@ namespace nmos if (current_time >= threshold_time) { // copy pending status to status property - const auto& status = get_control_protocol_property(control_protocol_resources, oid, domain_status.status_pending_field_name, gate); - const auto& status_message = get_control_protocol_property(control_protocol_resources, oid, domain_status.status_message_pending_field_name, gate); + const auto& status = nc::get_property(control_protocol_resources, oid, domain_status.status_pending_field_name, gate); + const auto& status_message = nc::get_property(control_protocol_resources, oid, domain_status.status_message_pending_field_name, gate); const auto& status_message_string = status_message == web::json::value::null() ? U("") : status_message.as_string(); - details::set_monitor_status(control_protocol_resources, oid, status.as_integer(), status_message_string, + nc::details::set_monitor_status(control_protocol_resources, oid, status.as_integer(), status_message_string, domain_status.status_property_id, domain_status.status_message_property_id, domain_status.status_transition_counter_property_id, diff --git a/Development/nmos/control_protocol_handlers.cpp b/Development/nmos/control_protocol_handlers.cpp index 044fa9539..8ec66b32c 100644 --- a/Development/nmos/control_protocol_handlers.cpp +++ b/Development/nmos/control_protocol_handlers.cpp @@ -55,7 +55,7 @@ namespace nmos auto& method_descriptors = control_class_descriptor.method_descriptors; auto found = std::find_if(method_descriptors.begin(), method_descriptors.end(), [&method_id](const experimental::method& method) { - return method_id == details::parse_nc_method_id(nmos::fields::nc::id(std::get<0>(method))); + return method_id == nc::details::parse_method_id(nmos::fields::nc::id(std::get<0>(method))); }); if (method_descriptors.end() != found) { @@ -91,20 +91,20 @@ namespace nmos const auto& endpoint_active = nmos::fields::endpoint_active(connection_resource.data); const bool active = nmos::fields::master_enable(endpoint_active); - auto found = find_control_protocol_resource(resources, nmos::types::nc_status_monitor, connection_resource.id); - if (resources.end() != found && nmos::is_nc_status_monitor(details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)))) + auto found = nc::find_resource(resources, nmos::types::nc_status_monitor, connection_resource.id); + if (resources.end() != found && nmos::nc::is_status_monitor(nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)))) { const auto& oid = nmos::fields::nc::oid(found->data); if (active) { // Activate monitor - activate_monitor(resources, oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); + nc::activate_monitor(resources, oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); } else { // deactivate monitor - deactivate_monitor(resources, oid, get_control_protocol_class_descriptor, gate); + nc::deactivate_monitor(resources, oid, get_control_protocol_class_descriptor, gate); } } }; @@ -116,7 +116,7 @@ namespace nmos return [&resources, get_control_protocol_class_descriptor, &gate](nc_oid oid, const nc_property_id& property_id) { - return get_control_protocol_property(resources, oid, property_id, get_control_protocol_class_descriptor, gate); + return nc::get_property(resources, oid, property_id, get_control_protocol_class_descriptor, gate); }; } @@ -126,7 +126,7 @@ namespace nmos return [&resources, get_control_protocol_class_descriptor, &gate](nc_oid oid, const nc_property_id& property_id, const web::json::value& value) { - return set_control_protocol_property_and_notify(resources, oid, property_id, value, get_control_protocol_class_descriptor, gate); + return nc::set_property_and_notify(resources, oid, property_id, value, get_control_protocol_class_descriptor, gate); }; } @@ -137,7 +137,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message) { - return set_receiver_monitor_link_status_with_delay(resources, oid, link_status, link_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_receiver_monitor_link_status_with_delay(resources, oid, link_status, link_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -149,7 +149,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message) { - return set_receiver_monitor_connection_status_with_delay(resources, oid, connection_status, connection_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_receiver_monitor_connection_status_with_delay(resources, oid, connection_status, connection_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -161,7 +161,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message) { - return set_receiver_monitor_external_synchronization_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_receiver_monitor_external_synchronization_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -173,7 +173,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message) { - return set_receiver_monitor_stream_status_with_delay(resources, oid, stream_status, stream_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_receiver_monitor_stream_status_with_delay(resources, oid, stream_status, stream_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -184,7 +184,7 @@ namespace nmos return [&resources, get_control_protocol_class_descriptor, &gate](nc_oid oid, const bst::optional& source_id) { - return set_monitor_synchronization_source_id(resources, oid, source_id, get_control_protocol_class_descriptor, gate); + return nc::set_monitor_synchronization_source_id(resources, oid, source_id, get_control_protocol_class_descriptor, gate); }; } @@ -196,7 +196,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message) { - return set_sender_monitor_link_status_with_delay(resources, oid, link_status, link_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_sender_monitor_link_status_with_delay(resources, oid, link_status, link_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -208,7 +208,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message) { - return set_sender_monitor_transmission_status_with_delay(resources, oid, transmission_status, transmission_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_sender_monitor_transmission_status_with_delay(resources, oid, transmission_status, transmission_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -220,7 +220,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message) { - return set_sender_monitor_external_synchronization_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_sender_monitor_external_synchronization_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -232,7 +232,7 @@ namespace nmos return [&resources, monitor_status_pending, get_control_protocol_class_descriptor, &gate](nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message) { - return set_sender_monitor_essence_status_with_delay(resources, oid, essence_status, essence_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); + return nc::set_sender_monitor_essence_status_with_delay(resources, oid, essence_status, essence_status_message, monitor_status_pending, get_control_protocol_class_descriptor, gate); }; } @@ -243,7 +243,7 @@ namespace nmos return [&resources, get_control_protocol_class_descriptor, &gate](nc_oid oid, const bst::optional& source_id) { - return set_monitor_synchronization_source_id(resources, oid, source_id, get_control_protocol_class_descriptor, gate); + return nc::set_monitor_synchronization_source_id(resources, oid, source_id, get_control_protocol_class_descriptor, gate); }; } } diff --git a/Development/nmos/control_protocol_handlers.h b/Development/nmos/control_protocol_handlers.h index 988059f03..18fa3824e 100644 --- a/Development/nmos/control_protocol_handlers.h +++ b/Development/nmos/control_protocol_handlers.h @@ -42,7 +42,7 @@ namespace nmos // callback to set monitor pending typedef std::function monitor_status_pending_handler; - // Receiver Monitor status callbacks + // Receiver & Sender Monitor status callbacks // these callbacks should not throw exceptions namespace nc { @@ -117,6 +117,7 @@ namespace nmos set_receiver_monitor_synchronization_source_id_handler make_set_receiver_monitor_synchronization_source_id_handler(resources& resources, experimental::control_protocol_state& control_protocol_state, slog::base_gate& gate); // NcSenderMonitor handlers + // Set sender monitor link status and link status message typedef std::function set_sender_monitor_link_status_handler; set_sender_monitor_link_status_handler make_set_sender_monitor_link_status_handler(resources& resources, experimental::control_protocol_state& control_protocol_state, slog::base_gate& gate); diff --git a/Development/nmos/control_protocol_methods.cpp b/Development/nmos/control_protocol_methods.cpp index 8ec6c1731..337cd43ad 100644 --- a/Development/nmos/control_protocol_methods.cpp +++ b/Development/nmos/control_protocol_methods.cpp @@ -10,783 +10,786 @@ namespace nmos { - // NcObject methods implementation - // Get property value - web::json::value get(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + namespace nc { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - - const auto& property_id = nmos::fields::nc::id(arguments); - - slog::log(gate, SLOG_FLF) << "Get property: " << property_id.serialize(); - - // find the relevant nc_property_descriptor - const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) + // NcObject methods implementation + // Get property value + web::json::value get(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, resource.data.at(nmos::fields::nc::name(property))); - } + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << U(" to do Get"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } + const auto& property_id = nmos::fields::nc::id(arguments); - // Set property value - web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + slog::log(gate, SLOG_FLF) << "Get property: " << property_id.serialize(); - const auto& property_id = nmos::fields::nc::id(arguments); - const auto& val = nmos::fields::nc::value(arguments); + // find the relevant nc_property_descriptor + const auto& property = nc::find_property_descriptor(details::parse_property_id(property_id), details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) + { + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}, resource.data.at(nmos::fields::nc::name(property))); + } - slog::log(gate, SLOG_FLF) << "Set property: " << property_id.serialize() << " value: " << val.serialize(); + // unknown property + utility::ostringstream_t ss; + ss << U("unknown property: ") << property_id.serialize() << U(" to do Get"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); + } - // find the relevant nc_property_descriptor - const auto property_id_ = details::parse_nc_property_id(property_id); - const auto& property = find_property_descriptor(property_id_, details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) + // Set property value + web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { - if (nmos::fields::nc::is_read_only(property)) - { - utility::ostringstream_t ss; - ss << U("can not set read only property: ") << property_id.serialize(); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::read_only }, ss.str()); - } + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - if ((val.is_null() && !nmos::fields::nc::is_nullable(property)) - || (!val.is_array() && nmos::fields::nc::is_sequence(property)) - || (val.is_array() && !nmos::fields::nc::is_sequence(property))) - { - utility::ostringstream_t ss; - ss << U("parameter error: cannot set value: ") << val.serialize() << U(" on property: ") << property_id.serialize(); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); - } + const auto& property_id = nmos::fields::nc::id(arguments); + const auto& val = nmos::fields::nc::value(arguments); - // Special case for BCP-008-01/02 where it specifies that status monitors cannot be disabled - if (nmos::fields::nc::name(property).c_str() == nmos::fields::nc::enabled.key - && is_nc_status_monitor(details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data))) - && !val.as_bool()) - { - utility::ostringstream_t ss; - ss << U("invalid request: cannot disable NcStatusMonitors"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } + slog::log(gate, SLOG_FLF) << "Set property: " << property_id.serialize() << " value: " << val.serialize(); - try + // find the relevant nc_property_descriptor + const auto property_id_ = details::parse_property_id(property_id); + const auto& property = nc::find_property_descriptor(property_id_, details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - // do property constraints validation - nmos::details::constraints_validation(val, details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), { details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor }); + if (nmos::fields::nc::is_read_only(property)) + { + utility::ostringstream_t ss; + ss << U("can not set read only property: ") << property_id.serialize(); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::read_only}, ss.str()); + } - // update property - modify_control_protocol_resource(resources, resource.id, [&](nmos::resource& resource) + if ((val.is_null() && !nmos::fields::nc::is_nullable(property)) + || (!val.is_array() && nmos::fields::nc::is_sequence(property)) + || (val.is_array() && !nmos::fields::nc::is_sequence(property))) { - resource.data[nmos::fields::nc::name(property)] = val; + utility::ostringstream_t ss; + ss << U("parameter error: cannot set value: ") << val.serialize() << U(" on property: ") << property_id.serialize(); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); + } - // do notification that the specified property has changed - if (property_changed) + // Special case for BCP-008-01/02 where it specifies that status monitors cannot be disabled + if (nmos::fields::nc::name(property).c_str() == nmos::fields::nc::enabled.key + && nc::is_status_monitor(details::parse_class_id(nmos::fields::nc::class_id(resource.data))) + && !val.as_bool()) + { + utility::ostringstream_t ss; + ss << U("invalid request: cannot disable NcStatusMonitors"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } + + try + { + // do property constraints validation + nmos::nc::details::constraints_validation(val, nc::details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), {nc::details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor}); + + // update property + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) { - property_changed(resource, nmos::fields::nc::name(property), -1); - } + resource.data[nmos::fields::nc::name(property)] = val; - }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::value_changed, val } })); + // do notification that the specified property has changed + if (property_changed) + { + property_changed(resource, nmos::fields::nc::name(property), -1); + } - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + }, make_property_changed_event(nmos::fields::nc::oid(resource.data), {{property_id_, nc_property_change_type::type::value_changed, val}})); + + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}); + } + catch (const nmos::control_protocol_exception& e) + { + utility::ostringstream_t ss; + ss << "Set property: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); + } } - catch (const nmos::control_protocol_exception& e) + + // unknown property + utility::ostringstream_t ss; + ss << U("unknown property: ") << property_id.serialize() << " to do Set"; + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); + } + + // Get sequence item + web::json::value get_sequence_item(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + + const auto& property_id = nmos::fields::nc::id(arguments); + const auto& index = nmos::fields::nc::index(arguments); + + slog::log(gate, SLOG_FLF) << "Get sequence item: " << property_id.serialize() << " index: " << index; + + // find the relevant nc_property_descriptor + const auto& property = nc::find_property_descriptor(details::parse_property_id(property_id), details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { + const auto& data = resource.data.at(nmos::fields::nc::name(property)); + + if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) + { + // property is not a sequence + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceItem"); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } + + if (data.as_array().size() > (size_t)index) + { + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}, data.at(index)); + } + + // out of bound utility::ostringstream_t ss; - ss << "Set property: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); + ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do GetSequenceItem"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); + return details::make_method_result_error({nc_method_status::index_out_of_bounds}, ss.str()); } + + // unknown property + utility::ostringstream_t ss; + ss << U("unknown property: ") << property_id.serialize() << U(" to do GetSequenceItem"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); } - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << " to do Set"; - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } + // Set sequence item + web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - // Get sequence item - web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + const auto& property_id = nmos::fields::nc::id(arguments); + const auto& index = nmos::fields::nc::index(arguments); + const auto& val = nmos::fields::nc::value(arguments); - const auto& property_id = nmos::fields::nc::id(arguments); - const auto& index = nmos::fields::nc::index(arguments); + slog::log(gate, SLOG_FLF) << "Set sequence item: " << property_id.serialize() << " index: " << index << " value: " << val.serialize(); - slog::log(gate, SLOG_FLF) << "Get sequence item: " << property_id.serialize() << " index: " << index; + // find the relevant nc_property_descriptor + const auto property_id_ = details::parse_property_id(property_id); + const auto& property = nc::find_property_descriptor(property_id_, details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) + { + if (nmos::fields::nc::is_read_only(property)) + { + return details::make_method_result({nc_method_status::read_only}); + } - // find the relevant nc_property_descriptor - const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) - { - const auto& data = resource.data.at(nmos::fields::nc::name(property)); + auto& data = resource.data.at(nmos::fields::nc::name(property)); - if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) - { - // property is not a sequence - utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceItem"); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } + if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) + { + // property is not a sequence + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do SetSequenceItem"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } - if (data.as_array().size() > (size_t)index) - { - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, data.at(index)); + if (data.as_array().size() > (size_t)index) + { + try + { + // do property constraints validation + nmos::nc::details::constraints_validation(val, nc::details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), {nc::details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor}); + + // update property + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) + { + resource.data[nmos::fields::nc::name(property)][index] = val; + + // do notification that the specified property has changed + if (property_changed) + { + property_changed(resource, nmos::fields::nc::name(property), index); + } + + }, make_property_changed_event(nmos::fields::nc::oid(resource.data), {{property_id_, nc_property_change_type::type::sequence_item_changed, val, nc_id(index)}})); + + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}); + } + catch (const nmos::control_protocol_exception& e) + { + utility::ostringstream_t ss; + ss << "Set sequence item: " << property_id.serialize() << " index: " << index << " value: " << val.serialize() << " error: " << e.what(); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); + } + } + + // out of bound + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do SetSequenceItem"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::index_out_of_bounds}, ss.str()); } - // out of bound + // unknown property utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do GetSequenceItem"); + ss << U("unknown property: ") << property_id.serialize() << U(" to do SetSequenceItem"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); } - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << U(" to do GetSequenceItem"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } + // Add item to sequence + web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - // Set sequence item - web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + using web::json::value; - const auto& property_id = nmos::fields::nc::id(arguments); - const auto& index = nmos::fields::nc::index(arguments); - const auto& val = nmos::fields::nc::value(arguments); + const auto& property_id = nmos::fields::nc::id(arguments); + const auto& val = nmos::fields::nc::value(arguments); - slog::log(gate, SLOG_FLF) << "Set sequence item: " << property_id.serialize() << " index: " << index << " value: " << val.serialize(); + slog::log(gate, SLOG_FLF) << "Add sequence item: " << property_id.serialize() << " value: " << val.serialize(); - // find the relevant nc_property_descriptor - const auto property_id_ = details::parse_nc_property_id(property_id); - const auto& property = find_property_descriptor(property_id_, details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) - { - if (nmos::fields::nc::is_read_only(property)) + // find the relevant nc_property_descriptor + const auto property_id_ = details::parse_property_id(property_id); + const auto& property = nc::find_property_descriptor(property_id_, details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - return details::make_nc_method_result({ nc_method_status::read_only }); - } + if (nmos::fields::nc::is_read_only(property)) + { + return details::make_method_result({nc_method_status::read_only}); + } - auto& data = resource.data.at(nmos::fields::nc::name(property)); + if (!nmos::fields::nc::is_sequence(property)) + { + // property is not a sequence + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do AddSequenceItem"); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } - if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) - { - // property is not a sequence - utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do SetSequenceItem"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } + auto& data = resource.data.at(nmos::fields::nc::name(property)); + + const nc_id sequence_item_index = data.is_null() ? 0 : nc_id(data.as_array().size()); - if (data.as_array().size() > (size_t)index) - { try { // do property constraints validation - nmos::details::constraints_validation(val, details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), { details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor }); + nmos::nc::details::constraints_validation(val, nc::details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), {nc::details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor}); // update property - modify_control_protocol_resource(resources, resource.id, [&](nmos::resource& resource) + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) { - resource.data[nmos::fields::nc::name(property)][index] = val; + auto& sequence = resource.data[nmos::fields::nc::name(property)]; + if (data.is_null()) { sequence = value::array(); } + web::json::push_back(sequence, val); // do notification that the specified property has changed if (property_changed) { - property_changed(resource, nmos::fields::nc::name(property), index); + property_changed(resource, nmos::fields::nc::name(property), (int)sequence.as_array().size() - 1); } - }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::sequence_item_changed, val, nc_id(index) } })); + }, make_property_changed_event(nmos::fields::nc::oid(resource.data), {{property_id_, nc_property_change_type::type::sequence_item_added, val, sequence_item_index}})); - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}, sequence_item_index); } catch (const nmos::control_protocol_exception& e) { utility::ostringstream_t ss; - ss << "Set sequence item: " << property_id.serialize() << " index: " << index << " value: " << val.serialize() << " error: " << e.what(); + ss << "Add sequence item: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); } } - // out of bound + // unknown property utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do SetSequenceItem"); + ss << U("unknown property: ") << property_id.serialize() << U(" to do AddSequenceItem"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); } - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << U(" to do SetSequenceItem"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } - - // Add item to sequence - web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - - using web::json::value; - - const auto& property_id = nmos::fields::nc::id(arguments); - const auto& val = nmos::fields::nc::value(arguments); - - slog::log(gate, SLOG_FLF) << "Add sequence item: " << property_id.serialize() << " value: " << val.serialize(); - - // find the relevant nc_property_descriptor - const auto property_id_ = details::parse_nc_property_id(property_id); - const auto& property = find_property_descriptor(property_id_, details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) + // Delete sequence item + web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) { - if (nmos::fields::nc::is_read_only(property)) - { - return details::make_nc_method_result({ nc_method_status::read_only }); - } + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - if (!nmos::fields::nc::is_sequence(property)) - { - // property is not a sequence - utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do AddSequenceItem"); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } - - auto& data = resource.data.at(nmos::fields::nc::name(property)); + const auto& property_id = nmos::fields::nc::id(arguments); + const auto& index = nmos::fields::nc::index(arguments); - const nc_id sequence_item_index = data.is_null() ? 0 : nc_id(data.as_array().size()); + slog::log(gate, SLOG_FLF) << "Remove sequence item: " << property_id.serialize() << " index: " << index; - try + // find the relevant nc_property_descriptor + const auto& property = nc::find_property_descriptor(details::parse_property_id(property_id), details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - // do property constraints validation - nmos::details::constraints_validation(val, details::get_runtime_property_constraints(property_id_, resource.data.at(nmos::fields::nc::runtime_property_constraints)), nmos::fields::nc::constraints(property), { details::get_datatype_descriptor(property.at(nmos::fields::nc::type_name), get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor }); - - // update property - modify_control_protocol_resource(resources, resource.id, [&](nmos::resource& resource) + if (nmos::fields::nc::is_read_only(property)) { - auto& sequence = resource.data[nmos::fields::nc::name(property)]; - if (data.is_null()) { sequence = value::array(); } - web::json::push_back(sequence, val); - - // do notification that the specified property has changed - if (property_changed) - { - property_changed(resource, nmos::fields::nc::name(property), (int)sequence.as_array().size()-1); - } - - }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_id_, nc_property_change_type::type::sequence_item_added, val, sequence_item_index } })); - - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, sequence_item_index); - } - catch (const nmos::control_protocol_exception& e) - { - utility::ostringstream_t ss; - ss << "Add sequence item: " << property_id.serialize() << " value: " << val.serialize() << " error: " << e.what(); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); - } - } + return details::make_method_result({nc_method_status::read_only}); + } - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << U(" to do AddSequenceItem"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } + const auto& data = resource.data.at(nmos::fields::nc::name(property)); - // Delete sequence item - web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) + { + // property is not a sequence + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do RemoveSequenceItem"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } - const auto& property_id = nmos::fields::nc::id(arguments); - const auto& index = nmos::fields::nc::index(arguments); + if (data.as_array().size() > (size_t)index) + { + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) + { + auto& sequence = resource.data[nmos::fields::nc::name(property)].as_array(); + sequence.erase(index); - slog::log(gate, SLOG_FLF) << "Remove sequence item: " << property_id.serialize() << " index: " << index; + // do notification that the specified property has changed + if (property_changed) + { + property_changed(resource, nmos::fields::nc::name(property), -2); + } - // find the relevant nc_property_descriptor - const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) - { - if (nmos::fields::nc::is_read_only(property)) - { - return details::make_nc_method_result({ nc_method_status::read_only }); - } + }, make_property_changed_event(nmos::fields::nc::oid(resource.data), {{details::parse_property_id(property_id), nc_property_change_type::type::sequence_item_removed, nc_id(index)}})); - const auto& data = resource.data.at(nmos::fields::nc::name(property)); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}); + } - if (!nmos::fields::nc::is_sequence(property) || data.is_null() || !data.is_array()) - { - // property is not a sequence + // out of bound utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do RemoveSequenceItem"); + ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do RemoveSequenceItem"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } - - if (data.as_array().size() > (size_t)index) - { - modify_control_protocol_resource(resources, resource.id, [&](nmos::resource& resource) - { - auto& sequence = resource.data[nmos::fields::nc::name(property)].as_array(); - sequence.erase(index); - - // do notification that the specified property has changed - if (property_changed) - { - property_changed(resource, nmos::fields::nc::name(property), -2); - } - - }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { details::parse_nc_property_id(property_id), nc_property_change_type::type::sequence_item_removed, nc_id(index) } })); - - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }); + return details::make_method_result_error({nc_method_status::index_out_of_bounds}, ss.str()); } - // out of bound + // unknown property utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is outside the available range to do RemoveSequenceItem"); + ss << U("unknown property: ") << property_id.serialize() << U(" to do RemoveSequenceItem"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::index_out_of_bounds }, ss.str()); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); } - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << U(" to do RemoveSequenceItem"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } - - // Get sequence length - web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + // Get sequence length + web::json::value get_sequence_length(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - using web::json::value; + using web::json::value; - const auto& property_id = nmos::fields::nc::id(arguments); + const auto& property_id = nmos::fields::nc::id(arguments); - slog::log(gate, SLOG_FLF) << "Get sequence length: " << property_id.serialize(); + slog::log(gate, SLOG_FLF) << "Get sequence length: " << property_id.serialize(); - // find the relevant nc_property_descriptor - const auto& property = find_property_descriptor(details::parse_nc_property_id(property_id), details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) - { - if (!nmos::fields::nc::is_sequence(property)) + // find the relevant nc_property_descriptor + const auto& property = nc::find_property_descriptor(details::parse_property_id(property_id), details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - // property is not a sequence - utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceLength"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); - } + if (!nmos::fields::nc::is_sequence(property)) + { + // property is not a sequence + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << U(" is not a sequence to do GetSequenceLength"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } - const auto& data = resource.data.at(nmos::fields::nc::name(property)); + const auto& data = resource.data.at(nmos::fields::nc::name(property)); - if (nmos::fields::nc::is_nullable(property)) - { - // can be null - if (data.is_null()) + if (nmos::fields::nc::is_nullable(property)) { - // null - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, value::null()); + // can be null + if (data.is_null()) + { + // null + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}, value::null()); + } } - } - else - { - // cannot be null - if (data.is_null()) + else { - // null - utility::ostringstream_t ss; - ss << U("property: ") << property_id.serialize() << " is a null sequence to do GetSequenceLength"; - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::invalid_request }, ss.str()); + // cannot be null + if (data.is_null()) + { + // null + utility::ostringstream_t ss; + ss << U("property: ") << property_id.serialize() << " is a null sequence to do GetSequenceLength"; + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::invalid_request}, ss.str()); + } } + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok}, value(uint32_t(data.as_array().size()))); } - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nmos::fields::nc::is_deprecated(property) ? nc_method_status::property_deprecated : nc_method_status::ok }, value(uint32_t(data.as_array().size()))); - } - - // unknown property - utility::ostringstream_t ss; - ss << U("unknown property: ") << property_id.serialize() << " to do GetSequenceLength"; - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::property_not_implemented }, ss.str()); - } - // NcBlock methods implementation - // Gets descriptors of members of the block - web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + // unknown property + utility::ostringstream_t ss; + ss << U("unknown property: ") << property_id.serialize() << " to do GetSequenceLength"; + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::property_not_implemented}, ss.str()); + } - using web::json::value; + // NcBlock methods implementation + // Gets descriptors of members of the block + web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - const auto& recurse = nmos::fields::nc::recurse(arguments); // If recurse is set to true, nested members is to be retrieved + using web::json::value; - slog::log(gate, SLOG_FLF) << "Get descriptors of members of the block: " << "recurse: " << recurse; + const auto& recurse = nmos::fields::nc::recurse(arguments); // If recurse is set to true, nested members is to be retrieved - auto descriptors = value::array(); - nmos::get_member_descriptors(resources, resource, recurse, descriptors.as_array()); + slog::log(gate, SLOG_FLF) << "Get descriptors of members of the block: " << "recurse: " << recurse; - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); - } + auto descriptors = value::array(); + nmos::nc::get_member_descriptors(resources, resource, recurse, descriptors.as_array()); - // Finds member(s) by path - web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource_, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptors); + } - using web::json::value; + // Finds member(s) by path + web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource_, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - // Relative path to search for (MUST not include the role of the block targeted by oid) - const auto& path = arguments.at(nmos::fields::nc::path); + using web::json::value; - slog::log(gate, SLOG_FLF) << "Find member(s) by path: " << "path: " << path.serialize(); + // Relative path to search for (MUST not include the role of the block targeted by oid) + const auto& path = arguments.at(nmos::fields::nc::path); - if (0 == path.size()) - { - // empty path - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty path to do FindMembersByPath")); - } + slog::log(gate, SLOG_FLF) << "Find member(s) by path: " << "path: " << path.serialize(); - auto descriptors = value::array(); - value descriptor; + if (0 == path.size()) + { + // empty path + return details::make_method_result_error({nc_method_status::parameter_error}, U("empty path to do FindMembersByPath")); + } - nmos::resource resource = resource_; - for (const auto& role : path.as_array()) - { - // look for the role in members + auto descriptors = value::array(); + value descriptor; - if (resource.data.has_field(nmos::fields::nc::members)) + nmos::resource resource = resource_; + for (const auto& role : path.as_array()) { - auto& members = nmos::fields::nc::members(resource.data); - auto member_found = std::find_if(members.begin(), members.end(), [&](const web::json::value& nc_block_member_descriptor) - { - return role.as_string() == nmos::fields::nc::role(nc_block_member_descriptor); - }); + // look for the role in members - if (members.end() != member_found) + if (resource.data.has_field(nmos::fields::nc::members)) { - descriptor = *member_found; + auto& members = nmos::fields::nc::members(resource.data); + auto member_found = std::find_if(members.begin(), members.end(), [&](const web::json::value& nc_block_member_descriptor) + { + return role.as_string() == nmos::fields::nc::role(nc_block_member_descriptor); + }); + + if (members.end() != member_found) + { + descriptor = *member_found; - // use oid to look for the next resource - resource = *nmos::find_resource(resources, utility::s2us(std::to_string(nmos::fields::nc::oid(*member_found)))); + // use oid to look for the next resource + resource = *nmos::find_resource(resources, utility::s2us(std::to_string(nmos::fields::nc::oid(*member_found)))); + } + else + { + // no role + utility::ostringstream_t ss; + ss << U("role: ") << role.as_string() << U(" not found to do FindMembersByPath"); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); + } } else { - // no role + // no members utility::ostringstream_t ss; - ss << U("role: ") << role.as_string() << U(" not found to do FindMembersByPath"); + ss << U("role: ") << role.as_string() << U(" has no members to do FindMembersByPath"); slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); } } - else - { - // no members - utility::ostringstream_t ss; - ss << U("role: ") << role.as_string() << U(" has no members to do FindMembersByPath"); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); - } - } - - web::json::push_back(descriptors, descriptor); - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); - } - // Finds members with given role name or fragment - web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - - using web::json::value; - - const auto& role = nmos::fields::nc::role(arguments); // Role text to search for - const auto& case_sensitive = nmos::fields::nc::case_sensitive(arguments); // Signals if the comparison should be case sensitive - const auto& match_whole_string = nmos::fields::nc::match_whole_string(arguments); // TRUE to only return exact matches - const auto& recurse = nmos::fields::nc::recurse(arguments); // TRUE to search nested blocks - - slog::log(gate, SLOG_FLF) << "Find members with given role name or fragment: " << "role: " << role; + web::json::push_back(descriptors, descriptor); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptors); + } - if (role.empty()) + // Finds members with given role name or fragment + web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - // empty role - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty role to do FindMembersByRole")); - } + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - auto descriptors = value::array(); - nmos::find_members_by_role(resources, resource, role, match_whole_string, case_sensitive, recurse, descriptors.as_array()); + using web::json::value; - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); - } + const auto& role = nmos::fields::nc::role(arguments); // Role text to search for + const auto& case_sensitive = nmos::fields::nc::case_sensitive(arguments); // Signals if the comparison should be case sensitive + const auto& match_whole_string = nmos::fields::nc::match_whole_string(arguments); // TRUE to only return exact matches + const auto& recurse = nmos::fields::nc::recurse(arguments); // TRUE to search nested blocks - // Finds members with given class id - web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + slog::log(gate, SLOG_FLF) << "Find members with given role name or fragment: " << "role: " << role; - using web::json::value; + if (role.empty()) + { + // empty role + return details::make_method_result_error({nc_method_status::parameter_error}, U("empty role to do FindMembersByRole")); + } - const auto class_id = details::parse_nc_class_id(nmos::fields::nc::class_id(arguments)); // Class id to search for - const auto& include_derived = nmos::fields::nc::include_derived(arguments); // If TRUE it will also include derived class descriptors - const auto& recurse = nmos::fields::nc::recurse(arguments); // TRUE to search nested blocks + auto descriptors = value::array(); + nmos::nc::find_members_by_role(resources, resource, role, match_whole_string, case_sensitive, recurse, descriptors.as_array()); - slog::log(gate, SLOG_FLF) << "Find members with given class id: " << "class_id: " << nmos::details::make_nc_class_id(class_id).serialize(); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptors); + } - if (class_id.empty()) + // Finds members with given class id + web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - // empty class_id - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty classId to do FindMembersByClassId")); - } + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... + using web::json::value; - auto descriptors = value::array(); - nmos::find_members_by_class_id(resources, resource, class_id, include_derived, recurse, descriptors.as_array()); + const auto class_id = details::parse_class_id(nmos::fields::nc::class_id(arguments)); // Class id to search for + const auto& include_derived = nmos::fields::nc::include_derived(arguments); // If TRUE it will also include derived class descriptors + const auto& recurse = nmos::fields::nc::recurse(arguments); // TRUE to search nested blocks - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptors); - } + slog::log(gate, SLOG_FLF) << "Find members with given class id: " << "class_id: " << details::make_class_id(class_id).serialize(); - // NcClassManager methods implementation - // Get a single class descriptor - web::json::value get_control_class(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - using web::json::value; + if (class_id.empty()) + { + // empty class_id + return details::make_method_result_error({nc_method_status::parameter_error}, U("empty classId to do FindMembersByClassId")); + } - const auto class_id = details::parse_nc_class_id(nmos::fields::nc::class_id(arguments)); // Class id to search for - const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - slog::log(gate, SLOG_FLF) << "Get a single class descriptor: " << "class_id: " << nmos::details::make_nc_class_id(class_id).serialize(); + auto descriptors = value::array(); + nmos::nc::find_members_by_class_id(resources, resource, class_id, include_derived, recurse, descriptors.as_array()); - if (class_id.empty()) - { - // empty class_id - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty classId to do GetControlClass")); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptors); } - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - - const auto& control_class = get_control_protocol_class_descriptor(class_id); - if (!control_class.class_id.empty()) + // NcClassManager methods implementation + // Get a single class descriptor + web::json::value get_control_class(const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - auto& description = control_class.description; - auto& name = control_class.name; - auto& fixed_role = control_class.fixed_role; - auto property_descriptors = control_class.property_descriptors; - auto method_descriptors = value::array(); - for (const auto& method_descriptor : control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } - auto event_descriptors = control_class.event_descriptors; - - if (include_inherited) + using web::json::value; + + const auto class_id = details::parse_class_id(nmos::fields::nc::class_id(arguments)); // Class id to search for + const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements + + slog::log(gate, SLOG_FLF) << "Get a single class descriptor: " << "class_id: " << details::make_class_id(class_id).serialize(); + + if (class_id.empty()) { - auto inherited_class_id = class_id; - inherited_class_id.pop_back(); + // empty class_id + return details::make_method_result_error({nc_method_status::parameter_error}, U("empty classId to do GetControlClass")); + } + + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - while (!inherited_class_id.empty()) + const auto& control_class = get_control_protocol_class_descriptor(class_id); + if (!control_class.class_id.empty()) + { + auto& description = control_class.description; + auto& name = control_class.name; + auto& fixed_role = control_class.fixed_role; + auto property_descriptors = control_class.property_descriptors; + auto method_descriptors = value::array(); + for (const auto& method_descriptor : control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } + auto event_descriptors = control_class.event_descriptors; + + if (include_inherited) { - const auto& inherited_control_class = get_control_protocol_class_descriptor(inherited_class_id); + auto inherited_class_id = class_id; + inherited_class_id.pop_back(); + + while (!inherited_class_id.empty()) { - for (const auto& property_descriptor : inherited_control_class.property_descriptors.as_array()) { web::json::push_back(property_descriptors, property_descriptor); } - for (const auto& method_descriptor : inherited_control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } - for (const auto& event_descriptor : inherited_control_class.event_descriptors.as_array()) { web::json::push_back(event_descriptors, event_descriptor); } + const auto& inherited_control_class = get_control_protocol_class_descriptor(inherited_class_id); + { + for (const auto& property_descriptor : inherited_control_class.property_descriptors.as_array()) { web::json::push_back(property_descriptors, property_descriptor); } + for (const auto& method_descriptor : inherited_control_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } + for (const auto& event_descriptor : inherited_control_class.event_descriptors.as_array()) { web::json::push_back(event_descriptors, event_descriptor); } + } + inherited_class_id.pop_back(); } - inherited_class_id.pop_back(); } + const auto descriptor = fixed_role.is_null() + ? details::make_class_descriptor(description, class_id, name, property_descriptors, method_descriptors, event_descriptors) + : details::make_class_descriptor(description, class_id, name, fixed_role.as_string(), property_descriptors, method_descriptors, event_descriptors); + + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptor); } - const auto descriptor = fixed_role.is_null() - ? details::make_nc_class_descriptor(description, class_id, name, property_descriptors, method_descriptors, event_descriptors) - : details::make_nc_class_descriptor(description, class_id, name, fixed_role.as_string(), property_descriptors, method_descriptors, event_descriptors); - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); + return details::make_method_result_error({nc_method_status::parameter_error}, U("classId not found")); } - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("classId not found")); - } - - // Get a single datatype descriptor - web::json::value get_datatype(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, slog::base_gate& gate) - { - // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - - const auto& name = nmos::fields::nc::name(arguments); // name of datatype - const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements + // Get a single datatype descriptor + web::json::value get_datatype(const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, slog::base_gate& gate) + { + // note, model mutex is already locked by the outer function, so access to control_protocol_resources is OK... - slog::log(gate, SLOG_FLF) << "Get a single datatype descriptor: " << "name: " << name; + const auto& name = nmos::fields::nc::name(arguments); // name of datatype + const auto& include_inherited = nmos::fields::nc::include_inherited(arguments); // If set the descriptor would contain all inherited elements - if (name.empty()) - { - // empty name - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("empty name to do GetDatatype")); - } + slog::log(gate, SLOG_FLF) << "Get a single datatype descriptor: " << "name: " << name; - const auto& datatype = get_control_protocol_datatype_descriptor(name); - if (datatype.descriptor.size()) - { - auto descriptor = datatype.descriptor; + if (name.empty()) + { + // empty name + return details::make_method_result_error({nc_method_status::parameter_error}, U("empty name to do GetDatatype")); + } - if (include_inherited) + const auto& datatype = get_control_protocol_datatype_descriptor(name); + if (datatype.descriptor.size()) { - const auto& type = nmos::fields::nc::type(descriptor); - if (nc_datatype_type::Struct == type) - { - auto descriptor_ = descriptor; + auto descriptor = datatype.descriptor; - for (;;) + if (include_inherited) + { + const auto& type = nmos::fields::nc::type(descriptor); + if (nc_datatype_type::Struct == type) { - const auto& parent_type = descriptor_.at(nmos::fields::nc::parent_type); - if (!parent_type.is_null()) + auto descriptor_ = descriptor; + + for (;;) { - const auto& parent_datatype = get_control_protocol_datatype_descriptor(parent_type.as_string()); - if (parent_datatype.descriptor.size()) + const auto& parent_type = descriptor_.at(nmos::fields::nc::parent_type); + if (!parent_type.is_null()) { - descriptor_ = parent_datatype.descriptor; - - const auto& fields = nmos::fields::nc::fields(descriptor_); - for (const auto& field : fields) + const auto& parent_datatype = get_control_protocol_datatype_descriptor(parent_type.as_string()); + if (parent_datatype.descriptor.size()) { - web::json::push_back(descriptor.at(nmos::fields::nc::fields), field); + descriptor_ = parent_datatype.descriptor; + + const auto& fields = nmos::fields::nc::fields(descriptor_); + for (const auto& field : fields) + { + web::json::push_back(descriptor.at(nmos::fields::nc::fields), field); + } } } - } - else - { - break; + else + { + break; + } } } } + + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, descriptor); } - return details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, descriptor); + return details::make_method_result_error({nc_method_status::parameter_error}, U("name not found")); } - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, U("name not found")); - } - - // NcReceiverMonitor methods implementation - namespace details - { - web::json::value get_packet_counters(bool is_deprecated, get_packet_counters_handler get_packet_counters) + // NcReceiverMonitor methods implementation + namespace details { - using web::json::value; - using web::json::value_from_elements; - - if (get_packet_counters) + web::json::value get_packet_counters(bool is_deprecated, get_packet_counters_handler get_packet_counters) { - const auto counters = get_packet_counters(); - auto nc_counter_sequence = value_from_elements(counters | boost::adaptors::transformed([](const nc::counter& counter) + using web::json::value; + using web::json::value_from_elements; + + if (get_packet_counters) { - return web::json::value_of({ - { nmos::fields::nc::name, value::string(counter.name) }, - { nmos::fields::nc::value, value::number(counter.value) }, - { nmos::fields::nc::description, value::string(counter.description) } - }); - })); + const auto counters = get_packet_counters(); + auto nc_counter_sequence = value_from_elements(counters | boost::adaptors::transformed([](const nc::counter& counter) + { + return web::json::value_of({ + {nmos::fields::nc::name, value::string(counter.name)}, + {nmos::fields::nc::value, value::number(counter.value)}, + {nmos::fields::nc::description, value::string(counter.description)} + }); + })); + + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}, nc_counter_sequence); + } - return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }, nc_counter_sequence); + return details::make_method_result_error({nmos::nc_method_status::method_not_implemented}, U("not implemented")); } - - return nmos::details::make_nc_method_result_error({ nmos::nc_method_status::method_not_implemented }, U("not implemented")); } - } - // Gets the lost packet counters - web::json::value get_lost_packet_counters(nmos::resources& /*resources*/, const nmos::resource& /*resource*/, const web::json::value& /*arguments*/, bool is_deprecated, get_packet_counters_handler get_lost_packet_counters, slog::base_gate& gate) - { - slog::log(gate, SLOG_FLF) << "Gets the lost packet counters"; + // Gets the lost packet counters + web::json::value get_lost_packet_counters(nmos::resources& /*resources*/, const nmos::resource& /*resource*/, const web::json::value& /*arguments*/, bool is_deprecated, get_packet_counters_handler get_lost_packet_counters, slog::base_gate& gate) + { + slog::log(gate, SLOG_FLF) << "Gets the lost packet counters"; - return details::get_packet_counters(is_deprecated, get_lost_packet_counters); - } + return details::get_packet_counters(is_deprecated, get_lost_packet_counters); + } - // Gets the late packet counters - web::json::value get_late_packet_counters(nmos::resources& /*resources*/, const nmos::resource& /*resource*/, const web::json::value& /*arguments*/, bool is_deprecated, get_packet_counters_handler get_late_packet_counters, slog::base_gate& gate) - { - slog::log(gate, SLOG_FLF) << "Gets the late packet counters"; + // Gets the late packet counters + web::json::value get_late_packet_counters(nmos::resources& /*resources*/, const nmos::resource& /*resource*/, const web::json::value& /*arguments*/, bool is_deprecated, get_packet_counters_handler get_late_packet_counters, slog::base_gate& gate) + { + slog::log(gate, SLOG_FLF) << "Gets the late packet counters"; - return details::get_packet_counters(is_deprecated, get_late_packet_counters); - } + return details::get_packet_counters(is_deprecated, get_late_packet_counters); + } - // Resets the packet counters and messages - web::json::value reset_monitor(nmos::resources& resources, const nmos::resource& resource, const web::json::value&, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, reset_monitor_handler reset_monitor, slog::base_gate& gate) - { - slog::log(gate, SLOG_FLF) << "Resets the packet counters"; - - const std::vector> receiver_property_values = { - std::pair(nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_receiver_monitor_connection_status_message_property_id, web::json::value::null()), - std::pair(nc_receiver_monitor_external_synchronization_status_message_property_id, web::json::value::null()), - std::pair(nc_receiver_monitor_link_status_message_property_id, web::json::value::null()), - std::pair(nc_receiver_monitor_stream_status_message_property_id, web::json::value::null()), - std::pair(nc_status_monitor_overall_status_message_property_id, web::json::value::null()), - }; - - const std::vector> sender_property_values = { - std::pair(nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(0)), - std::pair(nc_sender_monitor_transmission_status_message_property_id, web::json::value::null()), - std::pair(nc_sender_monitor_external_synchronization_status_message_property_id, web::json::value::null()), - std::pair(nc_sender_monitor_link_status_message_property_id, web::json::value::null()), - std::pair(nc_sender_monitor_essence_status_message_property_id, web::json::value::null()), - std::pair(nc_status_monitor_overall_status_message_property_id, web::json::value::null()), - }; - - const auto& class_id = details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)); - - // reset all counters - const std::vector> property_values = nmos::is_nc_sender_monitor(class_id) ? sender_property_values : receiver_property_values; - - for (const auto& property_value : property_values) + // Resets the packet counters and messages + web::json::value reset_monitor(nmos::resources& resources, const nmos::resource& resource, const web::json::value&, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, reset_monitor_handler reset_monitor, slog::base_gate& gate) { - const auto& property = find_property_descriptor(property_value.first, details::parse_nc_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); - if (!property.is_null()) + slog::log(gate, SLOG_FLF) << "Resets the packet counters"; + + const std::vector> receiver_property_values = { + std::pair(nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_receiver_monitor_connection_status_message_property_id, web::json::value::null()), + std::pair(nc_receiver_monitor_external_synchronization_status_message_property_id, web::json::value::null()), + std::pair(nc_receiver_monitor_link_status_message_property_id, web::json::value::null()), + std::pair(nc_receiver_monitor_stream_status_message_property_id, web::json::value::null()), + std::pair(nc_status_monitor_overall_status_message_property_id, web::json::value::null()), + }; + + const std::vector> sender_property_values = { + std::pair(nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(0)), + std::pair(nc_sender_monitor_transmission_status_message_property_id, web::json::value::null()), + std::pair(nc_sender_monitor_external_synchronization_status_message_property_id, web::json::value::null()), + std::pair(nc_sender_monitor_link_status_message_property_id, web::json::value::null()), + std::pair(nc_sender_monitor_essence_status_message_property_id, web::json::value::null()), + std::pair(nc_status_monitor_overall_status_message_property_id, web::json::value::null()), + }; + + const auto& class_id = details::parse_class_id(nmos::fields::nc::class_id(resource.data)); + + // reset all counters + const std::vector> property_values = nmos::nc::is_sender_monitor(class_id) ? sender_property_values : receiver_property_values; + + for (const auto& property_value : property_values) { - try + const auto& property = nc::find_property_descriptor(property_value.first, details::parse_class_id(nmos::fields::nc::class_id(resource.data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - // update property - modify_control_protocol_resource(resources, resource.id, [&](nmos::resource& resource) + try { - resource.data[nmos::fields::nc::name(property)] = property_value.second; - - // do notification that the specified property has changed - if (property_changed) + // update property + nc::modify_resource(resources, resource.id, [&](nmos::resource& resource) { - property_changed(resource, nmos::fields::nc::name(property), -1); - } + resource.data[nmos::fields::nc::name(property)] = property_value.second; - }, make_property_changed_event(nmos::fields::nc::oid(resource.data), { { property_value.first, nc_property_change_type::type::value_changed, property_value.second } })); - } - catch (const nmos::control_protocol_exception& e) - { - utility::ostringstream_t ss; - ss << "Reset counters: " << details::make_nc_property_id(property_value.first).serialize() << " error: " << e.what(); - slog::log(gate, SLOG_FLF) << ss.str(); - return details::make_nc_method_result_error({ nc_method_status::parameter_error }, ss.str()); + // do notification that the specified property has changed + if (property_changed) + { + property_changed(resource, nmos::fields::nc::name(property), -1); + } + + }, make_property_changed_event(nmos::fields::nc::oid(resource.data), {{property_value.first, nc_property_change_type::type::value_changed, property_value.second}})); + } + catch (const nmos::control_protocol_exception& e) + { + utility::ostringstream_t ss; + ss << "Reset counters: " << details::make_property_id(property_value.first).serialize() << " error: " << e.what(); + slog::log(gate, SLOG_FLF) << ss.str(); + return details::make_method_result_error({nc_method_status::parameter_error}, ss.str()); + } } } - } - if (reset_monitor) - { - reset_monitor(); - } + if (reset_monitor) + { + reset_monitor(); + } - return nmos::details::make_nc_method_result({ is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok }); + return details::make_method_result({is_deprecated ? nmos::nc_method_status::method_deprecated : nc_method_status::ok}); + } } } diff --git a/Development/nmos/control_protocol_methods.h b/Development/nmos/control_protocol_methods.h index e4a87e824..5f0e51d15 100644 --- a/Development/nmos/control_protocol_methods.h +++ b/Development/nmos/control_protocol_methods.h @@ -11,45 +11,48 @@ namespace slog namespace nmos { - // NcObject methods implementation - // Get property value - web::json::value get(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set property value - web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); - // Get sequence item - web::json::value get_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set sequence item - web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); - // Add item to sequence - web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); - // Delete sequence item - web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); - // Get sequence length - web::json::value get_sequence_length(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + namespace nc + { + // NcObject methods implementation + // Get property value + web::json::value get(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set property value + web::json::value set(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + // Get sequence item + web::json::value get_sequence_item(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set sequence item + web::json::value set_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + // Add item to sequence + web::json::value add_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + // Delete sequence item + web::json::value remove_sequence_item(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, slog::base_gate& gate); + // Get sequence length + web::json::value get_sequence_length(const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // NcBlock methods implementation - // Get descriptors of members of the block - web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); - // Finds member(s) by path - web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); - // Finds members with given role name or fragment - web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); - // Finds members with given class id - web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); + // NcBlock methods implementation + // Get descriptors of members of the block + web::json::value get_member_descriptors(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); + // Finds member(s) by path + web::json::value find_members_by_path(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); + // Finds members with given role name or fragment + web::json::value find_members_by_role(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); + // Finds members with given class id + web::json::value find_members_by_class_id(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate); - // NcClassManager methods implementation - // Get a single class descriptor - web::json::value get_control_class(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Get a single datatype descriptor - web::json::value get_datatype(nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype, slog::base_gate& gate); + // NcClassManager methods implementation + // Get a single class descriptor + web::json::value get_control_class(const web::json::value& arguments, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Get a single datatype descriptor + web::json::value get_datatype(const web::json::value& arguments, bool is_deprecated, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype, slog::base_gate& gate); - // NcReceiverMonitor methods implementation - // Gets the lost packet counters - web::json::value get_lost_packet_counters(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_packet_counters_handler get_lost_packet_counters, slog::base_gate& gate); - // Gets the last packet counters - web::json::value get_late_packet_counters(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_packet_counters_handler get_last_packet_counters, slog::base_gate& gate); - // Resets the packet counters and messages - web::json::value reset_monitor(nmos::resources& resources, const nmos::resource& resource, const web::json::value&, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, reset_monitor_handler reset_monitor, slog::base_gate& gate); + // NcReceiverMonitor method implementation + // Gets the last packet counters + web::json::value get_late_packet_counters(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_packet_counters_handler get_last_packet_counters, slog::base_gate& gate); + // NcReceiverMonitor & NcSenderMonitor methods implementation + // Gets the lost packet counters + web::json::value get_lost_packet_counters(nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, get_packet_counters_handler get_lost_packet_counters, slog::base_gate& gate); + // Resets the packet counters and messages + web::json::value reset_monitor(nmos::resources& resources, const nmos::resource& resource, const web::json::value&, bool is_deprecated, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, reset_monitor_handler reset_monitor, slog::base_gate& gate); + } } - #endif diff --git a/Development/nmos/control_protocol_nmos_resource_type.h b/Development/nmos/control_protocol_nmos_resource_type.h index 436b72257..b6c4aa16c 100644 --- a/Development/nmos/control_protocol_nmos_resource_type.h +++ b/Development/nmos/control_protocol_nmos_resource_type.h @@ -8,15 +8,15 @@ namespace nmos { // resourceType // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresourcenmos - DEFINE_STRING_ENUM(ncp_nmos_resource_type) - namespace ncp_nmos_resource_types + DEFINE_STRING_ENUM(ncp_touchpoint_resource_type) + namespace ncp_touchpoint_resource_types { - const ncp_nmos_resource_type node{ U("node") }; - const ncp_nmos_resource_type device{ U("device") }; - const ncp_nmos_resource_type source{ U("source") }; - const ncp_nmos_resource_type flow{ U("flow") }; - const ncp_nmos_resource_type sender{ U("sender") }; - const ncp_nmos_resource_type receiver{ U("receiver") }; + const ncp_touchpoint_resource_type node{ U("node") }; + const ncp_touchpoint_resource_type device{ U("device") }; + const ncp_touchpoint_resource_type source{ U("source") }; + const ncp_touchpoint_resource_type flow{ U("flow") }; + const ncp_touchpoint_resource_type sender{ U("sender") }; + const ncp_touchpoint_resource_type receiver{ U("receiver") }; } } diff --git a/Development/nmos/control_protocol_resource.cpp b/Development/nmos/control_protocol_resource.cpp index 12bd2ff7b..a58a8826b 100644 --- a/Development/nmos/control_protocol_resource.cpp +++ b/Development/nmos/control_protocol_resource.cpp @@ -6,2270 +6,2538 @@ namespace nmos { - namespace details + namespace nc { - web::json::value make_nc_method_result(const nc_method_result& method_result) + namespace details { - using web::json::value_of; + web::json::value make_method_result(const nc_method_result& method_result) + { + using web::json::value_of; - return value_of({ - { nmos::fields::nc::status, method_result.status } - }); - } + return value_of({ + { nmos::fields::nc::status, method_result.status } + }); + } - web::json::value make_nc_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message) - { - auto result = make_nc_method_result(method_result); - if (!error_message.empty()) { result[nmos::fields::nc::error_message] = web::json::value::string(error_message); } - return result; - } + web::json::value make_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message) + { + auto result = make_method_result(method_result); + if (!error_message.empty()) { result[nmos::fields::nc::error_message] = web::json::value::string(error_message); } + return result; + } - web::json::value make_nc_method_result(const nc_method_result& method_result, const web::json::value& value) - { - auto result = make_nc_method_result(method_result); - result[nmos::fields::nc::value] = value; - return result; - } + web::json::value make_method_result(const nc_method_result& method_result, const web::json::value& value) + { + auto result = make_method_result(method_result); + result[nmos::fields::nc::value] = value; + return result; + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid - web::json::value make_nc_element_id(uint16_t level, uint16_t index) - { - using web::json::value_of; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid + web::json::value make_element_id(uint16_t level, uint16_t index) + { + using web::json::value_of; - return value_of({ - { nmos::fields::nc::level, level }, - { nmos::fields::nc::index, index } - }); - } - web::json::value make_nc_element_id(const nc_element_id& id) - { - return make_nc_element_id(id.level, id.index); - } - nc_element_id parse_nc_element_id(const web::json::value& id) - { - return { uint16_t(nmos::fields::nc::level(id)), uint16_t(nmos::fields::nc::index(id)) }; - } + return value_of({ + { nmos::fields::nc::level, level }, + { nmos::fields::nc::index, index } + }); + } + web::json::value make_element_id(const nc_element_id& id) + { + return make_element_id(id.level, id.index); + } + nc_element_id parse_element_id(const web::json::value& id) + { + return { uint16_t(nmos::fields::nc::level(id)), uint16_t(nmos::fields::nc::index(id)) }; + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventid - web::json::value make_nc_event_id(const nc_event_id& id) - { - return make_nc_element_id(id); - } - nc_event_id parse_nc_event_id(const web::json::value& id) - { - return parse_nc_element_id(id); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventid + web::json::value make_event_id(const nc_event_id& id) + { + return make_element_id(id); + } + nc_event_id parse_event_id(const web::json::value& id) + { + return parse_element_id(id); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodid - web::json::value make_nc_method_id(const nc_method_id& id) - { - return make_nc_element_id(id); - } - nc_method_id parse_nc_method_id(const web::json::value& id) - { - return parse_nc_element_id(id); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodid + web::json::value make_method_id(const nc_method_id& id) + { + return make_element_id(id); + } + nc_method_id parse_method_id(const web::json::value& id) + { + return parse_element_id(id); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyid - web::json::value make_nc_property_id(const nc_property_id& id) - { - return make_nc_element_id(id); - } - nc_property_id parse_nc_property_id(const web::json::value& id) - { - return parse_nc_element_id(id); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyid + web::json::value make_property_id(const nc_property_id& id) + { + return make_element_id(id); + } + nc_property_id parse_property_id(const web::json::value& id) + { + return parse_element_id(id); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassid - web::json::value make_nc_class_id(const nc_class_id& class_id) - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassid + web::json::value make_class_id(const nc_class_id& class_id) + { + using web::json::value; - auto nc_class_id = value::array(); - for (const auto class_id_item : class_id) { web::json::push_back(nc_class_id, class_id_item); } - return nc_class_id; - } - nc_class_id parse_nc_class_id(const web::json::array& class_id_) - { - nc_class_id class_id; - for (auto& element : class_id_) + auto nc_class_id = value::array(); + for (const auto class_id_item : class_id) { web::json::push_back(nc_class_id, class_id_item); } + return nc_class_id; + } + nc_class_id parse_class_id(const web::json::array& class_id_) { - class_id.push_back(element.as_integer()); + nc_class_id class_id; + for (auto& element : class_id_) + { + class_id.push_back(element.as_integer()); + } + return class_id; } - return class_id; - } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanufacturer - web::json::value make_nc_manufacturer(const utility::string_t& name, const web::json::value& organization_id, const web::json::value& website) - { - using web::json::value_of; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanufacturer + web::json::value make_manufacturer(const utility::string_t& name, const web::json::value& organization_id, const web::json::value& website) + { + using web::json::value_of; - return value_of({ - { nmos::fields::nc::name, name }, - { nmos::fields::nc::organization_id, organization_id }, - { nmos::fields::nc::website, website } - }); - } - web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id, const web::uri& website) - { - using web::json::value; + return value_of({ + { nmos::fields::nc::name, name }, + { nmos::fields::nc::organization_id, organization_id }, + { nmos::fields::nc::website, website } + }); + } + web::json::value make_manufacturer(const utility::string_t& name, nc_organization_id organization_id, const web::uri& website) + { + using web::json::value; - return make_nc_manufacturer(name, organization_id, value::string(website.to_string())); - } - web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id) - { - using web::json::value; + return make_manufacturer(name, organization_id, value::string(website.to_string())); + } + web::json::value make_manufacturer(const utility::string_t& name, nc_organization_id organization_id) + { + using web::json::value; - return make_nc_manufacturer(name, organization_id, value::null()); - } - web::json::value make_nc_manufacturer(const utility::string_t& name) - { - using web::json::value; + return make_manufacturer(name, organization_id, value::null()); + } + web::json::value make_manufacturer(const utility::string_t& name) + { + using web::json::value; - return make_nc_manufacturer(name, value::null(), value::null()); - } + return make_manufacturer(name, value::null(), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncproduct - // brand_name can be null - // uuid can be null - // description can be null - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const web::json::value& brand_name, const web::json::value& uuid, const web::json::value& description) - { - using web::json::value_of; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncproduct + // brand_name can be null + // uuid can be null + // description can be null + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const web::json::value& brand_name, const web::json::value& uuid, const web::json::value& description) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::name, name }, + { nmos::fields::nc::key, key }, + { nmos::fields::nc::revision_level, revision_level }, + { nmos::fields::nc::brand_name, brand_name }, + { nmos::fields::nc::uuid, uuid }, + { nmos::fields::nc::description, description } + }); + } + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid, const utility::string_t& description) + { + using web::json::value; - return value_of({ - { nmos::fields::nc::name, name }, - { nmos::fields::nc::key, key }, - { nmos::fields::nc::revision_level, revision_level }, - { nmos::fields::nc::brand_name, brand_name }, - { nmos::fields::nc::uuid, uuid }, - { nmos::fields::nc::description, description } - }); - } - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name, const nc_uuid& uuid, const utility::string_t& description) - { - using web::json::value; + return make_product(name, key, revision_level, value::string(brand_name), value::string(uuid), value::string(description)); + } + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid) + { + using web::json::value; - return make_nc_product(name, key, revision_level, value::string(brand_name), value::string(uuid), value::string(description)); - } - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name, const nc_uuid& uuid) - { - using web::json::value; + return make_product(name, key, revision_level, value::string(brand_name), value::string(uuid), value::null()); + } + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name) + { + using web::json::value; - return make_nc_product(name, key, revision_level, value::string(brand_name), value::string(uuid), value::null()); - } - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name) - { - using web::json::value; + return make_product(name, key, revision_level, value::string(brand_name), value::null(), value::null()); + } + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level) + { + using web::json::value; - return make_nc_product(name, key, revision_level, value::string(brand_name), value::null(), value::null()); - } - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level) - { - using web::json::value; + return make_product(name, key, revision_level, value::null(), value::null(), value::null()); + } - return make_nc_product(name, key, revision_level, value::null(), value::null(), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdeviceoperationalstate + // device_specific_details can be null + web::json::value make_device_operational_state(nc_device_generic_state::state generic_state, const web::json::value& device_specific_details) + { + using web::json::value_of; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdeviceoperationalstate - // device_specific_details can be null - web::json::value make_nc_device_operational_state(nc_device_generic_state::state generic_state, const web::json::value& device_specific_details) - { - using web::json::value_of; + return value_of({ + { nmos::fields::nc::generic_state, generic_state }, + { nmos::fields::nc::device_specific_details, device_specific_details } + }); + } - return value_of({ - { nmos::fields::nc::generic_state, generic_state }, - { nmos::fields::nc::device_specific_details, device_specific_details } - }); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdescriptor + // description can be null + web::json::value make_descriptor(const web::json::value& description) + { + using web::json::value_of; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdescriptor - // description can be null - web::json::value make_nc_descriptor(const web::json::value& description) - { - using web::json::value_of; + return value_of({ { nmos::fields::nc::description, description } }); + } - return value_of({ { nmos::fields::nc::description, description } }); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblockmemberdescriptor + // description can be null + // user_label can be null + web::json::value make_block_member_descriptor(const web::json::value& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const web::json::value& user_label, nc_oid owner) + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblockmemberdescriptor - // description can be null - // user_label can be null - web::json::value make_nc_block_member_descriptor(const web::json::value& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const web::json::value& user_label, nc_oid owner) - { - using web::json::value; + auto data = make_descriptor(description); + data[nmos::fields::nc::role] = value::string(role); + data[nmos::fields::nc::oid] = oid; + data[nmos::fields::nc::constant_oid] = value::boolean(constant_oid); + data[nmos::fields::nc::class_id] = make_class_id(class_id); + data[nmos::fields::nc::user_label] = user_label; + data[nmos::fields::nc::owner] = owner; - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::role] = value::string(role); - data[nmos::fields::nc::oid] = oid; - data[nmos::fields::nc::constant_oid] = value::boolean(constant_oid); - data[nmos::fields::nc::class_id] = make_nc_class_id(class_id); - data[nmos::fields::nc::user_label] = user_label; - data[nmos::fields::nc::owner] = owner; + return data; + } + web::json::value make_block_member_descriptor(const utility::string_t& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const utility::string_t& user_label, nc_oid owner) + { + using web::json::value; - return data; - } - web::json::value make_nc_block_member_descriptor(const utility::string_t& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const utility::string_t& user_label, nc_oid owner) - { - using web::json::value; + return make_block_member_descriptor(value::string(description), role, oid, constant_oid, class_id, value::string(user_label), owner); + } - return make_nc_block_member_descriptor(value::string(description), role, oid, constant_oid, class_id, value::string(user_label), owner); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassdescriptor + // description can be null + // fixedRole can be null + web::json::value make_class_descriptor(const web::json::value& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassdescriptor - // description can be null - // fixedRole can be null - web::json::value make_nc_class_descriptor(const web::json::value& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) - { - using web::json::value; + auto data = make_descriptor(description); + data[nmos::fields::nc::class_id] = make_class_id(class_id); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::fixed_role] = fixed_role; + data[nmos::fields::nc::properties] = properties; + data[nmos::fields::nc::methods] = methods; + data[nmos::fields::nc::events] = events; - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::class_id] = make_nc_class_id(class_id); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::fixed_role] = fixed_role; - data[nmos::fields::nc::properties] = properties; - data[nmos::fields::nc::methods] = methods; - data[nmos::fields::nc::events] = events; + return data; + } + web::json::value make_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) + { + using web::json::value; - return data; - } - web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) - { - using web::json::value; + return make_class_descriptor(value::string(description), class_id, name, value::string(fixed_role), properties, methods, events); + } + web::json::value make_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) + { + using web::json::value; - return make_nc_class_descriptor(value::string(description), class_id, name, value::string(fixed_role), properties, methods, events); - } - web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) - { - using web::json::value; + return make_class_descriptor(value::string(description), class_id, name, value::null(), properties, methods, events); + } - return make_nc_class_descriptor(value::string(description), class_id, name, value::null(), properties, methods, events); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncenumitemdescriptor + // description can be null + web::json::value make_enum_item_descriptor(const web::json::value& description, const nc_name& name, uint16_t val) + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncenumitemdescriptor - // description can be null - web::json::value make_nc_enum_item_descriptor(const web::json::value& description, const nc_name& name, uint16_t val) - { - using web::json::value; + auto data = make_descriptor(description); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::value] = val; - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::value] = val; + return data; + } + web::json::value make_enum_item_descriptor(const utility::string_t& description, const nc_name& name, uint16_t val) + { + using web::json::value; - return data; - } - web::json::value make_nc_enum_item_descriptor(const utility::string_t& description, const nc_name& name, uint16_t val) - { - using web::json::value; + return make_enum_item_descriptor(value::string(description), name, val); + } - return make_nc_enum_item_descriptor(value::string(description), name, val); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventdescriptor + // description can be null + // id = make_event_id(level, index) + web::json::value make_event_descriptor(const web::json::value& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventdescriptor - // description can be null - // id = make_nc_event_id(level, index) - web::json::value make_nc_event_descriptor(const web::json::value& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) - { - using web::json::value; + auto data = make_descriptor(description); + data[nmos::fields::nc::id] = make_event_id(id); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::event_datatype] = value::string(event_datatype); + data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); + + return data; + } + web::json::value make_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) + { + using web::json::value; + + return make_event_descriptor(value::string(description), id, name, event_datatype, is_deprecated); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncfielddescriptor + // description can be null + // type_name can be null + // constraints can be null + web::json::value make_field_descriptor(const web::json::value& description, const nc_name& name, const web::json::value& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + auto data = make_descriptor(description); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::type_name] = type_name; + data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); + data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); + data[nmos::fields::nc::constraints] = constraints; + + return data; + } + web::json::value make_field_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + return make_field_descriptor(value::string(description), name, value::string(type_name), is_nullable, is_sequence, constraints); + } + web::json::value make_field_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + return make_field_descriptor(value::string(description), name, value::null(), is_nullable, is_sequence, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethoddescriptor + // description can be null + // id = make_method_id(level, index) + // sequence parameters + web::json::value make_method_descriptor(const web::json::value& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated) + { + using web::json::value; + + auto data = make_descriptor(description); + data[nmos::fields::nc::id] = make_method_id(id); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::result_datatype] = value::string(result_datatype); + data[nmos::fields::nc::parameters] = parameters; + data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); + + return data; + } + web::json::value make_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated) + { + using web::json::value; + + return make_method_descriptor(value::string(description), id, name, result_datatype, parameters, is_deprecated); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterdescriptor + // description can be null + // type_name can be null + web::json::value make_parameter_descriptor(const web::json::value& description, const nc_name& name, const web::json::value& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + auto data = make_descriptor(description); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::type_name] = type_name; + data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); + data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); + data[nmos::fields::nc::constraints] = constraints; + + return data; + } + web::json::value make_parameter_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + return make_parameter_descriptor(value::string(description), name, value::null(), is_nullable, is_sequence, constraints); + } + web::json::value make_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) + { + using web::json::value; + + return make_parameter_descriptor(value::string(description), name, value::string(type_name), is_nullable, is_sequence, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertydescriptor + // description can be null + // constraints can be null + web::json::value make_property_descriptor(const web::json::value& description, const nc_property_id& id, const nc_name& name, const web::json::value& type_name, + bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) + { + using web::json::value; + + auto data = make_descriptor(description); + data[nmos::fields::nc::id] = make_property_id(id); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::type_name] = type_name; + data[nmos::fields::nc::is_read_only] = value::boolean(is_read_only); + data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); + data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); + data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); + data[nmos::fields::nc::constraints] = constraints; + + return data; + } + web::json::value make_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, + bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) + { + using web::json::value; + + return nmos::nc::details::make_property_descriptor(value::string(description), id, name, value::string(type_name), is_read_only, is_nullable, is_sequence, is_deprecated, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptor + // description can be null + // constraints can be null + web::json::value make_datatype_descriptor(const web::json::value& description, const nc_name& name, nc_datatype_type::type type, const web::json::value& constraints) + { + using web::json::value; + + auto data = make_descriptor(description); + data[nmos::fields::nc::name] = value::string(name); + data[nmos::fields::nc::type] = type; + data[nmos::fields::nc::constraints] = constraints; + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorenum + // description can be null + // constraints can be null + // items: sequence + web::json::value make_datatype_descriptor_enum(const web::json::value& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints) + { + auto data = make_datatype_descriptor(description, name, nc_datatype_type::Enum, constraints); + data[nmos::fields::nc::items] = items; + + return data; + } + web::json::value make_datatype_descriptor_enum(const utility::string_t& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints) + { + using web::json::value; + + return make_datatype_descriptor_enum(value::string(description), name, items, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorprimitive + // description can be null + // constraints can be null + web::json::value make_datatype_descriptor_primitive(const web::json::value& description, const nc_name& name, const web::json::value& constraints) + { + return make_datatype_descriptor(description, name, nc_datatype_type::Primitive, constraints); + } + web::json::value make_datatype_descriptor_primitive(const utility::string_t& description, const nc_name& name, const web::json::value& constraints) + { + using web::json::value; + + return make_datatype_descriptor_primitive(value::string(description), name, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorstruct + // description can be null + // constraints can be null + // fields: sequence + // parent_type can be null + web::json::value make_datatype_descriptor_struct(const web::json::value& description, const nc_name& name, const web::json::value& fields, const web::json::value& parent_type, const web::json::value& constraints) + { + auto data = make_datatype_descriptor(description, name, nc_datatype_type::Struct, constraints); + data[nmos::fields::nc::fields] = fields; + data[nmos::fields::nc::parent_type] = parent_type; + + return data; + } + web::json::value make_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const utility::string_t& parent_type, const web::json::value& constraints) + { + using web::json::value; + + return make_datatype_descriptor_struct(value::string(description), name, fields, value::string(parent_type), constraints); + } + web::json::value make_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const web::json::value& constraints) + { + using web::json::value; + + return make_datatype_descriptor_struct(value::string(description), name, fields, value::null(), constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptortypedef + // description can be null + // constraints can be null + web::json::value make_datatype_typedef(const web::json::value& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints) + { + using web::json::value; + + auto data = make_datatype_descriptor(description, name, nc_datatype_type::Typedef, constraints); + data[nmos::fields::nc::parent_type] = value::string(parent_type); + data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); + + return data; + } + web::json::value make_datatype_typedef(const utility::string_t& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints) + { + using web::json::value; + + return make_datatype_typedef(value::string(description), name, is_sequence, parent_type, constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraints + web::json::value make_property_constraints(const nc_property_id& property_id, const web::json::value& default_value) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::property_id, make_property_id(property_id) }, + { nmos::fields::nc::default_value, default_value } + }); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsnumber + web::json::value make_property_constraints_number(const nc_property_id& property_id, const web::json::value& default_value, const web::json::value& minimum, const web::json::value& maximum, const web::json::value& step) + { + using web::json::value; + + auto data = make_property_constraints(property_id, default_value); + data[nmos::fields::nc::minimum] = minimum; + data[nmos::fields::nc::maximum] = maximum; + data[nmos::fields::nc::step] = step; + + return data; + } + web::json::value make_property_constraints_number(const nc_property_id& property_id, uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) + { + using web::json::value; + + return make_property_constraints_number(property_id, value(default_value), value(minimum), value(maximum), value(step)); + } + web::json::value make_property_constraints_number(const nc_property_id& property_id, uint64_t minimum, uint64_t maximum, uint64_t step) + { + using web::json::value; + + return make_property_constraints_number(property_id, value::null(), minimum, maximum, step); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsstring + web::json::value make_property_constraints_string(const nc_property_id& property_id, const web::json::value& default_value, const web::json::value& max_characters, const web::json::value& pattern) + { + using web::json::value; + + auto data = make_property_constraints(property_id, default_value); + data[nmos::fields::nc::max_characters] = max_characters; + data[nmos::fields::nc::pattern] = pattern; + + return data; + } + web::json::value make_property_constraints_string(const nc_property_id& property_id, const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) + { + using web::json::value; + + return make_property_constraints_string(property_id, value::string(default_value), max_characters, value::string(pattern)); + } + web::json::value make_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters, const nc_regex& pattern) + { + using web::json::value; + + return make_property_constraints_string(property_id, value::null(), max_characters, value::string(pattern)); + } + web::json::value make_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters) + { + using web::json::value; + + return make_property_constraints_string(property_id, value::null(), max_characters, value::null()); + } + web::json::value make_property_constraints_string(const nc_property_id& property_id, const nc_regex& pattern) + { + using web::json::value; + + return make_property_constraints_string(property_id, value::null(), value::null(), value::string(pattern)); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraints + web::json::value make_parameter_constraints(const web::json::value& default_value) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::default_value, default_value } + }); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber + web::json::value make_parameter_constraints_number(const web::json::value& default_value, const web::json::value& minimum, const web::json::value& maximum, const web::json::value& step) + { + using web::json::value; + + auto data = make_parameter_constraints(default_value); + data[nmos::fields::nc::minimum] = minimum; + data[nmos::fields::nc::maximum] = maximum; + data[nmos::fields::nc::step] = step; + + return data; + } + web::json::value make_parameter_constraints_number(uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) + { + using web::json::value; + + return make_parameter_constraints_number(value(default_value), value(minimum), value(maximum), value(step)); + } + web::json::value make_parameter_constraints_number(uint64_t minimum, uint64_t maximum, uint64_t step) + { + using web::json::value; + + return make_parameter_constraints_number(value::null(), minimum, maximum, step); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring + web::json::value make_parameter_constraints_string(const web::json::value& default_value, const web::json::value& max_characters, const web::json::value& pattern) + { + auto data = make_parameter_constraints(default_value); + data[nmos::fields::nc::max_characters] = max_characters; + data[nmos::fields::nc::pattern] = pattern; + + return data; + } + web::json::value make_parameter_constraints_string(const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) + { + using web::json::value; + + return make_parameter_constraints_string(value::string(default_value), max_characters, value::string(pattern)); + } + web::json::value make_parameter_constraints_string(uint32_t max_characters, const nc_regex& pattern) + { + using web::json::value; + + return make_parameter_constraints_string(value::null(), max_characters, value::string(pattern)); + } + web::json::value make_parameter_constraints_string(uint32_t max_characters) + { + using web::json::value; + + return make_parameter_constraints_string(value::null(), max_characters, value::null()); + } + web::json::value make_parameter_constraints_string(const nc_regex& pattern) + { + using web::json::value; + + return make_parameter_constraints_string(value::null(), value::null(), value::string(pattern)); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresource + web::json::value make_touchpoint_resource(const nc_touchpoint_resource& resource) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::resource_type, resource.resource_type } + }); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresourcenmos + web::json::value make_touchpoint_resource_nmos(const nc_touchpoint_resource_nmos& resource) + { + using web::json::value; + + auto data = make_touchpoint_resource(resource); + data[nmos::fields::nc::id] = value::string(resource.id); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresourcenmoschannelmapping + web::json::value make_touchpoint_resource_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource) + { + using web::json::value; + + auto data = make_touchpoint_resource_nmos(resource); + data[nmos::fields::nc::io_id] = value::string(resource.io_id); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpoint + web::json::value make_touchpoint(const utility::string_t& context_namespace) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::context_namespace, context_namespace } + }); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmos + web::json::value make_touchpoint_nmos(const nc_touchpoint_resource_nmos& resource) + { + auto data = make_touchpoint(U("x-nmos")); + data[nmos::fields::nc::resource] = make_touchpoint_resource_nmos(resource); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmoschannelmapping + web::json::value make_touchpoint_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource) + { + auto data = make_touchpoint(U("x-nmos/channelmapping")); + data[nmos::fields::nc::resource] = make_touchpoint_resource_nmos_channel_mapping(resource); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject + web::json::value make_object(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) + { + using web::json::value; + + const auto id = utility::conversions::details::to_string_t(oid); + auto data = nmos::details::make_resource_core(id, user_label.is_null() ? U("") : user_label.as_string(), description); // required for nmos::resource + data[nmos::fields::nc::class_id] = make_class_id(class_id); + data[nmos::fields::nc::oid] = oid; + data[nmos::fields::nc::constant_oid] = value::boolean(constant_oid); + data[nmos::fields::nc::owner] = owner; + data[nmos::fields::nc::role] = value::string(role); + data[nmos::fields::nc::user_label] = user_label; + data[nmos::fields::nc::touchpoints] = touchpoints; + data[nmos::fields::nc::runtime_property_constraints] = runtime_property_constraints; // level 2 runtime constraints. See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html + + // IS-14 metadata fields + // These fields are "invisible" as they are not part of the NcObject definition + // use make_rebuildable function to declare an control protocol resource rebuildable + data[nmos::fields::nc::is_rebuildable] = value::boolean(false); + // use allowed_member_classes to restrict the types of object that an NcBlock can contain + data[nmos::fields::nc::allowed_members_classes] = value::array(); + // use to indicate dependencies of an object in the device model + data[nmos::fields::nc::dependency_paths] = value::array(); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock + web::json::value make_block(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, const web::json::value& members) + { + using web::json::value; + + auto data = details::make_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); + data[nmos::fields::nc::enabled] = value::boolean(enabled); + data[nmos::fields::nc::members] = members; + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker + web::json::value make_worker(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled) + { + using web::json::value; + + auto data = details::make_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); + data[nmos::fields::nc::enabled] = value::boolean(enabled); + + return data; + } + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor + web::json::value make_status_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, uint64_t status_reporting_delay) + { + using web::json::value; + + auto data = make_worker(class_id, oid, constant_oid, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, enabled); + data[nmos::fields::nc::overall_status] = value::number(overall_status); + data[nmos::fields::nc::overall_status_message] = value::string(overall_status_message); + data[nmos::fields::nc::status_reporting_delay] = value::number(status_reporting_delay); + + return data; + } + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_connection_status::status connection_status, const utility::string_t& connection_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_stream_status::status stream_status, const utility::string_t& stream_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor) + { + using web::json::value; + + auto data = make_status_monitor(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, status_reporting_delay); + + data[nmos::fields::nc::link_status] = value::number(link_status); + data[nmos::fields::nc::link_status_message] = value::string(link_status_message); + data[nmos::fields::nc::link_status_transition_counter] = value::number(0); + data[nmos::fields::nc::connection_status] = value::number(connection_status); + data[nmos::fields::nc::connection_status_message] = value::string(connection_status_message); + data[nmos::fields::nc::connection_status_transition_counter] = value::number(0); + data[nmos::fields::nc::external_synchronization_status] = value::number(external_synchronization_status); + data[nmos::fields::nc::external_synchronization_status_message] = value::string(external_synchronization_status_message); + data[nmos::fields::nc::external_synchronization_status_transition_counter] = value::number(0); + data[nmos::fields::nc::synchronization_source_id] = synchronization_source_id; + data[nmos::fields::nc::stream_status] = value::number(stream_status); + data[nmos::fields::nc::stream_status_message] = value::string(stream_status_message); + data[nmos::fields::nc::stream_status_transition_counter] = value::number(0); + data[nmos::fields::nc::auto_reset_monitor] = value::boolean(auto_reset_monitor); + + // Pending status updates + data[nmos::fields::nc::monitor_activation_time] = value::number(0); + data[nmos::fields::nc::link_status_pending] = value::number(link_status); + data[nmos::fields::nc::link_status_message_pending] = value::string(link_status_message); + data[nmos::fields::nc::link_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::connection_status_pending] = value::number(connection_status); + data[nmos::fields::nc::connection_status_message_pending] = value::string(connection_status_message); + data[nmos::fields::nc::connection_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::external_synchronization_status_pending] = value::number(external_synchronization_status); + data[nmos::fields::nc::external_synchronization_status_message_pending] = value::string(external_synchronization_status_message); + data[nmos::fields::nc::external_synchronization_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::stream_status_pending] = value::number(stream_status); + data[nmos::fields::nc::stream_status_message_pending] = value::string(stream_status_message); + data[nmos::fields::nc::stream_status_pending_received_time] = value::number(0); + + return data; + } + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor + web::json::value make_sender_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_essence_status::status essence_status, const utility::string_t& essence_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor) + { + using web::json::value; + + auto data = make_status_monitor(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, status_reporting_delay); + + data[nmos::fields::nc::link_status] = value::number(link_status); + data[nmos::fields::nc::link_status_message] = value::string(link_status_message); + data[nmos::fields::nc::link_status_transition_counter] = value::number(0); + data[nmos::fields::nc::transmission_status] = value::number(transmission_status); + data[nmos::fields::nc::transmission_status_message] = value::string(transmission_status_message); + data[nmos::fields::nc::transmission_status_transition_counter] = value::number(0); + data[nmos::fields::nc::external_synchronization_status] = value::number(external_synchronization_status); + data[nmos::fields::nc::external_synchronization_status_message] = value::string(external_synchronization_status_message); + data[nmos::fields::nc::external_synchronization_status_transition_counter] = value::number(0); + data[nmos::fields::nc::synchronization_source_id] = synchronization_source_id; + data[nmos::fields::nc::essence_status] = value::number(essence_status); + data[nmos::fields::nc::essence_status_message] = value::string(essence_status_message); + data[nmos::fields::nc::essence_status_transition_counter] = value::number(0); + data[nmos::fields::nc::auto_reset_monitor] = value::boolean(auto_reset_monitor); + + // Pending status updates + data[nmos::fields::nc::monitor_activation_time] = value::number(0); + data[nmos::fields::nc::link_status_pending] = value::number(link_status); + data[nmos::fields::nc::link_status_message_pending] = value::string(link_status_message); + data[nmos::fields::nc::link_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::transmission_status_pending] = value::number(transmission_status); + data[nmos::fields::nc::transmission_status_message_pending] = value::string(transmission_status_message); + data[nmos::fields::nc::transmission_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::external_synchronization_status_pending] = value::number(external_synchronization_status); + data[nmos::fields::nc::external_synchronization_status_message_pending] = value::string(external_synchronization_status_message); + data[nmos::fields::nc::external_synchronization_status_pending_received_time] = value::number(0); + data[nmos::fields::nc::essence_status_pending] = value::number(essence_status); + data[nmos::fields::nc::essence_status_message_pending] = value::string(essence_status_message); + data[nmos::fields::nc::essence_status_pending_received_time] = value::number(0); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager + web::json::value make_manager(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) + { + return make_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager + web::json::value make_device_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, + const web::json::value& manufacturer, const web::json::value& product, const utility::string_t& serial_number, + const web::json::value& user_inventory_code, const web::json::value& device_name, const web::json::value& device_role, const web::json::value& operational_state, nc_reset_cause::cause reset_cause) + { + using web::json::value; + + auto data = details::make_manager(nc_device_manager_class_id, oid, true, owner, U("DeviceManager"), user_label, description, touchpoints, runtime_property_constraints); + data[nmos::fields::nc::nc_version] = value::string(U("v1.0.0")); + data[nmos::fields::nc::manufacturer] = manufacturer; + data[nmos::fields::nc::product] = product; + data[nmos::fields::nc::serial_number] = value::string(serial_number); + data[nmos::fields::nc::user_inventory_code] = user_inventory_code; + data[nmos::fields::nc::device_name] = device_name; + data[nmos::fields::nc::device_role] = device_role; + data[nmos::fields::nc::operational_state] = operational_state; + data[nmos::fields::nc::reset_cause] = reset_cause; + data[nmos::fields::nc::message] = value::null(); + + return data; + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager + web::json::value make_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state) + { + using web::json::value; + + auto data = make_manager(nc_class_manager_class_id, oid, true, owner, U("ClassManager"), user_label, description, touchpoints, runtime_property_constraints); - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::id] = make_nc_event_id(id); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::event_datatype] = value::string(event_datatype); - data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); + auto lock = control_protocol_state.read_lock(); - return data; - } - web::json::value make_nc_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) - { - using web::json::value; + // add control classes + data[nmos::fields::nc::control_classes] = value::array(); + auto& control_classes = data[nmos::fields::nc::control_classes]; + for (const auto& control_class : control_protocol_state.control_class_descriptors) + { + auto& ctl_class = control_class.second; - return make_nc_event_descriptor(value::string(description), id, name, event_datatype, is_deprecated); - } + auto method_descriptors = value::array(); + for (const auto& method_descriptor : ctl_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncfielddescriptor - // description can be null - // type_name can be null - // constraints can be null - web::json::value make_nc_field_descriptor(const web::json::value& description, const nc_name& name, const web::json::value& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + const auto class_description = ctl_class.fixed_role.is_null() + ? make_class_descriptor(ctl_class.description, ctl_class.class_id, ctl_class.name, ctl_class.property_descriptors, method_descriptors, ctl_class.event_descriptors) + : make_class_descriptor(ctl_class.description, ctl_class.class_id, ctl_class.name, ctl_class.fixed_role.as_string(), ctl_class.property_descriptors, method_descriptors, ctl_class.event_descriptors); + web::json::push_back(control_classes, class_description); + } - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::type_name] = type_name; - data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); - data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); - data[nmos::fields::nc::constraints] = constraints; + // add datatypes + data[nmos::fields::nc::datatypes] = value::array(); + auto& datatypes = data[nmos::fields::nc::datatypes]; + for (const auto& datatype_descriptor : control_protocol_state.datatype_descriptors) + { + web::json::push_back(datatypes, datatype_descriptor.second.descriptor); + } - return data; - } - web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + return data; + } - return make_nc_field_descriptor(value::string(description), name, value::string(type_name), is_nullable, is_sequence, constraints); - } - web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertychangedeventdata + web::json::value make_property_changed_event_data(const nc_property_changed_event_data& property_changed_event_data) + { + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::property_id, details::make_property_id(property_changed_event_data.property_id) }, + { nmos::fields::nc::change_type, property_changed_event_data.change_type }, + { nmos::fields::nc::value, property_changed_event_data.value }, + { nmos::fields::nc::sequence_item_index, property_changed_event_data.sequence_item_index } + }, true + ); + } - return make_nc_field_descriptor(value::string(description), name, value::null(), is_nullable, is_sequence, constraints); - } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + web::json::value make_bulk_properties_manager(nc_oid oid, nc_oid owner, const web::json::value &user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethoddescriptor - // description can be null - // id = make_nc_method_id(level, index) - // sequence parameters - web::json::value make_nc_method_descriptor(const web::json::value& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated) - { - using web::json::value; + auto data = make_manager(nc_bulk_properties_manager_class_id, oid, true, owner, U("BulkPropertiesManager"), user_label, description, touchpoints, runtime_property_constraints); - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::id] = make_nc_method_id(id); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::result_datatype] = value::string(result_datatype); - data[nmos::fields::nc::parameters] = parameters; - data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); + return data; + } - return data; - } - web::json::value make_nc_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated) - { - using web::json::value; + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesholder + web::json::value make_bulk_properties_holder(const utility::string_t& validation_fingerprint, const web::json::value& object_properties_holders) + { + using web::json::value_of; - return make_nc_method_descriptor(value::string(description), id, name, result_datatype, parameters, is_deprecated); - } + return value_of({ + { nmos::fields::nc::validation_fingerprint, validation_fingerprint }, + { nmos::fields::nc::values, object_properties_holders } + }, true + ); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterdescriptor - // description can be null - // type_name can be null - web::json::value make_nc_parameter_descriptor(const web::json::value& description, const nc_name& name, const web::json::value& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyholder + web::json::value make_property_holder(const nc_property_id& property_id, const web::json::value& descriptor, const web::json::value& property_value) + { + using web::json::value; + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::id, make_property_id(property_id)}, + { nmos::fields::nc::descriptor, descriptor}, + { nmos::fields::nc::value, property_value}, + }, true); + } - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::type_name] = type_name; - data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); - data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); - data[nmos::fields::nc::constraints] = constraints; + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiesholder + web::json::value make_object_properties_holder(const web::json::array& role_path, const web::json::array& property_holders, const web::json::array& dependency_paths, const web::json::array& allowed_members_classes, bool is_rebuildable) + { + using web::json::value_of; - return data; - } - web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + return value_of({ + { nmos::fields::nc::path, web::json::value_from_elements(role_path)}, + { nmos::fields::nc::dependency_paths, web::json::value_from_elements(dependency_paths)}, + { nmos::fields::nc::allowed_members_classes, web::json::value_from_elements(allowed_members_classes)}, + { nmos::fields::nc::values, web::json::value_from_elements(property_holders)}, + { nmos::fields::nc::is_rebuildable, is_rebuildable} + }, true + ); - return make_nc_parameter_descriptor(value::string(description), name, value::null(), is_nullable, is_sequence, constraints); - } - web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) - { - using web::json::value; + } + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenotice + web::json::value make_property_restore_notice(const nc_property_id& property_id, const nc_name& name, nc_property_restore_notice_type::type notice_type, const utility::string_t& notice_message) + { + using web::json::value; + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::id, make_property_id(property_id)}, + { nmos::fields::nc::name, value::string(name)}, + { nmos::fields::nc::notice_type, value::number(notice_type)}, + { nmos::fields::nc::notice_message, value::string(notice_message)} + }, true + ); + } - return make_nc_parameter_descriptor(value::string(description), name, value::string(type_name), is_nullable, is_sequence, constraints); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiessetvalidation + web::json::value make_object_properties_set_validation(const web::json::array& role_path, nc_restore_validation_status::status status, const web::json::array& notices, const web::json::value& status_message) + { + using web::json::value; + using web::json::value_of; + + return value_of({ + { nmos::fields::nc::path, web::json::value_from_elements(role_path)}, + { nmos::fields::nc::status, value::number(status)}, + { nmos::fields::nc::notices, web::json::value_from_elements(notices)}, + { nmos::fields::nc::status_message, status_message} + }, true + ); + } } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertydescriptor - // description can be null - // constraints can be null - web::json::value make_nc_property_descriptor(const web::json::value& description, const nc_property_id& id, const nc_name& name, const web::json::value& type_name, - bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) + // command message response + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type + web::json::value make_response(int32_t handle, const web::json::value& method_result) { - using web::json::value; - - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::id] = make_nc_property_id(id); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::type_name] = type_name; - data[nmos::fields::nc::is_read_only] = value::boolean(is_read_only); - data[nmos::fields::nc::is_nullable] = value::boolean(is_nullable); - data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); - data[nmos::fields::nc::is_deprecated] = value::boolean(is_deprecated); - data[nmos::fields::nc::constraints] = constraints; + using web::json::value_of; - return data; + return value_of({ + { nmos::fields::nc::handle, handle }, + { nmos::fields::nc::result, method_result } + }); } - web::json::value make_nc_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, - bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) + web::json::value make_command_response(const web::json::value& responses) { - using web::json::value; + using web::json::value_of; - return nmos::details::make_nc_property_descriptor(value::string(description), id, name, value::string(type_name), is_read_only, is_nullable, is_sequence, is_deprecated, constraints); + return value_of({ + { nmos::fields::nc::message_type, ncp_message_type::command_response }, + { nmos::fields::nc::responses, responses } + }); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptor - // description can be null - // constraints can be null - web::json::value make_nc_datatype_descriptor(const web::json::value& description, const nc_name& name, nc_datatype_type::type type, const web::json::value& constraints) + // subscription response + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#subscription-response-message-type + web::json::value make_subscription_response(const web::json::value& subscriptions) { - using web::json::value; - - auto data = make_nc_descriptor(description); - data[nmos::fields::nc::name] = value::string(name); - data[nmos::fields::nc::type] = type; - data[nmos::fields::nc::constraints] = constraints; + using web::json::value_of; - return data; + return value_of({ + { nmos::fields::nc::message_type, ncp_message_type::subscription_response }, + { nmos::fields::nc::subscriptions, subscriptions } + }); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorenum - // description can be null - // constraints can be null - // items: sequence - web::json::value make_nc_datatype_descriptor_enum(const web::json::value& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints) + // notification + // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#notification-messages + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#notification-message-type + web::json::value make_notification(nc_oid oid, const nc_event_id& event_id, const nc_property_changed_event_data& property_changed_event_data) { - auto data = make_nc_datatype_descriptor(description, name, nc_datatype_type::Enum, constraints); - data[nmos::fields::nc::items] = items; + using web::json::value_of; - return data; + return value_of({ + { nmos::fields::nc::oid, oid }, + { nmos::fields::nc::event_id, details::make_event_id(event_id)}, + { nmos::fields::nc::event_data, details::make_property_changed_event_data(property_changed_event_data) } + }); } - web::json::value make_nc_datatype_descriptor_enum(const utility::string_t& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints) + web::json::value make_notification_message(const web::json::value& notifications) { - using web::json::value; + using web::json::value_of; - return make_nc_datatype_descriptor_enum(value::string(description), name, items, constraints); + return value_of({ + { nmos::fields::nc::message_type, ncp_message_type::notification }, + { nmos::fields::nc::notifications, notifications } + }); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorprimitive - // description can be null - // constraints can be null - web::json::value make_nc_datatype_descriptor_primitive(const web::json::value& description, const nc_name& name, const web::json::value& constraints) - { - return make_nc_datatype_descriptor(description, name, nc_datatype_type::Primitive, constraints); - } - web::json::value make_nc_datatype_descriptor_primitive(const utility::string_t& description, const nc_name& name, const web::json::value& constraints) + // property changed notification event + // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#the-propertychanged-event + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/NcObject.html#propertychanged-event + web::json::value make_property_changed_event(nc_oid oid, const std::vector& property_changed_event_data_list) { using web::json::value; - return make_nc_datatype_descriptor_primitive(value::string(description), name, constraints); + auto notifications = value::array(); + for (auto& property_changed_event_data : property_changed_event_data_list) + { + web::json::push_back(notifications, make_notification(oid, nc_object_property_changed_event_id, property_changed_event_data)); + } + return make_notification_message(notifications); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorstruct - // description can be null - // constraints can be null - // fields: sequence - // parent_type can be null - web::json::value make_nc_datatype_descriptor_struct(const web::json::value& description, const nc_name& name, const web::json::value& fields, const web::json::value& parent_type, const web::json::value& constraints) + // error message + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#error-messages + web::json::value make_error_message(const nc_method_result& method_result, const utility::string_t& error_message) { - auto data = make_nc_datatype_descriptor(description, name, nc_datatype_type::Struct, constraints); - data[nmos::fields::nc::fields] = fields; - data[nmos::fields::nc::parent_type] = parent_type; + using web::json::value_of; - return data; + return value_of({ + { nmos::fields::nc::message_type, ncp_message_type::error }, + { nmos::fields::nc::status, method_result.status}, + { nmos::fields::nc::error_message, error_message } + }); } - web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const utility::string_t& parent_type, const web::json::value& constraints) - { - using web::json::value; - return make_nc_datatype_descriptor_struct(value::string(description), name, fields, value::string(parent_type), constraints); - } - web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const web::json::value& constraints) + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject + web::json::value make_object_properties() { using web::json::value; - return make_nc_datatype_descriptor_struct(value::string(description), name, fields, value::null(), constraints); - } + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Static value. All instances of the same class will have the same identity value"), nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Object identifier"), nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("TRUE iff OID is hardwired into device"), nc_object_constant_oid_property_id, nmos::fields::nc::constant_oid, U("NcBoolean"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("OID of containing block. Can only ever be null for the root block"), nc_object_owner_property_id, nmos::fields::nc::owner, U("NcOid"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Role of object in the containing block"), nc_object_role_property_id, nmos::fields::nc::role, U("NcString"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Scribble strip"), nc_object_user_label_property_id, nmos::fields::nc::user_label, U("NcString"), false, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Touchpoints to other contexts"), nc_object_touchpoints_property_id, nmos::fields::nc::touchpoints, U("NcTouchpoint"), true, true, true, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Runtime property constraints"), nc_object_runtime_property_constraints_property_id, nmos::fields::nc::runtime_property_constraints, U("NcPropertyConstraints"), true, true, true, false, value::null())); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptortypedef - // description can be null - // constraints can be null - web::json::value make_nc_datatype_typedef(const web::json::value& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints) + return properties; + } + web::json::value make_object_methods() { using web::json::value; - auto data = make_nc_datatype_descriptor(description, name, nc_datatype_type::Typedef, constraints); - data[nmos::fields::nc::parent_type] = value::string(parent_type); - data[nmos::fields::nc::is_sequence] = value::boolean(is_sequence); + auto methods = value::array(); + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get property value"), nc_object_get_method_id, U("Get"), U("NcMethodResultPropertyValue"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property value"), nmos::fields::nc::value, true, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Set property value"), nc_object_set_method_id, U("Set"), U("NcMethodResult"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get sequence item"), nc_object_get_sequence_item_method_id, U("GetSequenceItem"), U("NcMethodResultPropertyValue"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Set sequence item value"), nc_object_set_sequence_item_method_id, U("SetSequenceItem"), U("NcMethodResult"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id,U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Add item to sequence"), nc_object_add_sequence_item_method_id, U("AddSequenceItem"), U("NcMethodResultId"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Delete sequence item"), nc_object_remove_sequence_item_method_id, U("RemoveSequenceItem"), U("NcMethodResult"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get sequence length"), nc_object_get_sequence_length_method_id, U("GetSequenceLength"), U("NcMethodResultLength"), parameters, false)); + } - return data; + return methods; } - web::json::value make_nc_datatype_typedef(const utility::string_t& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints) + web::json::value make_object_events() { using web::json::value; - return make_nc_datatype_typedef(value::string(description), name, is_sequence, parent_type, constraints); - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraints - web::json::value make_nc_property_constraints(const nc_property_id& property_id, const web::json::value& default_value) - { - using web::json::value_of; + auto events = value::array(); + web::json::push_back(events, details::make_event_descriptor(U("Property changed event"), nc_object_property_changed_event_id, U("PropertyChanged"), U("NcPropertyChangedEventData"), false)); - return value_of({ - { nmos::fields::nc::property_id, make_nc_property_id(property_id) }, - { nmos::fields::nc::default_value, default_value } - }); + return events; } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsnumber - web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, const web::json::value& default_value, const web::json::value& minimum, const web::json::value& maximum, const web::json::value& step) + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock + web::json::value make_block_properties() { using web::json::value; - auto data = make_nc_property_constraints(property_id, default_value); - data[nmos::fields::nc::minimum] = minimum; - data[nmos::fields::nc::maximum] = maximum; - data[nmos::fields::nc::step] = step; + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("TRUE if block is functional"), nc_block_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Descriptors of this block's members"), nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, value::null())); - return data; + return properties; } - web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) + web::json::value make_block_methods() { using web::json::value; - return make_nc_property_constraints_number(property_id, value(default_value), value(minimum), value(maximum), value(step)); + auto methods = value::array(); + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If recurse is set to true, nested members can be retrieved"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Gets descriptors of members of the block"), nc_block_get_member_descriptors_method_id, U("GetMemberDescriptors"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Relative path to search for (MUST not include the role of the block targeted by oid)"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Finds member(s) by path"), nc_block_find_members_by_path_method_id, U("FindMembersByPath"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Role text to search for"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Signals if the comparison should be case sensitive"), nmos::fields::nc::case_sensitive, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("TRUE to only return exact matches"), nmos::fields::nc::match_whole_string, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("TRUE to search nested blocks"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Finds members with given role name or fragment"), nc_block_find_members_by_role_method_id, U("FindMembersByRole"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Class id to search for"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If TRUE it will also include derived class descriptors"), nmos::fields::nc::include_derived, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("TRUE to search nested blocks"), nmos::fields::nc::recurse,U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Finds members with given class id"), nc_block_find_members_by_class_id_method_id, U("FindMembersByClassId"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); + } + + return methods; } - web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t minimum, uint64_t maximum, uint64_t step) + web::json::value make_block_events() { using web::json::value; - return make_nc_property_constraints_number(property_id, value::null(), minimum, maximum, step); + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsstring - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const web::json::value& default_value, const web::json::value& max_characters, const web::json::value& pattern) + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker + web::json::value make_worker_properties() { using web::json::value; - auto data = make_nc_property_constraints(property_id, default_value); - data[nmos::fields::nc::max_characters] = max_characters; - data[nmos::fields::nc::pattern] = pattern; + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("TRUE iff worker is enabled"), nc_worker_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), false, false, false, false, value::null())); - return data; + return properties; } - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) + web::json::value make_worker_methods() { using web::json::value; - return make_nc_property_constraints_string(property_id, value::string(default_value), max_characters, value::string(pattern)); + return value::array(); } - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters, const nc_regex& pattern) + web::json::value make_worker_events() { using web::json::value; - return make_nc_property_constraints_string(property_id, value::null(), max_characters, value::string(pattern)); + return value::array(); } - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters) + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager + web::json::value make_manager_properties() { using web::json::value; - return make_nc_property_constraints_string(property_id, value::null(), max_characters, value::null()); + return value::array(); } - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const nc_regex& pattern) + web::json::value make_manager_methods() { using web::json::value; - return make_nc_property_constraints_string(property_id, value::null(), value::null(), value::string(pattern)); + return value::array(); } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraints - web::json::value make_nc_parameter_constraints(const web::json::value& default_value) + web::json::value make_manager_events() { - using web::json::value_of; + using web::json::value; - return value_of({ - { nmos::fields::nc::default_value, default_value } - }); + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber - web::json::value make_nc_parameter_constraints_number(const web::json::value& default_value, const web::json::value& minimum, const web::json::value& maximum, const web::json::value& step) + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager + web::json::value make_device_manager_properties() { using web::json::value; - auto data = make_nc_parameter_constraints(default_value); - data[nmos::fields::nc::minimum] = minimum; - data[nmos::fields::nc::maximum] = maximum; - data[nmos::fields::nc::step] = step; + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Version of MS-05-02 that this device uses"), nc_device_manager_nc_version_property_id, nmos::fields::nc::nc_version, U("NcVersionCode"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Manufacturer descriptor"), nc_device_manager_manufacturer_property_id, nmos::fields::nc::manufacturer, U("NcManufacturer"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Product descriptor"), nc_device_manager_product_property_id, nmos::fields::nc::product, U("NcProduct"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Serial number"), nc_device_manager_serial_number_property_id, nmos::fields::nc::serial_number, U("NcString"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Asset tracking identifier (user specified)"), nc_device_manager_user_inventory_code_property_id, nmos::fields::nc::user_inventory_code, U("NcString"), false, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Name of this device in the application. Instance name, not product name"), nc_device_manager_device_name_property_id, nmos::fields::nc::device_name, U("NcString"), false, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Role of this device in the application"), nc_device_manager_device_role_property_id, nmos::fields::nc::device_role, U("NcString"), false, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Device operational state"), nc_device_manager_operational_state_property_id, nmos::fields::nc::operational_state, U("NcDeviceOperationalState"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Reason for most recent reset"), nc_device_manager_reset_cause_property_id, nmos::fields::nc::reset_cause, U("NcResetCause"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Arbitrary message from dev to controller"), nc_device_manager_message_property_id, nmos::fields::nc::message, U("NcString"), true, true, false, false, value::null())); - return data; + return properties; } - web::json::value make_nc_parameter_constraints_number(uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) + web::json::value make_device_manager_methods() { using web::json::value; - return make_nc_parameter_constraints_number(value(default_value), value(minimum), value(maximum), value(step)); + return value::array(); } - web::json::value make_nc_parameter_constraints_number(uint64_t minimum, uint64_t maximum, uint64_t step) + web::json::value make_device_manager_events() { using web::json::value; - return make_nc_parameter_constraints_number(value::null(), minimum, maximum, step); + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring - web::json::value make_nc_parameter_constraints_string(const web::json::value& default_value, const web::json::value& max_characters, const web::json::value& pattern) + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager + web::json::value make_class_manager_properties() { - auto data = make_nc_parameter_constraints(default_value); - data[nmos::fields::nc::max_characters] = max_characters; - data[nmos::fields::nc::pattern] = pattern; + using web::json::value; - return data; + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Descriptions of all control classes in the device (descriptors do not contain inherited elements)"), nc_class_manager_control_classes_property_id, nmos::fields::nc::control_classes, U("NcClassDescriptor"), true, false, true, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Descriptions of all data types in the device (descriptors do not contain inherited elements)"), nc_class_manager_datatypes_property_id, nmos::fields::nc::datatypes, U("NcDatatypeDescriptor"), true, false, true, false, value::null())); + + return properties; } - web::json::value make_nc_parameter_constraints_string(const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) + web::json::value make_class_manager_methods() { using web::json::value; - return make_nc_parameter_constraints_string(value::string(default_value), max_characters, value::string(pattern)); + auto methods = value::array(); + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::include_inherited, U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get a single class descriptor"), nc_class_manager_get_control_class_method_id, U("GetControlClass"), U("NcMethodResultClassDescriptor"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("name of datatype"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::include_inherited, U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get a single datatype descriptor"), nc_class_manager_get_datatype_method_id, U("GetDatatype"), U("NcMethodResultDatatypeDescriptor"), parameters, false)); + } + + return methods; } - web::json::value make_nc_parameter_constraints_string(uint32_t max_characters, const nc_regex& pattern) + web::json::value make_class_manager_events() { using web::json::value; - return make_nc_parameter_constraints_string(value::null(), max_characters, value::string(pattern)); + return value::array(); } - web::json::value make_nc_parameter_constraints_string(uint32_t max_characters) + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor + web::json::value make_status_monitor_properties() { using web::json::value; - return make_nc_parameter_constraints_string(value::null(), max_characters, value::null()); + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Overall status property"), nc_status_monitor_overall_status_property_id, nmos::fields::nc::overall_status, U("NcOverallStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Overall status message property"), nc_status_monitor_overall_status_message_property_id, nmos::fields::nc::overall_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Status reporting delay property (in seconds, default is 3s and 0 means no delay)"), nc_status_monitor_status_reporting_delay, nmos::fields::nc::status_reporting_delay, U("NcUint32"), false, false, false, false, value::null())); + + return properties; } - web::json::value make_nc_parameter_constraints_string(const nc_regex& pattern) + web::json::value make_status_monitor_methods() { using web::json::value; - return make_nc_parameter_constraints_string(value::null(), value::null(), value::string(pattern)); + return value::array(); } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresource - web::json::value make_nc_touchpoint_resource(const nc_touchpoint_resource& resource) + web::json::value make_status_monitor_events() { - using web::json::value_of; + using web::json::value; - return value_of({ - { nmos::fields::nc::resource_type, resource.resource_type } - }); + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresourcenmos - web::json::value make_nc_touchpoint_resource_nmos(const nc_touchpoint_resource_nmos& resource) + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor_properties() { using web::json::value; - auto data = make_nc_touchpoint_resource(resource); - data[nmos::fields::nc::id] = value::string(resource.id); - - return data; - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointresourcenmoschannelmapping - web::json::value make_nc_touchpoint_resource_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource) + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Link status property"), nc_receiver_monitor_link_status_property_id, nmos::fields::nc::link_status, U("NcLinkStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Link status message property"), nc_receiver_monitor_link_status_message_property_id, nmos::fields::nc::link_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Link status transition counter property"), nc_receiver_monitor_link_status_transition_counter_property_id, nmos::fields::nc::link_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Connection status property"), nc_receiver_monitor_connection_status_property_id, nmos::fields::nc::connection_status, U("NcConnectionStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Connection status message property"), nc_receiver_monitor_connection_status_message_property_id, nmos::fields::nc::connection_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Connection status transition counter property"), nc_receiver_monitor_connection_status_transition_counter_property_id, nmos::fields::nc::connection_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status property"), nc_receiver_monitor_external_synchronization_status_property_id, nmos::fields::nc::external_synchronization_status, U("NcSynchronizationStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status message property"), nc_receiver_monitor_external_synchronization_status_message_property_id, nmos::fields::nc::external_synchronization_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status transition counter property"), nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, nmos::fields::nc::external_synchronization_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Synchronization source id property"), nc_receiver_monitor_synchronization_source_id_property_id, nmos::fields::nc::synchronization_source_id, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Stream status property"), nc_receiver_monitor_stream_status_property_id, nmos::fields::nc::stream_status, U("NcStreamStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Stream status message property"), nc_receiver_monitor_stream_status_message_property_id, nmos::fields::nc::stream_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Stream status property transition counters"), nc_receiver_monitor_stream_status_transition_counter_property_id, nmos::fields::nc::stream_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Automatic reset counters and messages property (default: true)"), nc_receiver_monitor_auto_reset_monitor_property_id, nmos::fields::nc::auto_reset_monitor, U("NcBoolean"), false, false, false, false, value::null())); + + return properties; + } + web::json::value make_receiver_monitor_methods() { using web::json::value; - auto data = make_nc_touchpoint_resource_nmos(resource); - data[nmos::fields::nc::io_id] = value::string(resource.io_id); + auto methods = value::array(); + web::json::push_back(methods, details::make_method_descriptor(U("Gets the lost packet counters"), nc_receiver_monitor_get_lost_packet_counters_method_id, U("GetLostPacketCounters"), U("NcMethodResultCounters"), value::array(), false)); + web::json::push_back(methods, details::make_method_descriptor(U("Gets the late packet counters"), nc_receiver_monitor_get_late_packet_counters_method_id, U("GetLatePacketCounters"), U("NcMethodResultCounters"), value::array(), false)); + web::json::push_back(methods, details::make_method_descriptor(U("Resets ALL counters"), nc_receiver_monitor_reset_monitor_method_id, U("ResetCountersAndMessages"), U("NcMethodResult"), value::array(), false)); - return data; + return methods; } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpoint - web::json::value make_nc_touchpoint(const utility::string_t& context_namespace) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::context_namespace, context_namespace } - }); - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmos - web::json::value make_nc_touchpoint_nmos(const nc_touchpoint_resource_nmos& resource) + web::json::value make_receiver_monitor_events() { - auto data = make_nc_touchpoint(U("x-nmos")); - data[nmos::fields::nc::resource] = make_nc_touchpoint_resource_nmos(resource); + using web::json::value; - return data; + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmoschannelmapping - web::json::value make_nc_touchpoint_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource) + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor + web::json::value make_sender_monitor_properties() { - auto data = make_nc_touchpoint(U("x-nmos/channelmapping")); - data[nmos::fields::nc::resource] = make_nc_touchpoint_resource_nmos_channel_mapping(resource); - - return data; - } + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject - web::json::value make_nc_object(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Link status property"), nc_sender_monitor_link_status_property_id, nmos::fields::nc::link_status, U("NcLinkStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Link status message property"), nc_sender_monitor_link_status_message_property_id, nmos::fields::nc::link_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Link status transition counter property"), nc_sender_monitor_link_status_transition_counter_property_id, nmos::fields::nc::link_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Transmission status property"), nc_sender_monitor_transmission_status_property_id, nmos::fields::nc::transmission_status, U("NcTransmissionStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Transmission status message property"), nc_sender_monitor_transmission_status_message_property_id, nmos::fields::nc::transmission_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Transmission status transition counter property"), nc_sender_monitor_transmission_status_transition_counter_property_id, nmos::fields::nc::transmission_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status property"), nc_sender_monitor_external_synchronization_status_property_id, nmos::fields::nc::external_synchronization_status, U("NcSynchronizationStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status message property"), nc_sender_monitor_external_synchronization_status_message_property_id, nmos::fields::nc::external_synchronization_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("External synchronization status transition counter property"), nc_sender_monitor_external_synchronization_status_transition_counter_property_id, nmos::fields::nc::external_synchronization_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Synchronization source id property"), nc_sender_monitor_synchronization_source_id_property_id, nmos::fields::nc::synchronization_source_id, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Essence status property"), nc_sender_monitor_essence_status_property_id, nmos::fields::nc::essence_status, U("NcEssenceStatus"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Essence status message property"), nc_sender_monitor_essence_status_message_property_id, nmos::fields::nc::essence_status_message, U("NcString"), true, true, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Essence status property transition counters"), nc_sender_monitor_essence_status_transition_counter_property_id, nmos::fields::nc::essence_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); + web::json::push_back(properties, details::make_property_descriptor(U("Automatic reset counters and messages property (default: true)"), nc_sender_monitor_auto_reset_monitor_property_id, nmos::fields::nc::auto_reset_monitor, U("NcBoolean"), false, false, false, false, value::null())); + + return properties; + } + web::json::value make_sender_monitor_methods() { using web::json::value; - const auto id = utility::conversions::details::to_string_t(oid); - auto data = make_resource_core(id, user_label.is_null() ? U("") : user_label.as_string(), description); // required for nmos::resource - data[nmos::fields::nc::class_id] = make_nc_class_id(class_id); - data[nmos::fields::nc::oid] = oid; - data[nmos::fields::nc::constant_oid] = value::boolean(constant_oid); - data[nmos::fields::nc::owner] = owner; - data[nmos::fields::nc::role] = value::string(role); - data[nmos::fields::nc::user_label] = user_label; - data[nmos::fields::nc::touchpoints] = touchpoints; - data[nmos::fields::nc::runtime_property_constraints] = runtime_property_constraints; // level 2 runtime constraints. See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html + auto methods = value::array(); + web::json::push_back(methods, details::make_method_descriptor(U("Gets the transmission error counters"), nc_sender_monitor_get_transmission_error_counters_method_id, U("GetTransmissionErrorCounters"), U("NcMethodResultCounters"), value::array(), false)); + web::json::push_back(methods, details::make_method_descriptor(U("Resets ALL counters"), nc_sender_monitor_reset_monitor_method_id, U("ResetCountersAndMessages"), U("NcMethodResult"), value::array(), false)); - return data; + return methods; } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock - web::json::value make_nc_block(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, const web::json::value& members) + web::json::value make_sender_monitor_events() { using web::json::value; - auto data = details::make_nc_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); - data[nmos::fields::nc::enabled] = value::boolean(enabled); - data[nmos::fields::nc::members] = members; - - return data; + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker - web::json::value make_nc_worker(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled) + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon + web::json::value make_ident_beacon_properties() { using web::json::value; - auto data = details::make_nc_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); - data[nmos::fields::nc::enabled] = value::boolean(enabled); + auto properties = value::array(); + web::json::push_back(properties, details::make_property_descriptor(U("Indicator active state"), nc_ident_beacon_active_property_id, nmos::fields::nc::active, U("NcBoolean"), false, false, false, false, value::null())); - return data; + return properties; } - - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor - web::json::value make_nc_status_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, uint64_t status_reporting_delay) + web::json::value make_ident_beacon_methods() { using web::json::value; - auto data = make_nc_worker(class_id, oid, constant_oid, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, enabled); - data[nmos::fields::nc::overall_status] = value::number(overall_status); - data[nmos::fields::nc::overall_status_message] = value::string(overall_status_message); - data[nmos::fields::nc::status_reporting_delay] = value::number(status_reporting_delay); - - return data; - } - - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_receiver_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_connection_status::status connection_status, const utility::string_t& connection_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_stream_status::status stream_status, const utility::string_t& stream_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor) - { - using web::json::value; - - auto data = make_nc_status_monitor(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, status_reporting_delay); - - data[nmos::fields::nc::link_status] = value::number(link_status); - data[nmos::fields::nc::link_status_message] = value::string(link_status_message); - data[nmos::fields::nc::link_status_transition_counter] = value::number(0); - data[nmos::fields::nc::connection_status] = value::number(connection_status); - data[nmos::fields::nc::connection_status_message] = value::string(connection_status_message); - data[nmos::fields::nc::connection_status_transition_counter] = value::number(0); - data[nmos::fields::nc::external_synchronization_status] = value::number(external_synchronization_status); - data[nmos::fields::nc::external_synchronization_status_message] = value::string(external_synchronization_status_message); - data[nmos::fields::nc::external_synchronization_status_transition_counter] = value::number(0); - data[nmos::fields::nc::synchronization_source_id] = synchronization_source_id; - data[nmos::fields::nc::stream_status] = value::number(stream_status); - data[nmos::fields::nc::stream_status_message] = value::string(stream_status_message); - data[nmos::fields::nc::stream_status_transition_counter] = value::number(0); - data[nmos::fields::nc::auto_reset_monitor] = value::boolean(auto_reset_monitor); - - // Pending status updates - data[nmos::fields::nc::monitor_activation_time] = value::number(0); - data[nmos::fields::nc::link_status_pending] = value::number(link_status); - data[nmos::fields::nc::link_status_message_pending] = value::string(link_status_message); - data[nmos::fields::nc::link_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::connection_status_pending] = value::number(connection_status); - data[nmos::fields::nc::connection_status_message_pending] = value::string(connection_status_message); - data[nmos::fields::nc::connection_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::external_synchronization_status_pending] = value::number(external_synchronization_status); - data[nmos::fields::nc::external_synchronization_status_message_pending] = value::string(external_synchronization_status_message); - data[nmos::fields::nc::external_synchronization_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::stream_status_pending] = value::number(stream_status); - data[nmos::fields::nc::stream_status_message_pending] = value::string(stream_status_message); - data[nmos::fields::nc::stream_status_pending_received_time] = value::number(0); - - return data; - } - - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_sender_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_essence_status::status essence_status, const utility::string_t& essence_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor) - { - using web::json::value; - - auto data = make_nc_status_monitor(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, status_reporting_delay); - - data[nmos::fields::nc::link_status] = value::number(link_status); - data[nmos::fields::nc::link_status_message] = value::string(link_status_message); - data[nmos::fields::nc::link_status_transition_counter] = value::number(0); - data[nmos::fields::nc::transmission_status] = value::number(transmission_status); - data[nmos::fields::nc::transmission_status_message] = value::string(transmission_status_message); - data[nmos::fields::nc::transmission_status_transition_counter] = value::number(0); - data[nmos::fields::nc::external_synchronization_status] = value::number(external_synchronization_status); - data[nmos::fields::nc::external_synchronization_status_message] = value::string(external_synchronization_status_message); - data[nmos::fields::nc::external_synchronization_status_transition_counter] = value::number(0); - data[nmos::fields::nc::synchronization_source_id] = synchronization_source_id; - data[nmos::fields::nc::essence_status] = value::number(essence_status); - data[nmos::fields::nc::essence_status_message] = value::string(essence_status_message); - data[nmos::fields::nc::essence_status_transition_counter] = value::number(0); - data[nmos::fields::nc::auto_reset_monitor] = value::boolean(auto_reset_monitor); - - // Pending status updates - data[nmos::fields::nc::monitor_activation_time] = value::number(0); - data[nmos::fields::nc::link_status_pending] = value::number(link_status); - data[nmos::fields::nc::link_status_message_pending] = value::string(link_status_message); - data[nmos::fields::nc::link_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::transmission_status_pending] = value::number(transmission_status); - data[nmos::fields::nc::transmission_status_message_pending] = value::string(transmission_status_message); - data[nmos::fields::nc::transmission_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::external_synchronization_status_pending] = value::number(external_synchronization_status); - data[nmos::fields::nc::external_synchronization_status_message_pending] = value::string(external_synchronization_status_message); - data[nmos::fields::nc::external_synchronization_status_pending_received_time] = value::number(0); - data[nmos::fields::nc::essence_status_pending] = value::number(essence_status); - data[nmos::fields::nc::essence_status_message_pending] = value::string(essence_status_message); - data[nmos::fields::nc::essence_status_pending_received_time] = value::number(0); - - return data; + return value::array(); } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager - web::json::value make_nc_manager(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) + web::json::value make_ident_beacon_events() { - return make_nc_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); + using web::json::value; + + return value::array(); } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager - web::json::value make_nc_device_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, - const web::json::value& manufacturer, const web::json::value& product, const utility::string_t& serial_number, - const web::json::value& user_inventory_code, const web::json::value& device_name, const web::json::value& device_role, const web::json::value& operational_state, nc_reset_cause::cause reset_cause) + // Device configuration classes + // NcBulkPropertiesManager + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + web::json::value make_bulk_properties_manager_properties() { using web::json::value; - auto data = details::make_nc_manager(nc_device_manager_class_id, oid, true, owner, U("DeviceManager"), user_label, description, touchpoints, runtime_property_constraints); - data[nmos::fields::nc::nc_version] = value::string(U("v1.0.0")); - data[nmos::fields::nc::manufacturer] = manufacturer; - data[nmos::fields::nc::product] = product; - data[nmos::fields::nc::serial_number] = value::string(serial_number); - data[nmos::fields::nc::user_inventory_code] = user_inventory_code; - data[nmos::fields::nc::device_name] = device_name; - data[nmos::fields::nc::device_role] = device_role; - data[nmos::fields::nc::operational_state] = operational_state; - data[nmos::fields::nc::reset_cause] = reset_cause; - data[nmos::fields::nc::message] = value::null(); - - return data; + return value::array(); } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager - web::json::value make_nc_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state) + web::json::value make_bulk_properties_manager_methods() { using web::json::value; - auto data = make_nc_manager(nc_class_manager_class_id, oid, true, owner, U("ClassManager"), user_label, description, touchpoints, runtime_property_constraints); - - auto lock = control_protocol_state.read_lock(); - - // add control classes - data[nmos::fields::nc::control_classes] = value::array(); - auto& control_classes = data[nmos::fields::nc::control_classes]; - for (const auto& control_class : control_protocol_state.control_class_descriptors) + auto methods = value::array(); { - auto& ctl_class = control_class.second; - - auto method_descriptors = value::array(); - for (const auto& method_descriptor : ctl_class.method_descriptors) { web::json::push_back(method_descriptors, std::get<0>(method_descriptor)); } - - const auto class_description = ctl_class.fixed_role.is_null() - ? make_nc_class_descriptor(ctl_class.description, ctl_class.class_id, ctl_class.name, ctl_class.property_descriptors, method_descriptors, ctl_class.event_descriptors) - : make_nc_class_descriptor(ctl_class.description, ctl_class.class_id, ctl_class.name, ctl_class.fixed_role.as_string(), ctl_class.property_descriptors, method_descriptors, ctl_class.event_descriptors); - web::json::push_back(control_classes, class_description); + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("The target role path"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If true will return properties on specified path and all the nested paths"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If true, property holders returned will contain non-null property descriptors and for full backups the ClassManager role path will also be included"), nmos::fields::nc::include_descriptors, U("NcBoolean"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Get bulk object properties by given path"), nc_bulk_properties_manager_get_properties_by_path_method_id, U("GetPropertiesByPath"), U("NcMethodResultBulkPropertiesHolder"), parameters, false)); } - - // add datatypes - data[nmos::fields::nc::datatypes] = value::array(); - auto& datatypes = data[nmos::fields::nc::datatypes]; - for (const auto& datatype_descriptor : control_protocol_state.datatype_descriptors) { - web::json::push_back(datatypes, datatype_descriptor.second.descriptor); + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("The values offered (this may include read-only values and also paths which are not the target role path)"), nmos::fields::nc::data_set, U("NcBulkPropertiesHolder"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If true will validate properties on target path and all the nested paths"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Defines the restore mode to be applied"), nmos::fields::nc::restore_mode, U("NcRestoreMode"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Validate bulk properties for setting by given paths"), nc_bulk_properties_manager_validate_set_properties_by_path_method_id, U("ValidateSetPropertiesByPath"), U("NcMethodResultObjectPropertiesSetValidation"), parameters, false)); + } + { + auto parameters = value::array(); + web::json::push_back(parameters, details::make_parameter_descriptor(U("The values offered (this may include read-only values and also paths which are not the target role path)"), nmos::fields::nc::data_set, U("NcBulkPropertiesHolder"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("If true will validate properties on target path and all the nested paths"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); + web::json::push_back(parameters, details::make_parameter_descriptor(U("Defines the restore mode to be applied"), nmos::fields::nc::restore_mode, U("NcRestoreMode"), false, false, value::null())); + web::json::push_back(methods, details::make_method_descriptor(U("Set bulk properties for setting by given paths"), nc_bulk_properties_manager_set_properties_by_path_method_id, U("SetPropertiesByPath"), U("NcMethodResultObjectPropertiesSetValidation"), parameters, false)); } - return data; + return methods; } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertychangedeventdata - web::json::value make_nc_property_changed_event_data(const nc_property_changed_event_data& property_changed_event_data) + web::json::value make_bulk_properties_manager_events() { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::property_id, details::make_nc_property_id(property_changed_event_data.property_id) }, - { nmos::fields::nc::change_type, property_changed_event_data.change_type }, - { nmos::fields::nc::value, property_changed_event_data.value }, - { nmos::fields::nc::sequence_item_index, property_changed_event_data.sequence_item_index } - }); - } - } - - // command message response - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type - web::json::value make_control_protocol_response(int32_t handle, const web::json::value& method_result) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::handle, handle }, - { nmos::fields::nc::result, method_result } - }); - } - web::json::value make_control_protocol_command_response(const web::json::value& responses) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::message_type, ncp_message_type::command_response }, - { nmos::fields::nc::responses, responses } - }); - } - - // subscription response - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#subscription-response-message-type - web::json::value make_control_protocol_subscription_response(const web::json::value& subscriptions) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::message_type, ncp_message_type::subscription_response }, - { nmos::fields::nc::subscriptions, subscriptions } - }); - } - - // notification - // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#notification-messages - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#notification-message-type - web::json::value make_control_protocol_notification(nc_oid oid, const nc_event_id& event_id, const nc_property_changed_event_data& property_changed_event_data) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::oid, oid }, - { nmos::fields::nc::event_id, details::make_nc_event_id(event_id)}, - { nmos::fields::nc::event_data, details::make_nc_property_changed_event_data(property_changed_event_data) } - }); - } - web::json::value make_control_protocol_notification_message(const web::json::value& notifications) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::message_type, ncp_message_type::notification }, - { nmos::fields::nc::notifications, notifications } - }); - } - - // property changed notification event - // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#the-propertychanged-event - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/NcObject.html#propertychanged-event - web::json::value make_property_changed_event(nc_oid oid, const std::vector& property_changed_event_data_list) - { - using web::json::value; + using web::json::value; - auto notifications = value::array(); - for (auto& property_changed_event_data : property_changed_event_data_list) - { - web::json::push_back(notifications, make_control_protocol_notification(oid, nc_object_property_changed_event_id, property_changed_event_data)); + return value::array(); } - return make_control_protocol_notification_message(notifications); - } - // error message - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#error-messages - web::json::value make_control_protocol_error_message(const nc_method_result& method_result, const utility::string_t& error_message) - { - using web::json::value_of; - - return value_of({ - { nmos::fields::nc::message_type, ncp_message_type::error }, - { nmos::fields::nc::status, method_result.status}, - { nmos::fields::nc::error_message, error_message } - }); - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject - web::json::value make_nc_object_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Static value. All instances of the same class will have the same identity value"), nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Object identifier"), nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("TRUE iff OID is hardwired into device"), nc_object_constant_oid_property_id, nmos::fields::nc::constant_oid, U("NcBoolean"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("OID of containing block. Can only ever be null for the root block"), nc_object_owner_property_id, nmos::fields::nc::owner, U("NcOid"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Role of object in the containing block"), nc_object_role_property_id, nmos::fields::nc::role, U("NcString"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Scribble strip"), nc_object_user_label_property_id, nmos::fields::nc::user_label, U("NcString"), false, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Touchpoints to other contexts"), nc_object_touchpoints_property_id, nmos::fields::nc::touchpoints, U("NcTouchpoint"), true, true, true, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Runtime property constraints"), nc_object_runtime_property_constraints_property_id, nmos::fields::nc::runtime_property_constraints, U("NcPropertyConstraints"), true, true, true, false, value::null())); - - return properties; - } - web::json::value make_nc_object_methods() - { - using web::json::value; - - auto methods = value::array(); - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Get property value"), nc_object_get_method_id, U("Get"), U("NcMethodResultPropertyValue"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property value"), nmos::fields::nc::value, true, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Set property value"), nc_object_set_method_id, U("Set"), U("NcMethodResult"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Get sequence item"), nc_object_get_sequence_item_method_id, U("GetSequenceItem"), U("NcMethodResultPropertyValue"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Set sequence item value"), nc_object_set_sequence_item_method_id, U("SetSequenceItem"), U("NcMethodResult"), parameters, false)); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.html + web::json::value make_object_class() { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id,U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Add item to sequence"), nc_object_add_sequence_item_method_id, U("AddSequenceItem"), U("NcMethodResultId"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Delete sequence item"), nc_object_remove_sequence_item_method_id, U("RemoveSequenceItem"), U("NcMethodResult"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Get sequence length"), nc_object_get_sequence_length_method_id, U("GetSequenceLength"), U("NcMethodResultLength"), parameters, false)); - } - - return methods; - } - web::json::value make_nc_object_events() - { - using web::json::value; - - auto events = value::array(); - web::json::push_back(events, details::make_nc_event_descriptor(U("Property changed event"), nc_object_property_changed_event_id, U("PropertyChanged"), U("NcPropertyChangedEventData"), false)); - - return events; - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock - web::json::value make_nc_block_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("TRUE if block is functional"), nc_block_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Descriptors of this block's members"), nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, value::null())); - - return properties; - } - web::json::value make_nc_block_methods() - { - using web::json::value; + using web::json::value; - auto methods = value::array(); - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("If recurse is set to true, nested members can be retrieved"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Gets descriptors of members of the block"), nc_block_get_member_descriptors_method_id, U("GetMemberDescriptors"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Relative path to search for (MUST not include the role of the block targeted by oid)"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Finds member(s) by path"), nc_block_find_members_by_path_method_id, U("FindMembersByPath"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Role text to search for"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Signals if the comparison should be case sensitive"), nmos::fields::nc::case_sensitive, U("NcBoolean"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("TRUE to only return exact matches"), nmos::fields::nc::match_whole_string, U("NcBoolean"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("TRUE to search nested blocks"), nmos::fields::nc::recurse, U("NcBoolean"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Finds members with given role name or fragment"), nc_block_find_members_by_role_method_id, U("FindMembersByRole"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); - } - { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("Class id to search for"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("If TRUE it will also include derived class descriptors"), nmos::fields::nc::include_derived, U("NcBoolean"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("TRUE to search nested blocks"), nmos::fields::nc::recurse,U("NcBoolean"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Finds members with given class id"), nc_block_find_members_by_class_id_method_id, U("FindMembersByClassId"), U("NcMethodResultBlockMemberDescriptors"), parameters, false)); + return details::make_class_descriptor(U("NcObject class descriptor"), nc_object_class_id, U("NcObject"), make_object_properties(), make_object_methods(), make_object_events()); } - return methods; - } - web::json::value make_nc_block_events() - { - using web::json::value; - - return value::array(); - } - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker - web::json::value make_nc_worker_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("TRUE iff worker is enabled"), nc_worker_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), false, false, false, false, value::null())); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.1.html + web::json::value make_block_class() + { + using web::json::value; - return properties; - } - web::json::value make_nc_worker_methods() - { - using web::json::value; + return details::make_class_descriptor(U("NcBlock class descriptor"), nc_block_class_id, U("NcBlock"), make_block_properties(), make_block_methods(), make_block_events()); + } - return value::array(); - } - web::json::value make_nc_worker_events() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.2.html + web::json::value make_worker_class() + { + using web::json::value; - return value::array(); - } + return details::make_class_descriptor(U("NcWorker class descriptor"), nc_worker_class_id, U("NcWorker"), make_worker_properties(), make_worker_methods(), make_worker_events()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager - web::json::value make_nc_manager_properties() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.html + web::json::value make_manager_class() + { + using web::json::value; - return value::array(); - } - web::json::value make_nc_manager_methods() - { - using web::json::value; + return details::make_class_descriptor(U("NcManager class descriptor"), nc_manager_class_id, U("NcManager"), make_manager_properties(), make_manager_methods(), make_manager_events()); + } - return value::array(); - } - web::json::value make_nc_manager_events() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.1.html + web::json::value make_device_manager_class() + { + using web::json::value; - return value::array(); - } + return details::make_class_descriptor(U("NcDeviceManager class descriptor"), nc_device_manager_class_id, U("NcDeviceManager"), U("DeviceManager"), make_device_manager_properties(), make_device_manager_methods(), make_device_manager_events()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager - web::json::value make_nc_device_manager_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Version of MS-05-02 that this device uses"), nc_device_manager_nc_version_property_id, nmos::fields::nc::nc_version, U("NcVersionCode"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Manufacturer descriptor"), nc_device_manager_manufacturer_property_id, nmos::fields::nc::manufacturer, U("NcManufacturer"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Product descriptor"), nc_device_manager_product_property_id, nmos::fields::nc::product, U("NcProduct"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Serial number"), nc_device_manager_serial_number_property_id, nmos::fields::nc::serial_number, U("NcString"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Asset tracking identifier (user specified)"), nc_device_manager_user_inventory_code_property_id, nmos::fields::nc::user_inventory_code, U("NcString"), false, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Name of this device in the application. Instance name, not product name"), nc_device_manager_device_name_property_id, nmos::fields::nc::device_name, U("NcString"), false, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Role of this device in the application"), nc_device_manager_device_role_property_id, nmos::fields::nc::device_role, U("NcString"), false, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Device operational state"), nc_device_manager_operational_state_property_id, nmos::fields::nc::operational_state, U("NcDeviceOperationalState"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Reason for most recent reset"), nc_device_manager_reset_cause_property_id, nmos::fields::nc::reset_cause, U("NcResetCause"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Arbitrary message from dev to controller"), nc_device_manager_message_property_id, nmos::fields::nc::message, U("NcString"), true, true, false, false, value::null())); - - return properties; - } - web::json::value make_nc_device_manager_methods() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.2.html + web::json::value make_class_manager_class() + { + using web::json::value; - return value::array(); - } - web::json::value make_nc_device_manager_events() - { - using web::json::value; + return details::make_class_descriptor(U("NcClassManager class descriptor"), nc_class_manager_class_id, U("NcClassManager"), U("ClassManager"), make_class_manager_properties(), make_class_manager_methods(), make_class_manager_events()); + } - return value::array(); - } + // Identification feature set control classes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon + web::json::value make_ident_beacon_class() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager - web::json::value make_nc_class_manager_properties() - { - using web::json::value; + return details::make_class_descriptor(U("NcIdentBeacon class descriptor"), nc_ident_beacon_class_id, U("NcIdentBeacon"), make_ident_beacon_properties(), make_ident_beacon_methods(), make_ident_beacon_events()); + } - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Descriptions of all control classes in the device (descriptors do not contain inherited elements)"), nc_class_manager_control_classes_property_id, nmos::fields::nc::control_classes, U("NcClassDescriptor"), true, false, true, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Descriptions of all data types in the device (descriptors do not contain inherited elements)"), nc_class_manager_datatypes_property_id, nmos::fields::nc::datatypes, U("NcDatatypeDescriptor"), true, false, true, false, value::null())); + // Monitoring feature set control classes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor + web::json::value make_status_monitor_class() + { + using web::json::value; - return properties; - } - web::json::value make_nc_class_manager_methods() - { - using web::json::value; + return details::make_class_descriptor(U("NcStatusMonitor class descriptor"), nc_status_monitor_class_id, U("NcStatusMonitor"), make_status_monitor_properties(), make_status_monitor_methods(), make_status_monitor_events()); + } - auto methods = value::array(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor_class() { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::include_inherited, U("NcBoolean"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Get a single class descriptor"), nc_class_manager_get_control_class_method_id, U("GetControlClass"), U("NcMethodResultClassDescriptor"), parameters, false)); + using web::json::value; + + return details::make_class_descriptor(U("NcReceiverMonitor class descriptor"), nc_receiver_monitor_class_id, U("NcReceiverMonitor"), make_receiver_monitor_properties(), make_receiver_monitor_methods(), make_receiver_monitor_events()); } + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor + web::json::value make_sender_monitor_class() { - auto parameters = value::array(); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("name of datatype"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(parameters, details::make_nc_parameter_descriptor(U("If set the descriptor would contain all inherited elements"), nmos::fields::nc::include_inherited, U("NcBoolean"), false, false, value::null())); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Get a single datatype descriptor"), nc_class_manager_get_datatype_method_id, U("GetDatatype"), U("NcMethodResultDatatypeDescriptor"), parameters, false)); + using web::json::value; + + return details::make_class_descriptor(U("NcSenderMonitor class descriptor"), nc_sender_monitor_class_id, U("NcSenderMonitor"), make_sender_monitor_properties(), make_sender_monitor_methods(), make_sender_monitor_events()); } - return methods; - } - web::json::value make_nc_class_manager_events() - { - using web::json::value; + // Device configuration feature set control classes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + web::json::value make_bulk_properties_manager_class() + { + using web::json::value; - return value::array(); - } + return details::make_class_descriptor(U("NcBulkPropertiesManager class descriptor"), nc_bulk_properties_manager_class_id, U("NcBulkPropertiesManager"), U("BulkPropertiesManager"), make_bulk_properties_manager_properties(), make_bulk_properties_manager_methods(), make_bulk_properties_manager_events()); + } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor - web::json::value make_nc_status_monitor_properties() - { - using web::json::value; + // Primitive datatypes + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_boolean_datatype() + { + using web::json::value; - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Overall status property"), nc_status_monitor_overall_status_property_id, nmos::fields::nc::overall_status, U("NcOverallStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Overall status message property"), nc_status_monitor_overall_status_message_property_id, nmos::fields::nc::overall_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Status reporting delay property (in seconds, default is 3s and 0 means no delay)"), nc_status_monitor_status_reporting_delay, nmos::fields::nc::status_reporting_delay, U("NcUint32"), false, false, false, false, value::null())); + return details::make_datatype_descriptor_primitive(U("Boolean primitive type"), U("NcBoolean"), value::null()); + } - return properties; - } - web::json::value make_nc_status_monitor_methods() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int16_datatype() + { + using web::json::value; - return value::array(); - } - web::json::value make_nc_status_monitor_events() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("short"), U("NcInt16"), value::null()); + } - return value::array(); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int32_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_nc_receiver_monitor_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status property"), nc_receiver_monitor_link_status_property_id, nmos::fields::nc::link_status, U("NcLinkStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status message property"), nc_receiver_monitor_link_status_message_property_id, nmos::fields::nc::link_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status transition counter property"), nc_receiver_monitor_link_status_transition_counter_property_id, nmos::fields::nc::link_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Connection status property"), nc_receiver_monitor_connection_status_property_id, nmos::fields::nc::connection_status, U("NcConnectionStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Connection status message property"), nc_receiver_monitor_connection_status_message_property_id, nmos::fields::nc::connection_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Connection status transition counter property"), nc_receiver_monitor_connection_status_transition_counter_property_id, nmos::fields::nc::connection_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status property"), nc_receiver_monitor_external_synchronization_status_property_id, nmos::fields::nc::external_synchronization_status, U("NcSynchronizationStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status message property"), nc_receiver_monitor_external_synchronization_status_message_property_id, nmos::fields::nc::external_synchronization_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status transition counter property"), nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, nmos::fields::nc::external_synchronization_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Synchronization source id property"), nc_receiver_monitor_synchronization_source_id_property_id, nmos::fields::nc::synchronization_source_id, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Stream status property"), nc_receiver_monitor_stream_status_property_id, nmos::fields::nc::stream_status, U("NcStreamStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Stream status message property"), nc_receiver_monitor_stream_status_message_property_id, nmos::fields::nc::stream_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Stream status property transition counters"), nc_receiver_monitor_stream_status_transition_counter_property_id, nmos::fields::nc::stream_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Automatic reset counters and messages property (default: true)"), nc_receiver_monitor_auto_reset_monitor_property_id, nmos::fields::nc::auto_reset_monitor, U("NcBoolean"), false, false, false, false, value::null())); - - return properties; - } - web::json::value make_nc_receiver_monitor_methods() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("long"), U("NcInt32"), value::null()); + } - auto methods = value::array(); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Gets the lost packet counters"), nc_receiver_monitor_get_lost_packet_counters_method_id, U("GetLostPacketCounters"), U("NcMethodResultCounters"), value::array(), false)); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Gets the late packet counters"), nc_receiver_monitor_get_late_packet_counters_method_id, U("GetLatePacketCounters"), U("NcMethodResultCounters"), value::array(), false)); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Resets ALL counters"), nc_receiver_monitor_reset_monitor_method_id, U("ResetCountersAndMessages"), U("NcMethodResult"), value::array(), false)); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int64_datatype() + { + using web::json::value; - return methods; - } - web::json::value make_nc_receiver_monitor_events() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("longlong"), U("NcInt64"), value::null()); + } - return value::array(); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint16_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_nc_sender_monitor_properties() - { - using web::json::value; - - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status property"), nc_sender_monitor_link_status_property_id, nmos::fields::nc::link_status, U("NcLinkStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status message property"), nc_sender_monitor_link_status_message_property_id, nmos::fields::nc::link_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Link status transition counter property"), nc_sender_monitor_link_status_transition_counter_property_id, nmos::fields::nc::link_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Transmission status property"), nc_sender_monitor_transmission_status_property_id, nmos::fields::nc::transmission_status, U("NcTransmissionStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Transmission status message property"), nc_sender_monitor_transmission_status_message_property_id, nmos::fields::nc::transmission_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Transmission status transition counter property"), nc_sender_monitor_transmission_status_transition_counter_property_id, nmos::fields::nc::transmission_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status property"), nc_sender_monitor_external_synchronization_status_property_id, nmos::fields::nc::external_synchronization_status, U("NcSynchronizationStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status message property"), nc_sender_monitor_external_synchronization_status_message_property_id, nmos::fields::nc::external_synchronization_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("External synchronization status transition counter property"), nc_sender_monitor_external_synchronization_status_transition_counter_property_id, nmos::fields::nc::external_synchronization_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Synchronization source id property"), nc_sender_monitor_synchronization_source_id_property_id, nmos::fields::nc::synchronization_source_id, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Essence status property"), nc_sender_monitor_essence_status_property_id, nmos::fields::nc::essence_status, U("NcEssenceStatus"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Essence status message property"), nc_sender_monitor_essence_status_message_property_id, nmos::fields::nc::essence_status_message, U("NcString"), true, true, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Essence status property transition counters"), nc_sender_monitor_essence_status_transition_counter_property_id, nmos::fields::nc::essence_status_transition_counter, U("NcUint64"), true, false, false, false, value::null())); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Automatic reset counters and messages property (default: true)"), nc_sender_monitor_auto_reset_monitor_property_id, nmos::fields::nc::auto_reset_monitor, U("NcBoolean"), false, false, false, false, value::null())); - - return properties; - } - web::json::value make_nc_sender_monitor_methods() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("unsignedshort"), U("NcUint16"), value::null()); + } - auto methods = value::array(); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Gets the transmission error counters"), nc_sender_monitor_get_transmission_error_counters_method_id, U("GetTransmissionErrorCounters"), U("NcMethodResultCounters"), value::array(), false)); - web::json::push_back(methods, details::make_nc_method_descriptor(U("Resets ALL counters"), nc_sender_monitor_reset_monitor_method_id, U("ResetCountersAndMessages"), U("NcMethodResult"), value::array(), false)); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint32_datatype() + { + using web::json::value; - return methods; - } - web::json::value make_nc_sender_monitor_events() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("unsignedlong"), U("NcUint32"), value::null()); + } - return value::array(); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint64_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon - web::json::value make_nc_ident_beacon_properties() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("unsignedlonglong"), U("NcUint64"), value::null()); + } - auto properties = value::array(); - web::json::push_back(properties, details::make_nc_property_descriptor(U("Indicator active state"), nc_ident_beacon_active_property_id, nmos::fields::nc::active, U("NcBoolean"), false, false, false, false, value::null())); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_float32_datatype() + { + using web::json::value; - return properties; - } - web::json::value make_nc_ident_beacon_methods() - { - using web::json::value; + return details::make_datatype_descriptor_primitive(U("unrestrictedfloat"), U("NcFloat32"), value::null()); + } - return value::array(); - } - web::json::value make_nc_ident_beacon_events() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_float64_datatype() + { + using web::json::value; - return value::array(); - } + return details::make_datatype_descriptor_primitive(U("unrestricteddouble"), U("NcFloat64"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.html - web::json::value make_nc_object_class() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_string_datatype() + { + using web::json::value; - return details::make_nc_class_descriptor(U("NcObject class descriptor"), nc_object_class_id, U("NcObject"), make_nc_object_properties(), make_nc_object_methods(), make_nc_object_events()); - } + return details::make_datatype_descriptor_primitive(U("UTF-8 string"), U("NcString"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.1.html - web::json::value make_nc_block_class() - { - using web::json::value; - return details::make_nc_class_descriptor(U("NcBlock class descriptor"), nc_block_class_id, U("NcBlock"), make_nc_block_properties(), make_nc_block_methods(), make_nc_block_events()); - } + // Standard datatypes + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcBlockMemberDescriptor.html + web::json::value make_block_member_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.2.html - web::json::value make_nc_worker_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Role of member in its containing block"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("OID of member"), nmos::fields::nc::oid, U("NcOid"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff member's OID is hardwired into device"), nmos::fields::nc::constant_oid, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("User label"), nmos::fields::nc::user_label, U("NcString"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Containing block's OID"), nmos::fields::nc::owner, U("NcOid"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor which is specific to a block member"), U("NcBlockMemberDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcWorker class descriptor"), nc_worker_class_id, U("NcWorker"), make_nc_worker_properties(), make_nc_worker_methods(), make_nc_worker_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassDescriptor.html + web::json::value make_class_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.html - web::json::value make_nc_manager_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Identity of the class"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of the class"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Role if the class has fixed role (manager classes)"), nmos::fields::nc::fixed_role, U("NcString"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property descriptors"), nmos::fields::nc::properties, U("NcPropertyDescriptor"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Method descriptors"), nmos::fields::nc::methods, U("NcMethodDescriptor"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Event descriptors"), nmos::fields::nc::events, U("NcEventDescriptor"), false, true, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a class"), U("NcClassDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcManager class descriptor"), nc_manager_class_id, U("NcManager"), make_nc_manager_properties(), make_nc_manager_methods(), make_nc_manager_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassId.html + web::json::value make_class_id_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.1.html - web::json::value make_nc_device_manager_class() - { - using web::json::value; + return details::make_datatype_typedef(U("Sequence of class ID fields"), U("NcClassId"), true, U("NcInt32"), value::null()); + } - return details::make_nc_class_descriptor(U("NcDeviceManager class descriptor"), nc_device_manager_class_id, U("NcDeviceManager"), U("DeviceManager"), make_nc_device_manager_properties(), make_nc_device_manager_methods(), make_nc_device_manager_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptor.html + web::json::value make_datatype_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.2.html - web::json::value make_nc_class_manager_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Datatype name"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Type: Primitive, Typedef, Struct, Enum"), nmos::fields::nc::type, U("NcDatatypeType"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Base datatype descriptor"), U("NcDatatypeDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcClassManager class descriptor"), nc_class_manager_class_id, U("NcClassManager"), U("ClassManager"), make_nc_class_manager_properties(), make_nc_class_manager_methods(), make_nc_class_manager_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorEnum.html + web::json::value make_datatype_descriptor_enum_datatype() + { + using web::json::value; - // Identification feature set control classes - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon - web::json::value make_nc_ident_beacon_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("One item descriptor per enum option"), nmos::fields::nc::items, U("NcEnumItemDescriptor"), false, true, value::null())); + return details::make_datatype_descriptor_struct(U("Enum datatype descriptor"), U("NcDatatypeDescriptorEnum"), fields, U("NcDatatypeDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcIdentBeacon class descriptor"), nc_ident_beacon_class_id, U("NcIdentBeacon"), make_nc_ident_beacon_properties(), make_nc_ident_beacon_methods(), make_nc_ident_beacon_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorPrimitive.html + web::json::value make_datatype_descriptor_primitive_datatype() + { + using web::json::value; - // Monitoring feature set control classes - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor - web::json::value make_nc_status_monitor_class() - { - using web::json::value; + auto fields = value::array(); + return details::make_datatype_descriptor_struct(U("Primitive datatype descriptor"), U("NcDatatypeDescriptorPrimitive"), fields, U("NcDatatypeDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcStatusMonitor class descriptor"), nc_status_monitor_class_id, U("NcStatusMonitor"), make_nc_status_monitor_properties(), make_nc_status_monitor_methods(), make_nc_status_monitor_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorStruct.html + web::json::value make_datatype_descriptor_struct_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_nc_receiver_monitor_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("One item descriptor per field of the struct"), nmos::fields::nc::fields, U("NcFieldDescriptor"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of the parent type if any or null if it has no parent"), nmos::fields::nc::parent_type, U("NcName"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Struct datatype descriptor"), U("NcDatatypeDescriptorStruct"), fields, U("NcDatatypeDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcReceiverMonitor class descriptor"), nc_receiver_monitor_class_id, U("NcReceiverMonitor"), make_nc_receiver_monitor_properties(), make_nc_receiver_monitor_methods(), make_nc_receiver_monitor_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorTypeDef.html + web::json::value make_datatype_descriptor_type_def_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_nc_sender_monitor_class() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Original typedef datatype name"), nmos::fields::nc::parent_type, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff type is a typedef sequence of another type"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Type def datatype descriptor"), U("NcDatatypeDescriptorTypeDef"), fields, U("NcDatatypeDescriptor"), value::null()); + } - return details::make_nc_class_descriptor(U("NcSenderMonitor class descriptor"), nc_sender_monitor_class_id, U("NcSenderMonitor"), make_nc_sender_monitor_properties(), make_nc_sender_monitor_methods(), make_nc_sender_monitor_events()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeType.html + web::json::value make_datatype_type_datatype() + { + using web::json::value; - // Primitive datatypes - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_boolean_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Primitive datatype"), U("Primitive"), 0)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Simple alias of another datatype"), U("Typedef"), 1)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Data structure"), U("Struct"), 2)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Enum datatype"), U("Enum"), 3)); + return details::make_datatype_descriptor_enum(U("Datatype type"), U("NcDatatypeType"), items, value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("Boolean primitive type"), U("NcBoolean"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDescriptor.html + web::json::value make_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int16_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Optional user facing description"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Base descriptor"), U("NcDescriptor"), fields, value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("short"), U("NcInt16"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceGenericState.html + web::json::value make_device_generic_state_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int32_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Normal operation"), U("NormalOperation"), 1)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Device is initializing"), U("Initializing"), 2)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Device is performing a software or firmware update"), U("Updating"), 3)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Device is experiencing a licensing error"), U("LicensingError"), 4)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Device is experiencing an internal error"), U("InternalError"), 5)); + return details::make_datatype_descriptor_enum(U("Device generic operational state"), U("NcDeviceGenericState"), items, value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("long"), U("NcInt32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceOperationalState.html + web::json::value make_device_operational_state_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int64_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Generic operational state"), nmos::fields::nc::generic_state, U("NcDeviceGenericState"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Specific device details"), nmos::fields::nc::device_specific_details, U("NcString"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Device operational state"), U("NcDeviceOperationalState"), fields, value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("longlong"), U("NcInt64"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcElementId.html + web::json::value make_element_id_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint16_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Level of the element"), nmos::fields::nc::level, U("NcUint16"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Index of the element"), nmos::fields::nc::index, U("NcUint16"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Class element id which contains the level and index"), U("NcElementId"), fields, value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("unsignedshort"), U("NcUint16"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEnumItemDescriptor.html + web::json::value make_enum_item_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint32_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Name of option"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Enum item numerical value"), nmos::fields::nc::value, U("NcUint16"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of an enum item"), U("NcEnumItemDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("unsignedlong"), U("NcUint32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventDescriptor.html + web::json::value make_event_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint64_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Event id with level and index"), nmos::fields::nc::id, U("NcEventId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of event"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of event data's datatype"), nmos::fields::nc::event_datatype, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a class event"), U("NcEventDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("unsignedlonglong"), U("NcUint64"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventId.html + web::json::value make_event_id_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_float32_datatype() - { - using web::json::value; + return details::make_datatype_descriptor_struct(U("Event id which contains the level and index"), U("NcEventId"), value::array(), U("NcElementId"), value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("unrestrictedfloat"), U("NcFloat32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcFieldDescriptor.html + web::json::value make_field_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_float64_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Name of field"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of field's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff field is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff field is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a field of a struct"), U("NcFieldDescriptor"), fields, U("NcDescriptor"), value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("unrestricteddouble"), U("NcFloat64"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcId.html + web::json::value make_id_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_string_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Identity handler"), U("NcId"), false, U("NcUint32"), value::null()); + } - return details::make_nc_datatype_descriptor_primitive(U("UTF-8 string"), U("NcString"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcManufacturer.html + web::json::value make_manufacturer_datatype() + { + using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Manufacturer's name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("IEEE OUI or CID of manufacturer"), nmos::fields::nc::organization_id, U("NcOrganizationId"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("URL of the manufacturer's website"), nmos::fields::nc::website, U("NcUri"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Manufacturer descriptor"), U("NcManufacturer"), fields, value::null()); + } - // Standard datatypes - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcBlockMemberDescriptor.html - web::json::value make_nc_block_member_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Role of member in its containing block"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("OID of member"), nmos::fields::nc::oid, U("NcOid"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff member's OID is hardwired into device"), nmos::fields::nc::constant_oid, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("User label"), nmos::fields::nc::user_label, U("NcString"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Containing block's OID"), nmos::fields::nc::owner, U("NcOid"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor which is specific to a block member"), U("NcBlockMemberDescriptor"), fields, U("NcDescriptor"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodDescriptor.html + web::json::value make_method_descriptor_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassDescriptor.html - web::json::value make_nc_class_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Identity of the class"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of the class"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Role if the class has fixed role (manager classes)"), nmos::fields::nc::fixed_role, U("NcString"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Property descriptors"), nmos::fields::nc::properties, U("NcPropertyDescriptor"), false, true, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Method descriptors"), nmos::fields::nc::methods, U("NcMethodDescriptor"), false, true, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Event descriptors"), nmos::fields::nc::events, U("NcEventDescriptor"), false, true, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a class"), U("NcClassDescriptor"), fields, U("NcDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Method id with level and index"), nmos::fields::nc::id, U("NcMethodId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of method"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of method result's datatype"), nmos::fields::nc::result_datatype, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Parameter descriptors if any"), nmos::fields::nc::parameters, U("NcParameterDescriptor"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a class method"), U("NcMethodDescriptor"), fields, U("NcDescriptor"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassId.html - web::json::value make_nc_class_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodId.html + web::json::value make_method_id_datatype() + { + using web::json::value; - return details::make_nc_datatype_typedef(U("Sequence of class ID fields"), U("NcClassId"), true, U("NcInt32"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Method id which contains the level and index"), U("NcMethodId"), value::array(), U("NcElementId"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptor.html - web::json::value make_nc_datatype_descriptor_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResult.html + web::json::value make_method_result_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Datatype name"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Type: Primitive, Typedef, Struct, Enum"), nmos::fields::nc::type, U("NcDatatypeType"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Base datatype descriptor"), U("NcDatatypeDescriptor"), fields, U("NcDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Status for the invoked method"), nmos::fields::nc::status, U("NcMethodStatus"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Base result of the invoked method"), U("NcMethodResult"), fields, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorEnum.html - web::json::value make_nc_datatype_descriptor_enum_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultBlockMemberDescriptors.html + web::json::value make_method_result_block_member_descriptors_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("One item descriptor per enum option"), nmos::fields::nc::items, U("NcEnumItemDescriptor"), false, true, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Enum datatype descriptor"), U("NcDatatypeDescriptorEnum"), fields, U("NcDatatypeDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Block member descriptors method result value"), nmos::fields::nc::value, U("NcBlockMemberDescriptor"), false, true, value::null())); + return details::make_datatype_descriptor_struct(U("Method result containing block member descriptors as the value"), U("NcMethodResultBlockMemberDescriptors"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorPrimitive.html - web::json::value make_nc_datatype_descriptor_primitive_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultClassDescriptor.html + web::json::value make_method_result_class_descriptor_datatype() + { + using web::json::value; - auto fields = value::array(); - return details::make_nc_datatype_descriptor_struct(U("Primitive datatype descriptor"), U("NcDatatypeDescriptorPrimitive"), fields, U("NcDatatypeDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Class descriptor method result value"), nmos::fields::nc::value, U("NcClassDescriptor"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Method result containing a class descriptor as the value"), U("NcMethodResultClassDescriptor"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorStruct.html - web::json::value make_nc_datatype_descriptor_struct_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultDatatypeDescriptor.html + web::json::value make_method_result_datatype_descriptor_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("One item descriptor per field of the struct"), nmos::fields::nc::fields, U("NcFieldDescriptor"), false, true, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of the parent type if any or null if it has no parent"), nmos::fields::nc::parent_type, U("NcName"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Struct datatype descriptor"), U("NcDatatypeDescriptorStruct"), fields, U("NcDatatypeDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Datatype descriptor method result value"), nmos::fields::nc::value, U("NcDatatypeDescriptor"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Method result containing a datatype descriptor as the value"), U("NcMethodResultDatatypeDescriptor"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorTypeDef.html - web::json::value make_nc_datatype_descriptor_type_def_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultError.html + web::json::value make_method_result_error_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Original typedef datatype name"), nmos::fields::nc::parent_type, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff type is a typedef sequence of another type"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Type def datatype descriptor"), U("NcDatatypeDescriptorTypeDef"), fields, U("NcDatatypeDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Error message"), nmos::fields::nc::error_message, U("NcString"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Error result - to be used when the method call encounters an error"), U("NcMethodResultError"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeType.html - web::json::value make_nc_datatype_type_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Primitive datatype"), U("Primitive"), 0)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Simple alias of another datatype"), U("Typedef"), 1)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Data structure"), U("Struct"), 2)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Enum datatype"), U("Enum"), 3)); - return details::make_nc_datatype_descriptor_enum(U("Datatype type"), U("NcDatatypeType"), items, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultId.html + web::json::value make_method_result_id_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDescriptor.html - web::json::value make_nc_descriptor_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Id result value"), nmos::fields::nc::value, U("NcId"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Id method result"), U("NcMethodResultId"), fields, U("NcMethodResult"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional user facing description"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Base descriptor"), U("NcDescriptor"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultLength.html + web::json::value make_method_result_length_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceGenericState.html - web::json::value make_nc_device_generic_state_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Normal operation"), U("NormalOperation"), 1)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Device is initializing"), U("Initializing"), 2)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Device is performing a software or firmware update"), U("Updating"), 3)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Device is experiencing a licensing error"), U("LicensingError"), 4)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Device is experiencing an internal error"), U("InternalError"), 5)); - return details::make_nc_datatype_descriptor_enum(U("Device generic operational state"), U("NcDeviceGenericState"), items, value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Length result value"), nmos::fields::nc::value, U("NcUint32"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Length method result"), U("NcMethodResultLength"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceOperationalState.html - web::json::value make_nc_device_operational_state_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultPropertyValue.html + web::json::value make_method_result_property_value_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Generic operational state"), nmos::fields::nc::generic_state, U("NcDeviceGenericState"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Specific device details"), nmos::fields::nc::device_specific_details, U("NcString"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Device operational state"), U("NcDeviceOperationalState"), fields, value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Getter method value for the associated property"), nmos::fields::nc::value, true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Result when invoking the getter method associated with a property"), U("NcMethodResultPropertyValue"), fields, U("NcMethodResult"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcElementId.html - web::json::value make_nc_element_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodStatus.html + web::json::value make_method_status_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Level of the element"), nmos::fields::nc::level, U("NcUint16"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Index of the element"), nmos::fields::nc::index, U("NcUint16"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Class element id which contains the level and index"), U("NcElementId"), fields, value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method call was successful"), U("Ok"), 200)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method call was successful but targeted property is deprecated"), U("PropertyDeprecated"), 298)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method call was successful but method is deprecated"), U("MethodDeprecated"), 299)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Badly-formed command (e.g. the incoming command has invalid message encoding and cannot be parsed by the underlying protocol)"), U("BadCommandFormat"), 400)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Client is not authorized"), U("Unauthorized"), 401)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Command addresses a nonexistent object"), U("BadOid"), 404)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Attempt to change read-only state"), U("Readonly"), 405)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method call is invalid in current operating context (e.g. attempting to invoke a method when the object is disabled)"), U("InvalidRequest"), 406)); + web::json::push_back(items, details::make_enum_item_descriptor(U("There is a conflict with the current state of the device"), U("Conflict"), 409)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Something was too big"), U("BufferOverflow"), 413)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Index is outside the available range"), U("IndexOutOfBounds"), 414)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method parameter does not meet expectations (e.g. attempting to invoke a method with an invalid type for one of its parameters)"), U("ParameterError"), 417)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Addressed object is locked"), U("Locked"), 423)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Internal device error"), U("DeviceError"), 500)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Addressed method is not implemented by the addressed object"), U("MethodNotImplemented"), 501)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Addressed property is not implemented by the addressed object"), U("PropertyNotImplemented"), 502)); + web::json::push_back(items, details::make_enum_item_descriptor(U("The device is not ready to handle any commands"), U("NotReady"), 503)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Method call did not finish within the allotted time"), U("Timeout"), 504)); + return details::make_datatype_descriptor_enum(U("Method invokation status"), U("NcMethodStatus"), items, value::null()); + } + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcName.html + web::json::value make_name_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEnumItemDescriptor.html - web::json::value make_nc_enum_item_descriptor_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Programmatically significant name, alphanumerics + underscore, no spaces"), U("NcName"), false, U("NcString"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of option"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Enum item numerical value"), nmos::fields::nc::value, U("NcUint16"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of an enum item"), U("NcEnumItemDescriptor"), fields, U("NcDescriptor"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOid.html + web::json::value make_oid_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventDescriptor.html - web::json::value make_nc_event_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Event id with level and index"), nmos::fields::nc::id, U("NcEventId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of event"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of event data's datatype"), nmos::fields::nc::event_datatype, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a class event"), U("NcEventDescriptor"), fields, U("NcDescriptor"), value::null()); - } + return details::make_datatype_typedef(U("Object id"), U("NcOid"), false, U("NcUint32"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventId.html - web::json::value make_nc_event_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOrganizationId.html + web::json::value make_organization_id_datatype() + { + using web::json::value; - return details::make_nc_datatype_descriptor_struct(U("Event id which contains the level and index"), U("NcEventId"), value::array(), U("NcElementId"), value::null()); - } + return details::make_datatype_typedef(U("Unique 24-bit organization id"), U("NcOrganizationId"), false, U("NcInt32"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcFieldDescriptor.html - web::json::value make_nc_field_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of field"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of field's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff field is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff field is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a field of a struct"), U("NcFieldDescriptor"), fields, U("NcDescriptor"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraints.html + web::json::value make_parameter_constraints_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcId.html - web::json::value make_nc_id_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Default value"), nmos::fields::nc::default_value, true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Abstract parameter constraints class"), U("NcParameterConstraints"), fields, value::null()); + } - return details::make_nc_datatype_typedef(U("Identity handler"), U("NcId"), false, U("NcUint32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsNumber.html + web::json::value make_parameter_constraints_number_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcManufacturer.html - web::json::value make_nc_manufacturer_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Optional minimum"), nmos::fields::nc::minimum, true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional maximum"), nmos::fields::nc::maximum, true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional step"), nmos::fields::nc::step, true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Number parameter constraints class"), U("NcParameterConstraintsNumber"), fields, U("NcParameterConstraints"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Manufacturer's name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("IEEE OUI or CID of manufacturer"), nmos::fields::nc::organization_id, U("NcOrganizationId"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("URL of the manufacturer's website"), nmos::fields::nc::website, U("NcUri"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Manufacturer descriptor"), U("NcManufacturer"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsString.html + web::json::value make_parameter_constraints_string_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodDescriptor.html - web::json::value make_nc_method_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Method id with level and index"), nmos::fields::nc::id, U("NcMethodId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of method"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of method result's datatype"), nmos::fields::nc::result_datatype, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Parameter descriptors if any"), nmos::fields::nc::parameters, U("NcParameterDescriptor"), false, true, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a class method"), U("NcMethodDescriptor"), fields, U("NcDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Maximum characters allowed"), nmos::fields::nc::max_characters, U("NcUint32"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Regex pattern"), nmos::fields::nc::pattern, U("NcRegex"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("String parameter constraints class"), U("NcParameterConstraintsString"), fields, U("NcParameterConstraints"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodId.html - web::json::value make_nc_method_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterDescriptor.html + web::json::value make_parameter_descriptor_datatype() + { + using web::json::value; - return details::make_nc_datatype_descriptor_struct(U("Method id which contains the level and index"), U("NcMethodId"), value::array(), U("NcElementId"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Name of parameter"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of parameter's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a method parameter"), U("NcParameterDescriptor"), fields, U("NcDescriptor"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResult.html - web::json::value make_nc_method_result_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcProduct.html + web::json::value make_product_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Status for the invoked method"), nmos::fields::nc::status, U("NcMethodStatus"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Base result of the invoked method"), U("NcMethodResult"), fields, value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Product name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Manufacturer's unique key to product - model number, SKU, etc"), nmos::fields::nc::key, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Manufacturer's product revision level code"), nmos::fields::nc::revision_level, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Brand name under which product is sold"), nmos::fields::nc::brand_name, U("NcString"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Unique UUID of product (not product instance)"), nmos::fields::nc::uuid, U("NcUuid"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Text description of product"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Product descriptor"), U("NcProduct"), fields, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultBlockMemberDescriptors.html - web::json::value make_nc_method_result_block_member_descriptors_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangeType.html + web::json::value make_property_change_type_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Block member descriptors method result value"), nmos::fields::nc::value, U("NcBlockMemberDescriptor"), false, true, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Method result containing block member descriptors as the value"), U("NcMethodResultBlockMemberDescriptors"), fields, U("NcMethodResult"), value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Current value changed"), U("ValueChanged"), 0)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Sequence item added"), U("SequenceItemAdded"), 1)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Sequence item changed"), U("SequenceItemChanged"), 2)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Sequence item removed"), U("SequenceItemRemoved"), 3)); + return details::make_datatype_descriptor_enum(U("Type of property change"), U("NcPropertyChangeType"), items, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultClassDescriptor.html - web::json::value make_nc_method_result_class_descriptor_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangedEventData.html + web::json::value make_property_changed_event_data_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Class descriptor method result value"), nmos::fields::nc::value, U("NcClassDescriptor"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Method result containing a class descriptor as the value"), U("NcMethodResultClassDescriptor"), fields, U("NcMethodResult"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("The id of the property that changed"), nmos::fields::nc::property_id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Information regarding the change type"), nmos::fields::nc::change_type, U("NcPropertyChangeType"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property-type specific value"), nmos::fields::nc::value, true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Index of sequence item if the property is a sequence"), nmos::fields::nc::sequence_item_index,U("NcId"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Payload of property-changed event"), U("NcPropertyChangedEventData"), fields, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultDatatypeDescriptor.html - web::json::value make_nc_method_result_datatype_descriptor_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraints.html + web::json::value make_property_contraints_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Datatype descriptor method result value"), nmos::fields::nc::value, U("NcDatatypeDescriptor"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Method result containing a datatype descriptor as the value"), U("NcMethodResultDatatypeDescriptor"), fields, U("NcMethodResult"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("The id of the property being constrained"), nmos::fields::nc::property_id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional default value"), nmos::fields::nc::default_value, true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Property constraints class"), U("NcPropertyConstraints"), fields, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultError.html - web::json::value make_nc_method_result_error_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsNumber.html + web::json::value make_property_constraints_number_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Error message"), nmos::fields::nc::error_message, U("NcString"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Error result - to be used when the method call encounters an error"), U("NcMethodResultError"), fields, U("NcMethodResult"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Optional minimum"), nmos::fields::nc::minimum, true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional maximum"), nmos::fields::nc::maximum, true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional step"), nmos::fields::nc::step, true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Number property constraints class"), U("NcPropertyConstraintsNumber"), fields, U("NcPropertyConstraints"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultId.html - web::json::value make_nc_method_result_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsString.html + web::json::value make_property_constraints_string_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Id result value"), nmos::fields::nc::value, U("NcId"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Id method result"), U("NcMethodResultId"), fields, U("NcMethodResult"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Maximum characters allowed"), nmos::fields::nc::max_characters, U("NcUint32"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Regex pattern"), nmos::fields::nc::pattern, U("NcRegex"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("String property constraints class"), U("NcPropertyConstraintsString"), fields, U("NcPropertyConstraints"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultLength.html - web::json::value make_nc_method_result_length_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyDescriptor.html + web::json::value make_property_descriptor_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Length result value"), nmos::fields::nc::value, U("NcUint32"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Length method result"), U("NcMethodResultLength"), fields, U("NcMethodResult"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Property id with level and index"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of property"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Name of property's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is read-only"), nmos::fields::nc::is_read_only, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Descriptor of a class property"), U("NcPropertyDescriptor"), fields, U("NcDescriptor"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultPropertyValue.html - web::json::value make_nc_method_result_property_value_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyId.html + web::json::value make_property_id_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Getter method value for the associated property"), nmos::fields::nc::value, true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Result when invoking the getter method associated with a property"), U("NcMethodResultPropertyValue"), fields, U("NcMethodResult"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Property id which contains the level and index"), U("NcPropertyId"), value::array(), U("NcElementId"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodStatus.html - web::json::value make_nc_method_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method call was successful"), U("Ok"), 200)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method call was successful but targeted property is deprecated"), U("PropertyDeprecated"), 298)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method call was successful but method is deprecated"), U("MethodDeprecated"), 299)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Badly-formed command (e.g. the incoming command has invalid message encoding and cannot be parsed by the underlying protocol)"), U("BadCommandFormat"), 400)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Client is not authorized"), U("Unauthorized"), 401)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Command addresses a nonexistent object"), U("BadOid"), 404)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Attempt to change read-only state"), U("Readonly"), 405)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method call is invalid in current operating context (e.g. attempting to invoke a method when the object is disabled)"), U("InvalidRequest"), 406)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("There is a conflict with the current state of the device"), U("Conflict"), 409)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Something was too big"), U("BufferOverflow"), 413)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Index is outside the available range"), U("IndexOutOfBounds"), 414)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method parameter does not meet expectations (e.g. attempting to invoke a method with an invalid type for one of its parameters)"), U("ParameterError"), 417)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Addressed object is locked"), U("Locked"), 423)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Internal device error"), U("DeviceError"), 500)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Addressed method is not implemented by the addressed object"), U("MethodNotImplemented"), 501)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Addressed property is not implemented by the addressed object"), U("PropertyNotImplemented"), 502)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("The device is not ready to handle any commands"), U("NotReady"), 503)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Method call did not finish within the allotted time"), U("Timeout"), 504)); - return details::make_nc_datatype_descriptor_enum(U("Method invokation status"), U("NcMethodStatus"), items, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRegex.html + web::json::value make_regex_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcName.html - web::json::value make_nc_name_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Regex pattern"), U("NcRegex"), false, U("NcString"), value::null()); + } - return details::make_nc_datatype_typedef(U("Programmatically significant name, alphanumerics + underscore, no spaces"), U("NcName"), false, U("NcString"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcResetCause.html + web::json::value make_reset_cause_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOid.html - web::json::value make_nc_oid_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Power on"), U("PowerOn"), 1)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Internal error"), U("InternalError"), 2)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Upgrade"), U("Upgrade"), 3)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Controller request"), U("ControllerRequest"), 4)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Manual request from the front panel"), U("ManualReset"), 5)); + return details::make_datatype_descriptor_enum(U("Reset cause enum"), U("NcResetCause"), items, value::null()); + } - return details::make_nc_datatype_typedef(U("Object id"), U("NcOid"), false, U("NcUint32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRolePath.html + web::json::value make_role_path_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOrganizationId.html - web::json::value make_nc_organization_id_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Role path"), U("NcRolePath"), true, U("NcString"), value::null()); + } - return details::make_nc_datatype_typedef(U("Unique 24-bit organization id"), U("NcOrganizationId"), false, U("NcInt32"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTimeInterval.html + web::json::value make_time_interval_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraints.html - web::json::value make_nc_parameter_constraints_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Time interval described in nanoseconds"), U("NcTimeInterval"), false, U("NcInt64"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Default value"), nmos::fields::nc::default_value, true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Abstract parameter constraints class"), U("NcParameterConstraints"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpoint.html + web::json::value make_touchpoint_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsNumber.html - web::json::value make_nc_parameter_constraints_number_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Context namespace"), nmos::fields::nc::context_namespace, U("NcString"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Base touchpoint class"), U("NcTouchpoint"), fields, value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional minimum"), nmos::fields::nc::minimum, true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional maximum"), nmos::fields::nc::maximum, true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional step"), nmos::fields::nc::step, true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Number parameter constraints class"), U("NcParameterConstraintsNumber"), fields, U("NcParameterConstraints"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmos.html + web::json::value make_touchpoint_nmos_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsString.html - web::json::value make_nc_parameter_constraints_string_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Context NMOS resource"), nmos::fields::nc::resource, U("NcTouchpointResourceNmos"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Touchpoint class for NMOS resources"), U("NcTouchpointNmos"), fields, U("NcTouchpoint"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Maximum characters allowed"), nmos::fields::nc::max_characters, U("NcUint32"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Regex pattern"), nmos::fields::nc::pattern, U("NcRegex"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("String parameter constraints class"), U("NcParameterConstraintsString"), fields, U("NcParameterConstraints"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmosChannelMapping.html + web::json::value make_touchpoint_nmos_channel_mapping_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterDescriptor.html - web::json::value make_nc_parameter_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of parameter"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of parameter's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a method parameter"), U("NcParameterDescriptor"), fields, U("NcDescriptor"), value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Context Channel Mapping resource"), nmos::fields::nc::resource,U("NcTouchpointResourceNmosChannelMapping"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Touchpoint class for NMOS IS-08 resources"), U("NcTouchpointNmosChannelMapping"), fields, U("NcTouchpoint"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcProduct.html - web::json::value make_nc_product_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Product name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Manufacturer's unique key to product - model number, SKU, etc"), nmos::fields::nc::key, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Manufacturer's product revision level code"), nmos::fields::nc::revision_level, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Brand name under which product is sold"), nmos::fields::nc::brand_name, U("NcString"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Unique UUID of product (not product instance)"), nmos::fields::nc::uuid, U("NcUuid"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Text description of product"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Product descriptor"), U("NcProduct"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResource.html + web::json::value make_touchpoint_resource_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangeType.html - web::json::value make_nc_property_change_type_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Current value changed"), U("ValueChanged"), 0)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Sequence item added"), U("SequenceItemAdded"), 1)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Sequence item changed"), U("SequenceItemChanged"), 2)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Sequence item removed"), U("SequenceItemRemoved"), 3)); - return details::make_nc_datatype_descriptor_enum(U("Type of property change"), U("NcPropertyChangeType"), items, value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("The type of the resource"), nmos::fields::nc::resource_type, U("NcString"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Touchpoint resource class"), U("NcTouchpointResource"), fields, value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangedEventData.html - web::json::value make_nc_property_changed_event_data_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("The id of the property that changed"), nmos::fields::nc::property_id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Information regarding the change type"), nmos::fields::nc::change_type, U("NcPropertyChangeType"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Property-type specific value"), nmos::fields::nc::value, true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Index of sequence item if the property is a sequence"), nmos::fields::nc::sequence_item_index,U("NcId"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Payload of property-changed event"), U("NcPropertyChangedEventData"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmos.html + web::json::value make_touchpoint_resource_nmos_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraints.html - web::json::value make_nc_property_contraints_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("NMOS resource UUID"), nmos::fields::nc::id, U("NcUuid"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Touchpoint resource class for NMOS resources"), U("NcTouchpointResourceNmos"), fields, U("NcTouchpointResource"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("The id of the property being constrained"), nmos::fields::nc::property_id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional default value"), nmos::fields::nc::default_value, true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Property constraints class"), U("NcPropertyConstraints"), fields, value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmosChannelMapping.html + web::json::value make_touchpoint_resource_nmos_channel_mapping_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsNumber.html - web::json::value make_nc_property_constraints_number_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("IS-08 Audio Channel Mapping input or output id"), nmos::fields::nc::io_id, U("NcString"), false, false, value::null())); + return details::make_datatype_descriptor_struct(U("Touchpoint resource class for NMOS resources"), U("NcTouchpointResourceNmosChannelMapping"), fields, U("NcTouchpointResourceNmos"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional minimum"), nmos::fields::nc::minimum, true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional maximum"), nmos::fields::nc::maximum, true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional step"), nmos::fields::nc::step, true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Number property constraints class"), U("NcPropertyConstraintsNumber"), fields, U("NcPropertyConstraints"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUri.html + web::json::value make_uri_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsString.html - web::json::value make_nc_property_constraints_string_datatype() - { - using web::json::value; + return details::make_datatype_typedef(U("Uniform resource identifier"), U("NcUri"), false, U("NcString"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Maximum characters allowed"), nmos::fields::nc::max_characters, U("NcUint32"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Regex pattern"), nmos::fields::nc::pattern, U("NcRegex"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("String property constraints class"), U("NcPropertyConstraintsString"), fields, U("NcPropertyConstraints"), value::null()); - } + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUuid.html + web::json::value make_uuid_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyDescriptor.html - web::json::value make_nc_property_descriptor_datatype() - { - using web::json::value; - - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Property id with level and index"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of property"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Name of property's datatype. Can only ever be null if the type is any"), nmos::fields::nc::type_name, U("NcName"), true, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is read-only"), nmos::fields::nc::is_read_only, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is nullable"), nmos::fields::nc::is_nullable, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is a sequence"), nmos::fields::nc::is_sequence, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("TRUE iff property is marked as deprecated"), nmos::fields::nc::is_deprecated, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Optional constraints on top of the underlying data type"), nmos::fields::nc::constraints, U("NcParameterConstraints"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Descriptor of a class property"), U("NcPropertyDescriptor"), fields, U("NcDescriptor"), value::null()); - } + return details::make_datatype_typedef(U("UUID"), U("NcUuid"), false, U("NcString"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyId.html - web::json::value make_nc_property_id_datatype() - { - using web::json::value; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcVersionCode.html + web::json::value make_version_code_datatype() + { + using web::json::value; - return details::make_nc_datatype_descriptor_struct(U("Property id which contains the level and index"), U("NcPropertyId"), value::array(), U("NcElementId"), value::null()); - } + return details::make_datatype_typedef(U("Version code in semantic versioning format"), U("NcVersionCode"), false, U("NcString"), value::null()); + } - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRegex.html - web::json::value make_nc_regex_datatype() - { - using web::json::value; + // Monitoring datatype defintions + // + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncconnectionstatus + web::json::value make_connection_status_datatype() + { + using web::json::value; - return details::make_nc_datatype_typedef(U("Regex pattern"), U("NcRegex"), false, U("NcString"), value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_connection_status::status::inactive)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_connection_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_connection_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_connection_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Connection status enum data type"), U("NcConnectionStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nccounter + web::json::value make_counter_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcResetCause.html - web::json::value make_nc_reset_cause_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Power on"), U("PowerOn"), 1)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Internal error"), U("InternalError"), 2)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Upgrade"), U("Upgrade"), 3)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Controller request"), U("ControllerRequest"), 4)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Manual request from the front panel"), U("ManualReset"), 5)); - return details::make_nc_datatype_descriptor_enum(U("Reset cause enum"), U("NcResetCause"), items, value::null()); - } + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Counter name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Counter value"), nmos::fields::nc::value, U("NcUint64"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Description"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); + return details::make_datatype_descriptor_struct(U("Counter data type"), U("NcCounter"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncessencestatus + web::json::value make_essence_status_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRolePath.html - web::json::value make_nc_role_path_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_essence_status::status::inactive)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_essence_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_essence_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_essence_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Essence status enum data type"), U("NcEssenceStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nclinkstatus + web::json::value make_link_status_datatype() + { + using web::json::value; - return details::make_nc_datatype_typedef(U("Role path"), U("NcRolePath"), true, U("NcString"), value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("All the associated network interfaces are up"), U("AllUp"), nc_link_status::status::all_up)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Some of the associated network interfaces are down"), U("SomeDown"), nc_link_status::status::some_down)); + web::json::push_back(items, details::make_enum_item_descriptor(U("All the associated network interfaces are down"), U("AllDown"), nc_link_status::status::all_down)); + return details::make_datatype_descriptor_enum(U("Link status enum data type"), U("NcLinkStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncoverallstatus + web::json::value make_overall_status_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTimeInterval.html - web::json::value make_nc_time_interval_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_overall_status::status::inactive)); + web::json::push_back(items, details::make_enum_item_descriptor(U("The overall status is healthy"), U("Healthy"), nc_overall_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("The overall status is partially healthy"), U("PartiallyHealthy"), nc_overall_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("The overall status is unhealthy"), U("Unhealthy"), nc_overall_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Overall status enum data type"), U("NcOverallStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsynchronizationstatus + web::json::value make_synchronization_status_datatype() + { + using web::json::value; - return details::make_nc_datatype_typedef(U("Time interval described in nanoseconds"), U("NcTimeInterval"), false, U("NcInt64"), value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Feature not in use"), U("NotUsed"), nc_synchronization_status::status::not_used)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Locked to a synchronization source"), U("Healthy"), nc_synchronization_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Partially locked to a synchronization source"), U("PartiallyHealthy"), nc_synchronization_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Not locked to a synchronization source"), U("Unhealthy"), nc_synchronization_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Synchronization status enum data type"), U("NcSynchronizationStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstreamstatus + web::json::value make_stream_status_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpoint.html - web::json::value make_nc_touchpoint_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_stream_status::status::inactive)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_stream_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_stream_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_stream_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Stream status enum data type"), U("NcStreamStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nctransmissionstatus + web::json::value make_transmission_status_datatype() + { + using web::json::value; - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Context namespace"), nmos::fields::nc::context_namespace, U("NcString"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Base touchpoint class"), U("NcTouchpoint"), fields, value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_transmission_status::status::inactive)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_transmission_status::status::healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_transmission_status::status::partially_healthy)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_transmission_status::status::unhealthy)); + return details::make_datatype_descriptor_enum(U("Transmission status enum data type"), U("NcTransmissionStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncmethodresultcounters + web::json::value make_method_result_counters_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmos.html - web::json::value make_nc_touchpoint_nmos_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Counters"), nmos::fields::nc::value, U("NcCounter"), false, true, value::null())); + return details::make_datatype_descriptor_struct(U("Counter method result"), U("NcMethodResultCounters"), fields, U("NcMethodResult"), value::null()); + } - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Context NMOS resource"), nmos::fields::nc::resource, U("NcTouchpointResourceNmos"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Touchpoint class for NMOS resources"), U("NcTouchpointNmos"), fields, U("NcTouchpoint"), value::null()); - } + // Device Configuration datatypes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestoremode + web::json::value make_restore_mode_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmosChannelMapping.html - web::json::value make_nc_touchpoint_nmos_channel_mapping_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore mode is Modify"), U("Modify"), 0)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore mode is Rebuild"), U("Rebuild"), 1)); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Context Channel Mapping resource"), nmos::fields::nc::resource,U("NcTouchpointResourceNmosChannelMapping"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Touchpoint class for NMOS IS-08 resources"), U("NcTouchpointNmosChannelMapping"), fields, U("NcTouchpoint"), value::null()); - } + return details::make_datatype_descriptor_enum(U("Restore mode enumeration"), U("NcRestoreMode"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyholder + web::json::value make_property_holder_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResource.html - web::json::value make_nc_touchpoint_resource_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property descriptor"), nmos::fields::nc::descriptor, U("NcPropertyDescriptor"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property value"), nmos::fields::nc::value, true, false, value::null())); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("The type of the resource"), nmos::fields::nc::resource_type, U("NcString"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Touchpoint resource class"), U("NcTouchpointResource"), fields, value::null()); - } + return details::make_datatype_descriptor_struct(U("Property holder descriptor"), U("NcPropertyHolder"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiesholder + web::json::value make_object_properties_holder_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmos.html - web::json::value make_nc_touchpoint_resource_nmos_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Object role path"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Sequence of role paths which are a dependency for this object"), nmos::fields::nc::dependency_paths, U("NcRolePath"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Sequence of class ids allowed as members of the block"), nmos::fields::nc::allowed_members_classes, U("NcClassId"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Object properties"), nmos::fields::nc::values, U("NcPropertyHolder"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Describes if the object is rebuildable"), nmos::fields::nc::is_rebuildable, U("NcBoolean"), false, false, value::null())); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("NMOS resource UUID"), nmos::fields::nc::id, U("NcUuid"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Touchpoint resource class for NMOS resources"), U("NcTouchpointResourceNmos"), fields, U("NcTouchpointResource"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Object properties holder descriptor"), U("NcObjectPropertiesHolder"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesholder + web::json::value make_bulk_properties_holder_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmosChannelMapping.html - web::json::value make_nc_touchpoint_resource_nmos_channel_mapping_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Optional vendor specific fingerprinting mechanism used for validation purposes"), nmos::fields::nc::validation_fingerprint, U("NcString"), true, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Values by rolePath"), nmos::fields::nc::values, U("NcObjectPropertiesHolder"), false, true, value::null())); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("IS-08 Audio Channel Mapping input or output id"), nmos::fields::nc::io_id, U("NcString"), false, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Touchpoint resource class for NMOS resources"), U("NcTouchpointResourceNmosChannelMapping"), fields, U("NcTouchpointResourceNmos"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Bulk properties holder descriptor"), U("NcBulkPropertiesHolder"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestorevalidationstatus + web::json::value make_restore_validation_status_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUri.html - web::json::value make_nc_uri_datatype() - { - using web::json::value; + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore was successful"), U("Ok"), 200)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore failed"), U("Failed"), 400)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore failed because the role path is not found in the device model or the device cannot create the role path from the data set"), U("NotFound"), 404)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Restore failed due to an internal device error preventing the restore from happening"), U("DeviceError"), 500)); + return details::make_datatype_descriptor_enum(U("Restore validation status enumeration"), U("NcRestoreValidationStatus"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenoticetype + web::json::value make_property_restore_notice_type_datatype() + { + using web::json::value; - return details::make_nc_datatype_typedef(U("Uniform resource identifier"), U("NcUri"), false, U("NcString"), value::null()); - } + auto items = value::array(); + web::json::push_back(items, details::make_enum_item_descriptor(U("Warning property restore notice"), U("Warning"), nc_property_restore_notice_type::warning)); + web::json::push_back(items, details::make_enum_item_descriptor(U("Error property restore notice"), U("Error"), nc_property_restore_notice_type::error)); + return details::make_datatype_descriptor_enum(U("Property restore notice type enumeration"), U("NcPropertyRestoreNoticeType"), items, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenotice + web::json::value make_property_restore_notice_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUuid.html - web::json::value make_nc_uuid_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property name"), nmos::fields::nc::name, U("NcName"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property restore notice type"), nmos::fields::nc::notice_type, U("NcPropertyRestoreNoticeType"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Property restore notice message"), nmos::fields::nc::notice_message, U("NcString"), false, false, value::null())); - return details::make_nc_datatype_typedef(U("UUID"), U("NcUuid"), false, U("NcString"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Property restore notice descriptor"), U("NcPropertyRestoreNotice"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiessetvalidation + web::json::value make_object_properties_set_validation_datatype() + { + using web::json::value; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcVersionCode.html - web::json::value make_nc_version_code_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Object role path"), nmos::fields::nc::path, U("NcRolePath"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Validation status"), nmos::fields::nc::status, U("NcRestoreValidationStatus"), false, false, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Validation property notices"), nmos::fields::nc::notices, U("NcPropertyRestoreNotice"), false, true, value::null())); + web::json::push_back(fields, details::make_field_descriptor(U("Validation status message"), nmos::fields::nc::status_message, U("NcString"), true, false, value::null())); - return details::make_nc_datatype_typedef(U("Version code in semantic versioning format"), U("NcVersionCode"), false, U("NcString"), value::null()); - } + return details::make_datatype_descriptor_struct(U("Object properties set validation descriptor"), U("NcObjectPropertiesSetValidation"), fields, value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncmethodresultbulkpropertiesholder + web::json::value make_method_result_bulk_properties_holder_datatype() + { + using web::json::value; - // Monitoring datatype defintions - // - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncconnectionstatus - web::json::value make_nc_connection_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_connection_status::status::inactive)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_connection_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_connection_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_connection_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Connection status enum data type"), U("NcConnectionStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nccounter - web::json::value make_nc_counter_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Bulk properties holder value"), nmos::fields::nc::value, U("NcBulkPropertiesHolder"), false, false, value::null())); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Counter name"), nmos::fields::nc::name, U("NcString"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Counter value"), nmos::fields::nc::value, U("NcUint64"), false, false, value::null())); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Description"), nmos::fields::nc::description, U("NcString"), true, false, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Counter data type"), U("NcCounter"), fields, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncessencestatus - web::json::value make_nc_essence_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_essence_status::status::inactive)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_essence_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_essence_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_essence_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Essence status enum data type"), U("NcEssenceStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nclinkstatus - web::json::value make_nc_link_status_datatype() - { - using web::json::value; + return details::make_datatype_descriptor_struct(U("Method result containing bulk properties holder descriptor"), U("NcMethodResultBulkPropertiesHolder"), fields, U("NcMethodResult"), value::null()); + } + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncmethodresultobjectpropertiessetvalidation + web::json::value make_method_result_object_properties_set_validation_datatype() + { + using web::json::value; - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("All the associated network interfaces are up"), U("AllUp"), nc_link_status::status::all_up)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Some of the associated network interfaces are down"), U("SomeDown"), nc_link_status::status::some_down)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("All the associated network interfaces are down"), U("AllDown"), nc_link_status::status::all_down)); - return details::make_nc_datatype_descriptor_enum(U("Link status enum data type"), U("NcLinkStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncoverallstatus - web::json::value make_nc_overall_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_overall_status::status::inactive)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("The overall status is healthy"), U("Healthy"), nc_overall_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("The overall status is partially healthy"), U("PartiallyHealthy"), nc_overall_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("The overall status is unhealthy"), U("Unhealthy"), nc_overall_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Overall status enum data type"), U("NcOverallStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsynchronizationstatus - web::json::value make_nc_synchronization_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Feature not in use"), U("NotUsed"), nc_synchronization_status::status::not_used)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Locked to a synchronization source"), U("Healthy"), nc_synchronization_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Partially locked to a synchronization source"), U("PartiallyHealthy"), nc_synchronization_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Not locked to a synchronization source"), U("Unhealthy"), nc_synchronization_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Synchronization status enum data type"), U("NcSynchronizationStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstreamstatus - web::json::value make_nc_stream_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_stream_status::status::inactive)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_stream_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_stream_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_stream_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Stream status enum data type"), U("NcStreamStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nctransmissionstatus - web::json::value make_nc_transmission_status_datatype() - { - using web::json::value; - - auto items = value::array(); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Inactive"), U("Inactive"), nc_transmission_status::status::inactive)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and healthy"), U("Healthy"), nc_transmission_status::status::healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and partially healthy"), U("PartiallyHealthy"), nc_transmission_status::status::partially_healthy)); - web::json::push_back(items, details::make_nc_enum_item_descriptor(U("Active and unhealthy"), U("Unhealthy"), nc_transmission_status::status::unhealthy)); - return details::make_nc_datatype_descriptor_enum(U("Transmission status enum data type"), U("NcTransmissionStatus"), items, value::null()); - } - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncmethodresultcounters - web::json::value make_nc_method_result_counters_datatype() - { - using web::json::value; + auto fields = value::array(); + web::json::push_back(fields, details::make_field_descriptor(U("Object properties set path validation"), nmos::fields::nc::value, U("NcObjectPropertiesSetValidation"), false, true, value::null())); - auto fields = value::array(); - web::json::push_back(fields, details::make_nc_field_descriptor(U("Counters"), nmos::fields::nc::value, U("NcCounter"), false, true, value::null())); - return details::make_nc_datatype_descriptor_struct(U("Counter method result"), U("NcMethodResultCounters"), fields, U("NcMethodResult"), value::null()); + return details::make_datatype_descriptor_struct(U("Method result containing object properties set validation descriptor"), U("NcMethodResultObjectPropertiesSetValidation"), fields, U("NcMethodResult"), value::null()); + } } } diff --git a/Development/nmos/control_protocol_resource.h b/Development/nmos/control_protocol_resource.h index 63f60bb92..902b995b0 100644 --- a/Development/nmos/control_protocol_resource.h +++ b/Development/nmos/control_protocol_resource.h @@ -18,6 +18,10 @@ namespace nmos { struct control_protocol_resource : resource { + control_protocol_resource() + : resource() + {} + control_protocol_resource(api_version version, nmos::type type, web::json::value&& data, nmos::id id, bool never_expire) : resource(version, type, std::move(data), id, never_expire) {} @@ -38,418 +42,650 @@ namespace nmos struct control_protocol_state; } - namespace details + namespace nc { - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodresult - web::json::value make_nc_method_result(const nc_method_result& method_result); - web::json::value make_nc_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message); - web::json::value make_nc_method_result(const nc_method_result& method_result, const web::json::value& value); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid - web::json::value make_nc_element_id(const nc_element_id& element_id); - nc_element_id parse_nc_element_id(const web::json::value& element_id); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventid - web::json::value make_nc_event_id(const nc_event_id& event_id); - nc_event_id parse_nc_event_id(const web::json::value& event_id); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodid - web::json::value make_nc_method_id(const nc_method_id& method_id); - nc_method_id parse_nc_method_id(const web::json::value& method_id); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyid - web::json::value make_nc_property_id(const nc_property_id& property_id); - nc_property_id parse_nc_property_id(const web::json::value& property_id); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassid - web::json::value make_nc_class_id(const nc_class_id& class_id); - nc_class_id parse_nc_class_id(const web::json::array& class_id); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanufacturer - web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id, const web::uri& website); - web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id); - web::json::value make_nc_manufacturer(const utility::string_t& name); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncproduct - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name, const nc_uuid& uuid, const utility::string_t& description); - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name, const nc_uuid& uuid); - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, - const utility::string_t& brand_name); - web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdeviceoperationalstate - // device_specific_details can be null - web::json::value make_nc_device_operational_state(nc_device_generic_state::state generic_state, const web::json::value& device_specific_details); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblockmemberdescriptor - web::json::value make_nc_block_member_descriptor(const utility::string_t& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const utility::string_t& user_label, nc_oid owner); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassdescriptor - web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events); - web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& properties, const web::json::value& methods, const web::json::value& events); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncenumitemdescriptor - web::json::value make_nc_enum_item_descriptor(const utility::string_t& description, const nc_name& name, uint16_t val); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventdescriptor - web::json::value make_nc_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncfielddescriptor - // constraints can be null - web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethoddescriptor - // sequence parameters - web::json::value make_nc_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterdescriptor - // constraints can be null - web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertydescriptor - // constraints can be null - web::json::value make_nc_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, - bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorenum - // constraints can be null - // items: sequence - web::json::value make_nc_datatype_descriptor_enum(const utility::string_t& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorprimitive - // constraints can be null - web::json::value make_nc_datatype_descriptor_primitive(const utility::string_t& description, const nc_name& name, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorstruct - // constraints can be null - // fields: sequence - web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const utility::string_t& parent_type, const web::json::value& constraints); - web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptortypedef - web::json::value make_nc_datatype_typedef(const utility::string_t& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraints - web::json::value make_nc_property_constraints(const nc_property_id& property_id, const web::json::value& default_value); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsnumber - web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step); - web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t minimum, uint64_t maximum, uint64_t step); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsstring - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern); - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters, const nc_regex& pattern); - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters); - web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const nc_regex& pattern); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraints - web::json::value make_nc_parameter_constraints(const web::json::value& default_value); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber - web::json::value make_nc_parameter_constraints_number(uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step); - web::json::value make_nc_parameter_constraints_number(uint64_t minimum, uint64_t maximum, uint64_t step); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring - web::json::value make_nc_parameter_constraints_string(const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern); - web::json::value make_nc_parameter_constraints_string(uint32_t max_characters, const nc_regex& pattern); - web::json::value make_nc_parameter_constraints_string(uint32_t max_characters); - web::json::value make_nc_parameter_constraints_string(const nc_regex& pattern); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpoint - web::json::value make_nc_touchpoint(const utility::string_t& context_namespace); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmos - web::json::value make_nc_touchpoint_nmos(const nc_touchpoint_resource_nmos& resource); - - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmoschannelmapping - web::json::value make_nc_touchpoint_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource); + namespace details + { + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodresult + web::json::value make_method_result(const nc_method_result& method_result); + web::json::value make_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message); + web::json::value make_method_result(const nc_method_result& method_result, const web::json::value& value); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid + web::json::value make_element_id(const nc_element_id& element_id); + nc_element_id parse_element_id(const web::json::value& element_id); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventid + web::json::value make_event_id(const nc_event_id& event_id); + nc_event_id parse_event_id(const web::json::value& event_id); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethodid + web::json::value make_method_id(const nc_method_id& method_id); + nc_method_id parse_method_id(const web::json::value& method_id); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyid + web::json::value make_property_id(const nc_property_id& property_id); + nc_property_id parse_property_id(const web::json::value& property_id); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassid + web::json::value make_class_id(const nc_class_id& class_id); + nc_class_id parse_class_id(const web::json::array& class_id); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanufacturer + web::json::value make_manufacturer(const utility::string_t& name, nc_organization_id organization_id, const web::uri& website); + web::json::value make_manufacturer(const utility::string_t& name, nc_organization_id organization_id); + web::json::value make_manufacturer(const utility::string_t& name); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncproduct + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid, const utility::string_t& description); + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid); + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name); + web::json::value make_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdeviceoperationalstate + // device_specific_details can be null + web::json::value make_device_operational_state(nc_device_generic_state::state generic_state, const web::json::value& device_specific_details); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblockmemberdescriptor + web::json::value make_block_member_descriptor(const utility::string_t& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const utility::string_t& user_label, nc_oid owner); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassdescriptor + web::json::value make_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events); + web::json::value make_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& properties, const web::json::value& methods, const web::json::value& events); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncenumitemdescriptor + web::json::value make_enum_item_descriptor(const utility::string_t& description, const nc_name& name, uint16_t val); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nceventdescriptor + web::json::value make_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncfielddescriptor + // constraints can be null + web::json::value make_field_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints); + web::json::value make_field_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject - web::json::value make_nc_object(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmethoddescriptor + // sequence parameters + web::json::value make_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock - web::json::value make_nc_block(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, const web::json::value& members); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterdescriptor + // constraints can be null + web::json::value make_parameter_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints); + web::json::value make_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker - web::json::value make_nc_worker(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertydescriptor + // constraints can be null + web::json::value make_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, + bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor - web::json::value make_nc_status_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, uint64_t status_reporting_delay); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorenum + // constraints can be null + // items: sequence + web::json::value make_datatype_descriptor_enum(const utility::string_t& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_receiver_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_connection_status::status connection_status, const utility::string_t& connection_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_stream_status::status stream_status, const utility::string_t& stream_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorprimitive + // constraints can be null + web::json::value make_datatype_descriptor_primitive(const utility::string_t& description, const nc_name& name, const web::json::value& constraints); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptorstruct + // constraints can be null + // fields: sequence + web::json::value make_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const utility::string_t& parent_type, const web::json::value& constraints); + web::json::value make_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const web::json::value& constraints); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdatatypedescriptortypedef + web::json::value make_datatype_typedef(const utility::string_t& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraints + web::json::value make_property_constraints(const nc_property_id& property_id, const web::json::value& default_value); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsnumber + web::json::value make_property_constraints_number(const nc_property_id& property_id, uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step); + web::json::value make_property_constraints_number(const nc_property_id& property_id, uint64_t minimum, uint64_t maximum, uint64_t step); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyconstraintsstring + web::json::value make_property_constraints_string(const nc_property_id& property_id, const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern); + web::json::value make_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters, const nc_regex& pattern); + web::json::value make_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters); + web::json::value make_property_constraints_string(const nc_property_id& property_id, const nc_regex& pattern); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraints + web::json::value make_parameter_constraints(const web::json::value& default_value); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber + web::json::value make_parameter_constraints_number(uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step); + web::json::value make_parameter_constraints_number(uint64_t minimum, uint64_t maximum, uint64_t step); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring + web::json::value make_parameter_constraints_string(const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern); + web::json::value make_parameter_constraints_string(uint32_t max_characters, const nc_regex& pattern); + web::json::value make_parameter_constraints_string(uint32_t max_characters); + web::json::value make_parameter_constraints_string(const nc_regex& pattern); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpoint + web::json::value make_touchpoint(const utility::string_t& context_namespace); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmos + web::json::value make_touchpoint_nmos(const nc_touchpoint_resource_nmos& resource); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpointnmoschannelmapping + web::json::value make_touchpoint_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject + web::json::value make_object(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock + web::json::value make_block(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, const web::json::value& members); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker + web::json::value make_worker(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor + web::json::value make_status_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, uint64_t status_reporting_delay); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_connection_status::status connection_status, const utility::string_t& connection_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_stream_status::status stream_status, const utility::string_t& stream_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor + web::json::value make_sender_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_essence_status::status essence_status, const utility::string_t& essence_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager + web::json::value make_manager(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager + web::json::value make_device_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, + const web::json::value& manufacturer, const web::json::value& product, const utility::string_t& serial_number, + const web::json::value& user_inventory_code, const web::json::value& device_name, const web::json::value& device_role, const web::json::value& operational_state, nc_reset_cause::cause reset_cause); + + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager + web::json::value make_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + web::json::value make_bulk_properties_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesholder + web::json::value make_bulk_properties_holder(const utility::string_t& validation_fingerprint, const web::json::value& object_properties_holders); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyholder + web::json::value make_property_holder(const nc_property_id& property_id, const web::json::value& descriptor, const web::json::value& property_value); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiesholder + web::json::value make_object_properties_holder(const web::json::array& role_path, const web::json::array& property_holders, const web::json::array& dependency_paths, const web::json::array& allowed_members_classes, bool is_rebuildable); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenotice + web::json::value make_property_restore_notice(const nc_property_id& property_id, const nc_name& name, nc_property_restore_notice_type::type notice_type, const utility::string_t& notice_message); + + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiessetvalidation + web::json::value make_object_properties_set_validation(const web::json::array& role_path, nc_restore_validation_status::status status, const web::json::array& notices, const web::json::value& status_message); + } + + // command message response + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type + web::json::value make_response(int32_t handle, const web::json::value& method_result); + web::json::value make_command_response(const web::json::value& responses); + + // subscription response + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#subscription-response-message-type + web::json::value make_subscription_response(const web::json::value& subscriptions); + + // notification + // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#notification-messages + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#notification-message-type + web::json::value make_notification(nc_oid oid, const nc_event_id& event_id, const nc_property_changed_event_data& property_changed_event_data); + web::json::value make_notification_message(const web::json::value& notifications); + + // property changed notification event + // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#the-propertychanged-event + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/NcObject.html#propertychanged-event + web::json::value make_property_changed_event(nc_oid oid, const std::vector& property_changed_event_data_list); + + // error message + // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#error-messages + web::json::value make_error_message(const nc_method_result& method_result, const utility::string_t& error_message); + + // Control class models + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/#control-class-models-for-branch-v10-dev + // + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.html + web::json::value make_object_class(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.1.html + web::json::value make_block_class(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.2.html + web::json::value make_worker_class(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.html + web::json::value make_manager_class(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.1.html + web::json::value make_device_manager_class(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.2.html + web::json::value make_class_manager_class(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon + web::json::value make_ident_beacon_class(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor_class(); // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_sender_monitor(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, const web::json::value& synchronization_source_id, nc_essence_status::status essence_status, const utility::string_t& essence_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor); + web::json::value make_sender_monitor_class(); + // control classes properties/methods/events + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject + web::json::value make_object_properties(); + web::json::value make_object_methods(); + web::json::value make_object_events(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock + web::json::value make_block_properties(); + web::json::value make_block_methods(); + web::json::value make_block_events(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker + web::json::value make_worker_properties(); + web::json::value make_worker_methods(); + web::json::value make_worker_events(); // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager - web::json::value make_nc_manager(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints); - + web::json::value make_manager_properties(); + web::json::value make_manager_methods(); + web::json::value make_manager_events(); // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager - web::json::value make_nc_device_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, + web::json::value make_device_manager_properties(); + web::json::value make_device_manager_methods(); + web::json::value make_device_manager_events(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager + web::json::value make_class_manager_properties(); + web::json::value make_class_manager_methods(); + web::json::value make_class_manager_events(); + // Monitoring feature set control classes + // https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor + web::json::value make_status_monitor_properties(); + web::json::value make_status_monitor_methods(); + web::json::value make_status_monitor_events(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor + web::json::value make_receiver_monitor_properties(); + web::json::value make_receiver_monitor_methods(); + web::json::value make_receiver_monitor_events(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor + web::json::value make_sender_monitor_properties(); + web::json::value make_sender_monitor_methods(); + web::json::value make_sender_monitor_events(); + + // Identification feature set control classes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon + web::json::value make_ident_beacon_properties(); + web::json::value make_ident_beacon_methods(); + web::json::value make_ident_beacon_events(); + + // Device configuration classes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + web::json::value make_bulk_properties_manager_properties(); + web::json::value make_bulk_properties_manager_methods(); + web::json::value make_bulk_properties_manager_events(); + + // Datatype models + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/#datatype-models-for-branch-v10-dev + // + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_boolean_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int16_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int32_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_int64_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint16_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint32_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_uint64_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_float32_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_float64_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives + web::json::value make_string_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcBlockMemberDescriptor.html + web::json::value make_block_member_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassDescriptor.html + web::json::value make_class_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassId.html + web::json::value make_class_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptor.html + web::json::value make_datatype_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorEnum.html + web::json::value make_datatype_descriptor_enum_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorPrimitive.html + web::json::value make_datatype_descriptor_primitive_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorStruct.html + web::json::value make_datatype_descriptor_struct_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorTypeDef.html + web::json::value make_datatype_descriptor_type_def_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeType.html + web::json::value make_datatype_type_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDescriptor.html + web::json::value make_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceGenericState.html + web::json::value make_device_generic_state_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceOperationalState.html + web::json::value make_device_operational_state_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcElementId.html + web::json::value make_element_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEnumItemDescriptor.html + web::json::value make_enum_item_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventDescriptor.html + web::json::value make_event_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventId.html + web::json::value make_event_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcFieldDescriptor.html + web::json::value make_field_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcId.html + web::json::value make_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcManufacturer.html + web::json::value make_manufacturer_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodDescriptor.html + web::json::value make_method_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodId.html + web::json::value make_method_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResult.html + web::json::value make_method_result_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultBlockMemberDescriptors.html + web::json::value make_method_result_block_member_descriptors_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultClassDescriptor.html + web::json::value make_method_result_class_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultDatatypeDescriptor.html + web::json::value make_method_result_datatype_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultError.html + web::json::value make_method_result_error_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultId.html + web::json::value make_method_result_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultLength.html + web::json::value make_method_result_length_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultPropertyValue.html + web::json::value make_method_result_property_value_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodStatus.html + web::json::value make_method_status_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcName.html + web::json::value make_name_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOid.html + web::json::value make_oid_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOrganizationId.html + web::json::value make_organization_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraints.html + web::json::value make_parameter_constraints_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsNumber.html + web::json::value make_parameter_constraints_number_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsString.html + web::json::value make_parameter_constraints_string_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterDescriptor.html + web::json::value make_parameter_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcProduct.html + web::json::value make_product_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangeType.html + web::json::value make_property_change_type_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangedEventData.html + web::json::value make_property_changed_event_data_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraints.html + web::json::value make_property_contraints_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsNumber.html + web::json::value make_property_constraints_number_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsString.html + web::json::value make_property_constraints_string_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyDescriptor.html + web::json::value make_property_descriptor_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyId.html + web::json::value make_property_id_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRegex.html + web::json::value make_regex_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcResetCause.html + web::json::value make_reset_cause_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRolePath.html + web::json::value make_role_path_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTimeInterval.html + web::json::value make_time_interval_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpoint.html + web::json::value make_touchpoint_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmos.html + web::json::value make_touchpoint_nmos_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmosChannelMapping.html + web::json::value make_touchpoint_nmos_channel_mapping_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResource.html + web::json::value make_touchpoint_resource_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmos.html + web::json::value make_touchpoint_resource_nmos_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmosChannelMapping.html + web::json::value make_touchpoint_resource_nmos_channel_mapping_datatype(); + // See // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUri.html + web::json::value make_uri_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUuid.html + web::json::value make_uuid_datatype(); + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcVersionCode.html + web::json::value make_version_code_datatype(); + + // Monitoring feature set datatypes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#datatypes + // + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncconnectionstatus + web::json::value make_connection_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncessencestatus + web::json::value make_essence_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncoverallstatus + web::json::value make_overall_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nclinkstatus + web::json::value make_link_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsynchronizationstatus + web::json::value make_synchronization_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstreamstatus + web::json::value make_stream_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nccounter + web::json::value make_counter_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nctransmissionstatus + web::json::value make_transmission_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncmethodresultcounters + web::json::value make_method_result_counters_datatype(); + + // Device configuration feature set datatypes + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestoremode + web::json::value make_restore_mode_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyholder + web::json::value make_property_holder_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiesholder + web::json::value make_object_properties_holder_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesholder + web::json::value make_bulk_properties_holder_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestorevalidationstatus + web::json::value make_restore_validation_status_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenoticetype + web::json::value make_property_restore_notice_type_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenotice + web::json::value make_property_restore_notice_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncobjectpropertiessetvalidation + web::json::value make_object_properties_set_validation_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncmethodresultbulkpropertiesholder + web::json::value make_method_result_bulk_properties_holder_datatype(); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncmethodresultobjectpropertiessetvalidation + web::json::value make_method_result_object_properties_set_validation_datatype(); + } + + namespace details + { + // Deprecated : use nc::details::make_method_result + inline web::json::value make_nc_method_result(const nc_method_result& method_result) { return nc::details::make_method_result(method_result); }; + inline web::json::value make_nc_method_result_error(const nc_method_result& method_result, const utility::string_t& error_message) { return nc::details::make_method_result_error(method_result, error_message); }; + inline web::json::value make_nc_method_result(const nc_method_result& method_result, const web::json::value& value) { return nc::details::make_method_result(method_result, value); }; + + // Deprecated: use nc::details::make use nc::details::make_element_id + inline web::json::value make_nc_element_id(const nc_element_id& element_id) { return nc::details::make_element_id(element_id); }; + // Deprecated: use nc::details::make use nc::details::parse_element_id + inline nc_element_id parse_nc_element_id(const web::json::value& element_id) { return nc::details::parse_element_id(element_id); }; + + // Deprecated: use nc::details::make use nc::details::make_event_id + inline web::json::value make_nc_event_id(const nc_event_id& event_id) { return nc::details::make_event_id(event_id); }; + // Deprecated use nc::details::parse_event_id + inline nc_event_id parse_nc_event_id(const web::json::value& event_id) { return nc::details::parse_event_id(event_id); }; + + // Deprecated: use nc::details::make use nc::details::make_method_id + inline web::json::value make_nc_method_id(const nc_method_id& method_id) { return nc::details::make_method_id(method_id); }; + // Deprecated: use nc::details::parse_method_id + inline nc_method_id parse_nc_method_id(const web::json::value& method_id) { return nc::details::parse_method_id(method_id); }; + + // Deprecated: use nc::details::make_property_id + inline web::json::value make_nc_property_id(const nc_property_id& property_id) { return nc::details::make_property_id(property_id); }; + // Deprecated: use nc::details::parse_property_id + inline nc_property_id parse_nc_property_id(const web::json::value& property_id) { return nc::details::parse_property_id(property_id); }; + + // Deprecated: use nc::details::make_class_id + inline web::json::value make_nc_class_id(const nc_class_id& class_id) { return nc::details::make_class_id(class_id); }; + // Deprecated: use nc::details::make + inline nc_class_id parse_nc_class_id(const web::json::array& class_id) { return nc::details::parse_class_id(class_id); }; + + // Deprecated: use nc::details::make_manufacturer + inline web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id, const web::uri& website) { return nc::details::make_manufacturer(name, organization_id, website); }; + inline web::json::value make_nc_manufacturer(const utility::string_t& name, nc_organization_id organization_id) { return nc::details::make_manufacturer(name, organization_id); }; + inline web::json::value make_nc_manufacturer(const utility::string_t& name) { return nc::details::make_manufacturer(name); }; + + // Deprecated: use nc::details::make_product + inline web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid, const utility::string_t& description) { return nc::details::make_product(name, key, revision_level, brand_name, uuid, description); }; + inline web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name, const nc_uuid& uuid) { return nc::details::make_product(name, key, revision_level, brand_name, uuid); }; + inline web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level, + const utility::string_t& brand_name) { return nc::details::make_product(name, key, revision_level, brand_name); }; + inline web::json::value make_nc_product(const utility::string_t& name, const utility::string_t& key, const utility::string_t& revision_level) { return nc::details::make_product(name, key, revision_level); }; + + // Deprecated: use nc::details::make_device_operational_state + inline web::json::value make_nc_device_operational_state(nc_device_generic_state::state generic_state, const web::json::value& device_specific_details) { return nc::details::make_device_operational_state(generic_state, device_specific_details); }; + + // Deprecated: use nc::details::make_block_member_descriptor + inline web::json::value make_nc_block_member_descriptor(const utility::string_t& description, const utility::string_t& role, nc_oid oid, bool constant_oid, const nc_class_id& class_id, const utility::string_t& user_label, nc_oid owner) { return nc::details::make_block_member_descriptor(description, role, oid, constant_oid, class_id, user_label, owner); }; + + // Deprecated: use nc::details::make_class_descriptor + inline web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) { return nc::details::make_class_descriptor(description, class_id, name, fixed_role, properties, methods, events); }; + inline web::json::value make_nc_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& properties, const web::json::value& methods, const web::json::value& events) { return nc::details::make_class_descriptor(description, class_id, name, properties, methods, events); }; + + // Deprecated: use nc::details::make_enum_item_descriptor + inline web::json::value make_nc_enum_item_descriptor(const utility::string_t& description, const nc_name& name, uint16_t val) { return nc::details::make_enum_item_descriptor(description, name, val); }; + + // Deprecated: use nc::details::make_event_descriptor + inline web::json::value make_nc_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) { return nc::details::make_event_descriptor(description, id, name, event_datatype, is_deprecated); }; + + // Deprecated: use nc::details::make_field_descriptor + inline web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) { return nc::details::make_field_descriptor(description, name, type_name, is_nullable, is_sequence, constraints); }; + inline web::json::value make_nc_field_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) { return nc::details::make_field_descriptor(description, name, is_nullable, is_sequence, constraints); }; + + // Deprecated: use nc::details::make_method_descriptor + inline web::json::value make_nc_method_descriptor(const utility::string_t& description, const nc_method_id& id, const nc_name& name, const utility::string_t& result_datatype, const web::json::value& parameters, bool is_deprecated) { return nc::details::make_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated); }; + + // Deprecated: use nc::details::make_parameter_descriptor + inline web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, bool is_nullable, bool is_sequence, const web::json::value& constraints) { return nc::details::make_parameter_descriptor(description, name, is_nullable, is_sequence, constraints); }; + inline web::json::value make_nc_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) { return nc::details::make_parameter_descriptor(description, name, type_name, is_nullable, is_sequence, constraints); }; + + // Deprecated: use nc::details::make_property_descriptor + inline web::json::value make_nc_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, + bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) { return nc::details::make_property_descriptor(description, id, name, type_name, is_read_only, is_nullable, is_sequence, is_deprecated, constraints); }; + + // Deprecated: use nc::details::make_datatype_descriptor_enum + inline web::json::value make_nc_datatype_descriptor_enum(const utility::string_t& description, const nc_name& name, const web::json::value& items, const web::json::value& constraints) { return nc::details::make_datatype_descriptor_enum(description, name, items, constraints); }; + + // Deprecated: use nc::details::make_datatype_descriptor_primitive + inline web::json::value make_nc_datatype_descriptor_primitive(const utility::string_t& description, const nc_name& name, const web::json::value& constraints) { return nc::details::make_datatype_descriptor_primitive(description, name, constraints); }; + + // Deprecated: use nc::details::make_datatype_descriptor_struct + inline web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const utility::string_t& parent_type, const web::json::value& constraints) { return nc::details::make_datatype_descriptor_struct(description, name, fields, parent_type, constraints); }; + inline web::json::value make_nc_datatype_descriptor_struct(const utility::string_t& description, const nc_name& name, const web::json::value& fields, const web::json::value& constraints) { return nc::details::make_datatype_descriptor_struct(description, name, fields, constraints); }; + + // Deprecated: use nc::details::make_datatype_typedef + inline web::json::value make_nc_datatype_typedef(const utility::string_t& description, const nc_name& name, bool is_sequence, const utility::string_t& parent_type, const web::json::value& constraints) { return nc::details::make_datatype_typedef(description, name, is_sequence, parent_type, constraints); }; + + // Deprecated: use nc::details::make_property_constraints + inline web::json::value make_nc_property_constraints(const nc_property_id& property_id, const web::json::value& default_value) { return nc::details::make_property_constraints(property_id, default_value); }; + + // Deprecated: use nc::details::make_property_constraints_number + inline web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) { return nc::details::make_property_constraints_number(property_id, default_value, minimum, maximum, step); }; + inline web::json::value make_nc_property_constraints_number(const nc_property_id& property_id, uint64_t minimum, uint64_t maximum, uint64_t step) { return nc::details::make_property_constraints_number(property_id, minimum, maximum, step); }; + + // Deprecated: use nc::details::make_property_constraints_string + inline web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) { return nc::details::make_property_constraints_string(property_id, default_value, max_characters, pattern); }; + inline web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters, const nc_regex& pattern) { return nc::details::make_property_constraints_string(property_id, max_characters, pattern); }; + inline web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, uint32_t max_characters) { return nc::details::make_property_constraints_string(property_id, max_characters); }; + inline web::json::value make_nc_property_constraints_string(const nc_property_id& property_id, const nc_regex& pattern) { return nc::details::make_property_constraints_string(property_id, pattern); }; + + // Deprecated: use nc::details::make_parameter_constraints + inline web::json::value make_nc_parameter_constraints(const web::json::value& default_value) { return nc::details::make_parameter_constraints(default_value); }; + + // Deprecated: use nc::details::make_parameter_constraints_number + inline web::json::value make_nc_parameter_constraints_number(uint64_t default_value, uint64_t minimum, uint64_t maximum, uint64_t step) { return nc::details::make_parameter_constraints_number(default_value, minimum, maximum, step); }; + inline web::json::value make_nc_parameter_constraints_number(uint64_t minimum, uint64_t maximum, uint64_t step) { return nc::details::make_parameter_constraints_number(minimum, maximum, step); }; + + // Deprecated: use nc::details::make_parameter_constraints_string + inline web::json::value make_nc_parameter_constraints_string(const utility::string_t& default_value, uint32_t max_characters, const nc_regex& pattern) { return nc::details::make_parameter_constraints_string(default_value, max_characters, pattern); }; + inline web::json::value make_nc_parameter_constraints_string(uint32_t max_characters, const nc_regex& pattern) { return nc::details::make_parameter_constraints_string(max_characters, pattern); }; + inline web::json::value make_nc_parameter_constraints_string(uint32_t max_characters) { return nc::details::make_parameter_constraints_string(max_characters); }; + inline web::json::value make_nc_parameter_constraints_string(const nc_regex& pattern) { return nc::details::make_parameter_constraints_string(pattern); }; + + // Deprecated: use nc::details::make_touchpoint + inline web::json::value make_nc_touchpoint(const utility::string_t& context_namespace) { return nc::details::make_touchpoint(context_namespace); }; + + // Deprecated: use nc::details::make_touchpoint_nmos + inline web::json::value make_nc_touchpoint_nmos(const nc_touchpoint_resource_nmos& resource) { return nc::details::make_touchpoint_nmos(resource); }; + + // Deprecated: use nc::details::make_touchpoint_nmos_channel_mapping + inline web::json::value make_nc_touchpoint_nmos_channel_mapping(const nc_touchpoint_resource_nmos_channel_mapping& resource) { return nc::details::make_touchpoint_nmos_channel_mapping(resource); }; + + // Deprecated: use nc::details::make_object + inline web::json::value make_nc_object(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) { return nc::details::make_object(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); }; + + // Deprecated: use nc::details::make_block + inline web::json::value make_nc_block(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, const web::json::value& members) { return nc::details::make_block(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, members); }; + + // Deprecated: use nc::details::make_worker + inline web::json::value make_nc_worker(const nc_class_id& class_id, nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled) { return nc::details::make_worker(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled); }; + + // Deprecated: use nc::details::make_manager + inline web::json::value make_nc_manager(const nc_class_id& class_id, nc_oid oid, bool constant_oid, const web::json::value& owner, const utility::string_t& role, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints) { return nc::details::make_manager(class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints); }; + + // Deprecated: use nc::details::make_device_manager + inline web::json::value make_nc_device_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const web::json::value& manufacturer, const web::json::value& product, const utility::string_t& serial_number, - const web::json::value& user_inventory_code, const web::json::value& device_name, const web::json::value& device_role, const web::json::value& operational_state, nc_reset_cause::cause reset_cause); + const web::json::value& user_inventory_code, const web::json::value& device_name, const web::json::value& device_role, const web::json::value& operational_state, nc_reset_cause::cause reset_cause) { return nc::details::make_device_manager(oid, owner, user_label, description, touchpoints, runtime_property_constraints, manufacturer, product, serial_number, user_inventory_code, device_name, device_role, operational_state, reset_cause); }; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager - web::json::value make_nc_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state); + // Deprecated: use nc::details::make_class_manager + inline web::json::value make_nc_class_manager(nc_oid oid, nc_oid owner, const web::json::value& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, const nmos::experimental::control_protocol_state& control_protocol_state) { return nc::details::make_class_manager(oid, owner, user_label, description, touchpoints, runtime_property_constraints, control_protocol_state); }; } - // command message response - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#command-response-message-type - web::json::value make_control_protocol_response(int32_t handle, const web::json::value& method_result); - web::json::value make_control_protocol_command_response(const web::json::value& responses); - - // subscription response - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#subscription-response-message-type - web::json::value make_control_protocol_subscription_response(const web::json::value& subscriptions); - - // notification - // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#notification-messages - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#notification-message-type - web::json::value make_control_protocol_notification(nc_oid oid, const nc_event_id& event_id, const nc_property_changed_event_data& property_changed_event_data); - web::json::value make_control_protocol_notification_message(const web::json::value& notifications); - - // property changed notification event - // See https://specs.amwa.tv/ms-05-01/branches/v1.0.x/docs/Core_Mechanisms.html#the-propertychanged-event - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/NcObject.html#propertychanged-event - web::json::value make_property_changed_event(nc_oid oid, const std::vector& property_changed_event_data_list); - - // error message - // See https://specs.amwa.tv/is-12/branches/v1.0.x/docs/Protocol_messaging.html#error-messages - web::json::value make_control_protocol_error_message(const nc_method_result& method_result, const utility::string_t& error_message); - - // Control class models - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/#control-class-models-for-branch-v10-dev - // - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.html - web::json::value make_nc_object_class(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.1.html - web::json::value make_nc_block_class(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.2.html - web::json::value make_nc_worker_class(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.html - web::json::value make_nc_manager_class(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.1.html - web::json::value make_nc_device_manager_class(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/classes/1.3.2.html - web::json::value make_nc_class_manager_class(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon - web::json::value make_nc_ident_beacon_class(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_nc_receiver_monitor_class(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_nc_sender_monitor_class(); - - // control classes properties/methods/events - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject - web::json::value make_nc_object_properties(); - web::json::value make_nc_object_methods(); - web::json::value make_nc_object_events(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock - web::json::value make_nc_block_properties(); - web::json::value make_nc_block_methods(); - web::json::value make_nc_block_events(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncworker - web::json::value make_nc_worker_properties(); - web::json::value make_nc_worker_methods(); - web::json::value make_nc_worker_events(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncmanager - web::json::value make_nc_manager_properties(); - web::json::value make_nc_manager_methods(); - web::json::value make_nc_manager_events(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager - web::json::value make_nc_device_manager_properties(); - web::json::value make_nc_device_manager_methods(); - web::json::value make_nc_device_manager_events(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassmanager - web::json::value make_nc_class_manager_properties(); - web::json::value make_nc_class_manager_methods(); - web::json::value make_nc_class_manager_events(); - // Monitoring feature set control classes - // https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstatusmonitor - web::json::value make_nc_status_monitor_properties(); - web::json::value make_nc_status_monitor_methods(); - web::json::value make_nc_status_monitor_events(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncreceivermonitor - web::json::value make_nc_receiver_monitor_properties(); - web::json::value make_nc_receiver_monitor_methods(); - web::json::value make_nc_receiver_monitor_events(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor - web::json::value make_nc_sender_monitor_properties(); - web::json::value make_nc_sender_monitor_methods(); - web::json::value make_nc_sender_monitor_events(); - - // Identification feature set control classes - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#ncidentbeacon - web::json::value make_nc_ident_beacon_properties(); - web::json::value make_nc_ident_beacon_methods(); - web::json::value make_nc_ident_beacon_events(); - - // Datatype models - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/#datatype-models-for-branch-v10-dev - // - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_boolean_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int16_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int32_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_int64_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint16_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint32_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_uint64_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_float32_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_float64_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#primitives - web::json::value make_nc_string_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcBlockMemberDescriptor.html - web::json::value make_nc_block_member_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassDescriptor.html - web::json::value make_nc_class_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcClassId.html - web::json::value make_nc_class_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptor.html - web::json::value make_nc_datatype_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorEnum.html - web::json::value make_nc_datatype_descriptor_enum_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorPrimitive.html - web::json::value make_nc_datatype_descriptor_primitive_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorStruct.html - web::json::value make_nc_datatype_descriptor_struct_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeDescriptorTypeDef.html - web::json::value make_nc_datatype_descriptor_type_def_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDatatypeType.html - web::json::value make_nc_datatype_type_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDescriptor.html - web::json::value make_nc_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceGenericState.html - web::json::value make_nc_device_generic_state_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcDeviceOperationalState.html - web::json::value make_nc_device_operational_state_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcElementId.html - web::json::value make_nc_element_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEnumItemDescriptor.html - web::json::value make_nc_enum_item_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventDescriptor.html - web::json::value make_nc_event_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcEventId.html - web::json::value make_nc_event_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcFieldDescriptor.html - web::json::value make_nc_field_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcId.html - web::json::value make_nc_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcManufacturer.html - web::json::value make_nc_manufacturer_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodDescriptor.html - web::json::value make_nc_method_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodId.html - web::json::value make_nc_method_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResult.html - web::json::value make_nc_method_result_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultBlockMemberDescriptors.html - web::json::value make_nc_method_result_block_member_descriptors_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultClassDescriptor.html - web::json::value make_nc_method_result_class_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultDatatypeDescriptor.html - web::json::value make_nc_method_result_datatype_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultError.html - web::json::value make_nc_method_result_error_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultId.html - web::json::value make_nc_method_result_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultLength.html - web::json::value make_nc_method_result_length_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodResultPropertyValue.html - web::json::value make_nc_method_result_property_value_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcMethodStatus.html - web::json::value make_nc_method_status_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcName.html - web::json::value make_nc_name_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOid.html - web::json::value make_nc_oid_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcOrganizationId.html - web::json::value make_nc_organization_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraints.html - web::json::value make_nc_parameter_constraints_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsNumber.html - web::json::value make_nc_parameter_constraints_number_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterConstraintsString.html - web::json::value make_nc_parameter_constraints_string_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcParameterDescriptor.html - web::json::value make_nc_parameter_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcProduct.html - web::json::value make_nc_product_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangeType.html - web::json::value make_nc_property_change_type_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyChangedEventData.html - web::json::value make_nc_property_changed_event_data_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraints.html - web::json::value make_nc_property_contraints_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsNumber.html - web::json::value make_nc_property_constraints_number_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyConstraintsString.html - web::json::value make_nc_property_constraints_string_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyDescriptor.html - web::json::value make_nc_property_descriptor_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcPropertyId.html - web::json::value make_nc_property_id_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRegex.html - web::json::value make_nc_regex_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcResetCause.html - web::json::value make_nc_reset_cause_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcRolePath.html - web::json::value make_nc_role_path_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTimeInterval.html - web::json::value make_nc_time_interval_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpoint.html - web::json::value make_nc_touchpoint_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmos.html - web::json::value make_nc_touchpoint_nmos_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointNmosChannelMapping.html - web::json::value make_nc_touchpoint_nmos_channel_mapping_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResource.html - web::json::value make_nc_touchpoint_resource_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmos.html - web::json::value make_nc_touchpoint_resource_nmos_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcTouchpointResourceNmosChannelMapping.html - web::json::value make_nc_touchpoint_resource_nmos_channel_mapping_datatype(); - // See // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUri.html - web::json::value make_nc_uri_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcUuid.html - web::json::value make_nc_uuid_datatype(); - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/NcVersionCode.html - web::json::value make_nc_version_code_datatype(); - - // Monitoring feature set datatypes - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#datatypes - // - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncconnectionstatus - web::json::value make_nc_connection_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncessencestatus - web::json::value make_nc_essence_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncoverallstatus - web::json::value make_nc_overall_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nclinkstatus - web::json::value make_nc_link_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsynchronizationstatus - web::json::value make_nc_synchronization_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncstreamstatus - web::json::value make_nc_stream_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nccounter - web::json::value make_nc_counter_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#nctransmissionstatus - web::json::value make_nc_transmission_status_datatype(); - // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncmethodresultcounters - web::json::value make_nc_method_result_counters_datatype(); + // Deprecated: use nc::make_response + inline web::json::value make_control_protocol_response(int32_t handle, const web::json::value& method_result) { return nc::make_response(handle, method_result); }; + // Deprecated: use nc::make_command_response + inline web::json::value make_control_protocol_command_response(const web::json::value& responses) { return nc::make_command_response(responses); }; + + // Deprecated: use nc::make_subscription_response + inline web::json::value make_control_protocol_subscription_response(const web::json::value& subscriptions) { return nc::make_subscription_response(subscriptions); }; + + // Deprecated: use nc::make_notification + inline web::json::value make_control_protocol_notification(nc_oid oid, const nc_event_id& event_id, const nc_property_changed_event_data& property_changed_event_data) { return nc::make_notification(oid, event_id, property_changed_event_data); }; + // Deprecated: use nc::make_notification_message + inline web::json::value make_control_protocol_notification_message(const web::json::value& notifications) { return nc::make_notification_message(notifications); }; + + // Deprecated: use nc::make_property_changed_event + inline web::json::value make_property_changed_event(nc_oid oid, const std::vector& property_changed_event_data_list) { return nc::make_property_changed_event(oid, property_changed_event_data_list); }; + + // Deprecated: use nc::make_error_message + inline web::json::value make_control_protocol_error_message(const nc_method_result& method_result, const utility::string_t& error_message) { return nc::make_error_message(method_result, error_message); }; + + // Deprecated: use nc::make_object_class + inline web::json::value make_nc_object_class() { return nc::make_object_class(); }; + // Deprecated: use nc::make_block_class + inline web::json::value make_nc_block_class() { return nc::make_block_class(); }; + // Deprecated: use nc::make_worker_class + inline web::json::value make_nc_worker_class() { return nc::make_worker_class(); }; + // Deprecated: use nc::make_manager_class + inline web::json::value make_nc_manager_class() { return nc::make_manager_class(); }; + // Deprecated: use nc::make_device_manager_class + inline web::json::value make_nc_device_manager_class() { return nc::make_device_manager_class(); }; + // Deprecated: use nc::make_class_manager_class + inline web::json::value make_nc_class_manager_class() { return nc::make_class_manager_class(); }; + // Deprecated: use nc::make_ident_beacon_class + inline web::json::value make_nc_ident_beacon_class() { return nc::make_ident_beacon_class(); }; + // Deprecated: use nc::make_receiver_monitor_class + inline web::json::value make_nc_receiver_monitor_class() { return nc::make_receiver_monitor_class(); }; + // Deprecated: use nc::make_sender_monitor_class + inline web::json::value make_nc_sender_monitor_class() { return nc::make_sender_monitor_class(); }; } - #endif diff --git a/Development/nmos/control_protocol_resources.cpp b/Development/nmos/control_protocol_resources.cpp index 89e0e696f..9ba45c47e 100644 --- a/Development/nmos/control_protocol_resources.cpp +++ b/Development/nmos/control_protocol_resources.cpp @@ -13,7 +13,7 @@ namespace nmos { using web::json::value; - auto data = details::make_nc_block(nc_block_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true, members); + auto data = nc::details::make_block(nc_block_class_id, oid, true, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, true, members); return{ is12_versions::v1_0, types::nc_block, std::move(data), true }; } @@ -27,12 +27,55 @@ namespace nmos return details::make_block(oid, value(owner), role, user_label, description, touchpoints, runtime_property_constraints, members); } + control_protocol_resource make_rebuildable(control_protocol_resource& control_protocol_resource) + { + using web::json::value; + + control_protocol_resource.data[nmos::fields::nc::is_rebuildable] = value::boolean(true); + + return control_protocol_resource; + } + + control_protocol_resource set_block_allowed_member_classes(control_protocol_resource& control_protocol_resource, const std::vector& allowed_member_classes) + { + using web::json::value; + + auto allowed_member_classes_array = value::array(); + + for(const auto& class_id: allowed_member_classes) + { + web::json::push_back(allowed_member_classes_array, nc::details::make_class_id(class_id)); + } + + control_protocol_resource.data[nmos::fields::nc::allowed_members_classes] = allowed_member_classes_array; + + return control_protocol_resource; + } + + control_protocol_resource set_object_dependency_paths(control_protocol_resource& control_protocol_resource, const std::vector& dependency_paths) + { + using web::json::value; + + auto dependency_path_array = value::array(); + + for(const auto& path: dependency_paths) + { + auto role_path = value::array(); + for (const auto& path_item : path) { web::json::push_back(role_path, path_item); } + web::json::push_back(dependency_path_array, role_path); + } + + control_protocol_resource.data[nmos::fields::nc::dependency_paths] = dependency_path_array; + + return control_protocol_resource; + } + // create Root block resource control_protocol_resource make_root_block() { using web::json::value; - return details::make_block(1, value::null(), U("root"), U("Root"), U("Root block"), value::null(), value::null(), value::array()); + return details::make_block(nmos::root_block_oid, value::null(), nmos::root_block_role, U("Root"), U("Root block"), value::null(), value::null(), value::array()); } // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncdevicemanager @@ -40,14 +83,14 @@ namespace nmos { using web::json::value; - const auto& manufacturer = details::make_nc_manufacturer(nmos::experimental::fields::manufacturer_name(settings)); - const auto& product = details::make_nc_product(nmos::experimental::fields::product_name(settings), nmos::experimental::fields::product_key(settings), nmos::experimental::fields::product_key(settings)); + const auto& manufacturer = nc::details::make_manufacturer(nmos::experimental::fields::manufacturer_name(settings)); + const auto& product = nc::details::make_product(nmos::experimental::fields::product_name(settings), nmos::experimental::fields::product_key(settings), nmos::experimental::fields::product_key(settings)); const auto& serial_number = nmos::experimental::fields::serial_number(settings); const auto device_name = value::null(); const auto device_role = value::null(); - const auto& operational_state = details::make_nc_device_operational_state(nc_device_generic_state::normal_operation, value::null()); + const auto& operational_state = nc::details::make_device_operational_state(nc_device_generic_state::normal_operation, value::null()); - auto data = details::make_nc_device_manager(oid, root_block_oid, value::string(U("Device manager")), U("The device manager offers information about the product this device is representing"), value::null(), value::null(), + auto data = nc::details::make_device_manager(oid, root_block_oid, value::string(U("Device manager")), U("The device manager offers information about the product this device is representing"), value::null(), value::null(), manufacturer, product, serial_number, value::null(), device_name, device_role, operational_state, nc_reset_cause::unknown); return{ is12_versions::v1_0, types::nc_device_manager, std::move(data), true }; @@ -58,7 +101,7 @@ namespace nmos { using web::json::value; - auto data = details::make_nc_class_manager(oid, root_block_oid, value::string(U("Class manager")), U("The class manager offers access to control class and data type descriptors"), value::null(), value::null(), control_protocol_state); + auto data = nc::details::make_class_manager(oid, root_block_oid, value::string(U("Class manager")), U("The class manager offers access to control class and data type descriptors"), value::null(), value::null(), control_protocol_state); return{ is12_versions::v1_0, types::nc_class_manager, std::move(data), true }; } @@ -69,7 +112,7 @@ namespace nmos control_protocol_resource make_receiver_monitor(nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_connection_status::status connection_status, const utility::string_t& connection_status_message, nc_synchronization_status::status synchronization_status, const utility::string_t& synchronization_status_message, const web::json::value& synchronization_source_id, nc_stream_status::status stream_status, const utility::string_t& stream_status_message, uint32_t status_reporting_delay, bool auto_reset_monitor) { - auto data = details::make_receiver_monitor(nc_receiver_monitor_class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, link_status, link_status_message, connection_status, connection_status_message, synchronization_status, synchronization_status_message, synchronization_source_id, stream_status, stream_status_message, status_reporting_delay, auto_reset_monitor); + auto data = nc::details::make_receiver_monitor(nc_receiver_monitor_class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, link_status, link_status_message, connection_status, connection_status_message, synchronization_status, synchronization_status_message, synchronization_source_id, stream_status, stream_status_message, status_reporting_delay, auto_reset_monitor); return{ is12_versions::v1_0, types::nc_status_monitor, std::move(data), true }; } @@ -78,7 +121,7 @@ namespace nmos control_protocol_resource make_sender_monitor(nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints, const web::json::value& runtime_property_constraints, bool enabled, nc_overall_status::status overall_status, const utility::string_t& overall_status_message, nc_link_status::status link_status, const utility::string_t& link_status_message, nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, nc_synchronization_status::status synchronization_status, const utility::string_t& synchronization_status_message, const web::json::value& synchronization_source_id, nc_essence_status::status essence_status, const utility::string_t& essence_status_message, uint32_t status_reporting_delay, bool auto_reset_counters) { - auto data = details::make_sender_monitor(nc_sender_monitor_class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, link_status, link_status_message, transmission_status, transmission_status_message, synchronization_status, synchronization_status_message, synchronization_source_id, essence_status, essence_status_message, status_reporting_delay, auto_reset_counters); + auto data = nc::details::make_sender_monitor(nc_sender_monitor_class_id, oid, constant_oid, owner, role, user_label, description, touchpoints, runtime_property_constraints, enabled, overall_status, overall_status_message, link_status, link_status_message, transmission_status, transmission_status_message, synchronization_status, synchronization_status_message, synchronization_source_id, essence_status, essence_status_message, status_reporting_delay, auto_reset_counters); return{ is12_versions::v1_0, types::nc_status_monitor, std::move(data), true }; } @@ -91,9 +134,21 @@ namespace nmos { using web::json::value; - auto data = nmos::details::make_nc_worker(nc_ident_beacon_class_id, oid, constant_oid, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, enabled); + auto data = nc::details::make_worker(nc_ident_beacon_class_id, oid, constant_oid, owner, role, value::string(user_label), description, touchpoints, runtime_property_constraints, enabled); data[nmos::fields::nc::active] = value::boolean(active); return{ is12_versions::v1_0, types::nc_ident_beacon, std::move(data), true }; } + + // Device Configuration feature set control classes + // + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + control_protocol_resource make_bulk_properties_manager(nc_oid oid) + { + using web::json::value; + + auto data = nc::details::make_bulk_properties_manager(oid, root_block_oid, value::string(U("Bulk properties manager")), U("The bulk properties manager offers a central model for getting and setting properties of multiple role paths"), value::null(), value::null()); + + return{ is12_versions::v1_0, types::nc_bulk_properties_manager, std::move(data), true }; + } } diff --git a/Development/nmos/control_protocol_resources.h b/Development/nmos/control_protocol_resources.h index 2c34a1ff0..fdded5c03 100644 --- a/Development/nmos/control_protocol_resources.h +++ b/Development/nmos/control_protocol_resources.h @@ -16,6 +16,15 @@ namespace nmos // create block resource control_protocol_resource make_block(nc_oid oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints = web::json::value::null(), const web::json::value& runtime_property_constraints = web::json::value::null(), const web::json::value& members = web::json::value::array()); + // make object rebuildable - for IS-14 dynamic configuration of Device Model + control_protocol_resource make_rebuildable(control_protocol_resource& control_protocol_resource); + + // set the allowed_member_classes field of an NcBlock - for IS-14 dynamic configuration of Device Model + control_protocol_resource set_block_allowed_member_classes(control_protocol_resource& control_protocol_resource, const std::vector& allowed_member_classes); + + // set the dependency_paths field of an NcObject - for IS-14 configuration of Device Model + control_protocol_resource set_object_dependency_paths(control_protocol_resource& control_protocol_resource, const std::vector& dependency_paths); + // create Root block resource control_protocol_resource make_root_block(); @@ -67,6 +76,11 @@ namespace nmos control_protocol_resource make_ident_beacon(nc_oid oid, bool constant_oid, nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description, const web::json::value& touchpoints = web::json::value::null(), const web::json::value& runtime_property_constraints = web::json::value::null(), bool enabled = true, bool active = false ); + + // Device Configuration feature set control classes + // + // create Bulk Properties Manager resource + control_protocol_resource make_bulk_properties_manager(nc_oid oid); } #endif diff --git a/Development/nmos/control_protocol_state.cpp b/Development/nmos/control_protocol_state.cpp index 27942d950..8e6b90762 100644 --- a/Development/nmos/control_protocol_state.cpp +++ b/Development/nmos/control_protocol_state.cpp @@ -3,6 +3,7 @@ #include "cpprest/http_utils.h" #include "nmos/control_protocol_methods.h" #include "nmos/control_protocol_resource.h" +#include "nmos/configuration_methods.h" namespace nmos { @@ -13,8 +14,8 @@ namespace nmos // create control class descriptor // where // properties: vector of NcPropertyDescriptor where NcPropertyDescriptor can be constructed using make_control_class_property - // methods: vector of NcMethodDescriptor vs assoicated method handler where NcMethodDescriptor can be constructed using make_nc_method_descriptor - // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_nc_event_descriptor + // methods: vector of NcMethodDescriptor vs assoicated method handler where NcMethodDescriptor can be constructed using make_method_descriptor + // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_event_descriptor control_class_descriptor make_control_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const web::json::value& fixed_role, const std::vector& properties_, const std::vector& methods_, const std::vector& events_) { using web::json::value; @@ -30,8 +31,8 @@ namespace nmos // create control class descriptor with fixed role // where // properties: vector of NcPropertyDescriptor where NcPropertyDescriptor can be constructed using make_control_class_property - // methods: vector of NcMethodDescriptor where NcMethodDescriptor can be constructed using make_nc_method_descriptor and the assoicated method handler - // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_nc_event_descriptor + // methods: vector of NcMethodDescriptor where NcMethodDescriptor can be constructed using make_method_descriptor and the assoicated method handler + // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_event_descriptor control_class_descriptor make_control_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const utility::string_t& fixed_role, const std::vector& properties, const std::vector& methods, const std::vector& events) { using web::json::value; @@ -41,8 +42,8 @@ namespace nmos // create control class descriptor without fixed role // where // properties: vector of NcPropertyDescriptor where NcPropertyDescriptor can be constructed using make_control_class_property - // methods: vector of NcMethodDescriptor where NcMethodDescriptor can be constructed using make_nc_method_descriptor and the assoicated method handler - // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_nc_event_descriptor + // methods: vector of NcMethodDescriptor where NcMethodDescriptor can be constructed using make_method_descriptor and the assoicated method handler + // events: vector of NcEventDescriptor where NcEventDescriptor can be constructed using make_event_descriptor control_class_descriptor make_control_class_descriptor(const utility::string_t& description, const nc_class_id& class_id, const nc_name& name, const std::vector& properties, const std::vector& methods, const std::vector& events) { using web::json::value; @@ -53,13 +54,13 @@ namespace nmos // create control class property descriptor web::json::value make_control_class_property_descriptor(const utility::string_t& description, const nc_property_id& id, const nc_name& name, const utility::string_t& type_name, bool is_read_only, bool is_nullable, bool is_sequence, bool is_deprecated, const web::json::value& constraints) { - return nmos::details::make_nc_property_descriptor(description, id, name, type_name, is_read_only, is_nullable, is_sequence, is_deprecated, constraints); + return nc::details::make_property_descriptor(description, id, name, type_name, is_read_only, is_nullable, is_sequence, is_deprecated, constraints); } // create control class method parameter descriptor web::json::value make_control_class_method_parameter_descriptor(const utility::string_t& description, const nc_name& name, const utility::string_t& type_name, bool is_nullable, bool is_sequence, const web::json::value& constraints) { - return nmos::details::make_nc_parameter_descriptor(description, name, type_name, is_nullable, is_sequence, constraints); + return nc::details::make_parameter_descriptor(description, name, type_name, is_nullable, is_sequence, constraints); } namespace details @@ -71,7 +72,7 @@ namespace nmos value parameters = value::array(); for (const auto& parameter : parameters_) { web::json::push_back(parameters, parameter); } - return nmos::details::make_nc_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated); + return nc::details::make_method_descriptor(description, id, name, result_datatype, parameters, is_deprecated); } } // create control class method descriptor @@ -83,126 +84,190 @@ namespace nmos // create control class event descriptor web::json::value make_control_class_event_descriptor(const utility::string_t& description, const nc_event_id& id, const nc_name& name, const utility::string_t& event_datatype, bool is_deprecated) { - return nmos::details::make_nc_event_descriptor(description, id, name, event_datatype, is_deprecated); + return nc::details::make_event_descriptor(description, id, name, event_datatype, is_deprecated); } namespace details { nmos::experimental::control_protocol_method_handler make_nc_get_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) { - return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + return [get_control_protocol_class_descriptor](nmos::resources&, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + return nc::get(resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_set_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) { return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return set(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + return nc::set(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) { - return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + return [get_control_protocol_class_descriptor](nmos::resources&, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + return nc::get_sequence_item(resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_set_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) { return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return set_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + return nc::set_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_add_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, control_protocol_property_changed_handler property_changed) { return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return add_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); + return nc::add_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, property_changed, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_remove_sequence_item_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed) { return [get_control_protocol_class_descriptor, property_changed](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return remove_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, property_changed, gate); + return nc::remove_sequence_item(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, property_changed, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) { - return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + return [get_control_protocol_class_descriptor](nmos::resources&, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get_sequence_length(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + return nc::get_sequence_length(resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_member_descriptors_handler() { return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get_member_descriptors(resources, resource, arguments, is_deprecated, gate); + return nc::get_member_descriptors(resources, resource, arguments, is_deprecated, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_find_members_by_path_handler() { return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return find_members_by_path(resources, resource, arguments, is_deprecated, gate); + return nc::find_members_by_path(resources, resource, arguments, is_deprecated, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_find_members_by_role_handler() { return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return find_members_by_role(resources, resource, arguments, is_deprecated, gate); + return nc::find_members_by_role(resources, resource, arguments, is_deprecated, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_find_members_by_class_id_handler() { return [](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return find_members_by_class_id(resources, resource, arguments, is_deprecated, gate); + return nc::find_members_by_class_id(resources, resource, arguments, is_deprecated, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_control_class_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) { - return [get_control_protocol_class_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + return [get_control_protocol_class_descriptor](nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get_control_class(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, gate); + return nc::get_control_class(arguments, is_deprecated, get_control_protocol_class_descriptor, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_datatype_handler(get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { - return [get_control_protocol_datatype_descriptor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + return [get_control_protocol_datatype_descriptor](nmos::resources&, const nmos::resource&, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return get_datatype(resources, resource, arguments, is_deprecated, get_control_protocol_datatype_descriptor, gate); + return nc::get_datatype(arguments, is_deprecated, get_control_protocol_datatype_descriptor, gate); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_get_properties_by_path_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, create_validation_fingerprint_handler create_validation_fingerprint) + { + return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + bool recurse = nmos::fields::nc::recurse(arguments); + bool include_descriptors = nmos::fields::nc::include_descriptors(arguments); + + return nmos::get_properties_by_path(resources, resource, recurse, include_descriptors, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint); + }; + } + nmos::experimental::control_protocol_method_handler make_nc_validate_set_properties_by_path_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, remove_device_model_object_handler remove_device_model_object, create_device_model_object_handler create_device_model_object) + { + return [&get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, validate_validation_fingerprint, remove_device_model_object, create_device_model_object](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + bool recurse = nmos::fields::nc::recurse(arguments); + const auto& restore_mode = nmos::fields::nc::restore_mode(arguments); + const auto& data_set = nmos::fields::nc::data_set(arguments); + + if (data_set.is_null()) + { + return nc::details::make_method_result_error({ nc_method_status::parameter_error }, U("Null dataSet parameter")); + } + + auto result = nc::details::make_method_result_error({ nmos::nc_method_status::method_not_implemented }, U("not implemented")); + if (get_read_only_modification_allow_list && remove_device_model_object && create_device_model_object) + { + result = validate_set_properties_by_path(resources, resource, data_set, recurse, static_cast(restore_mode), get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + const auto& status = nmos::fields::nc::status(result); + if (!web::http::is_error_status_code((web::http::status_code)status) && is_deprecated) + { + return nc::details::make_method_result({ nmos::nc_method_status::method_deprecated }, nmos::fields::nc::value(result)); + } + } + return result; + }; + } + nmos::experimental::control_protocol_method_handler make_nc_set_properties_by_path_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, remove_device_model_object_handler remove_device_model_object, create_device_model_object_handler create_device_model_object) + { + return [get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) + { + bool recurse = nmos::fields::nc::recurse(arguments); + const auto& restore_mode = nmos::fields::nc::restore_mode(arguments); + const auto& data_set = nmos::fields::nc::data_set(arguments); + + if (data_set.is_null()) + { + return nc::details::make_method_result_error({ nc_method_status::parameter_error }, U("Null dataSet parameter")); + } + + auto result = nc::details::make_method_result_error({ nmos::nc_method_status::method_not_implemented }, U("callbacks not implemented")); + if (get_read_only_modification_allow_list && remove_device_model_object && create_device_model_object) + { + result = set_properties_by_path(resources, resource, data_set, recurse, static_cast(restore_mode), get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + const auto& status = nmos::fields::nc::status(result); + if (!web::http::is_error_status_code((web::http::status_code)status) && is_deprecated) + { + return nc::details::make_method_result({ nmos::nc_method_status::method_deprecated }, nmos::fields::nc::value(result)); + } + } + return result; }; } nmos::experimental::control_protocol_method_handler make_nc_get_lost_packet_counters_handler(get_packet_counters_handler get_lost_packet_counters) { return [get_lost_packet_counters](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return nmos::get_lost_packet_counters(resources, resource, arguments, is_deprecated, get_lost_packet_counters, gate); + return nc::get_lost_packet_counters(resources, resource, arguments, is_deprecated, get_lost_packet_counters, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_get_late_packet_counters_handler(get_packet_counters_handler get_late_packet_counters) { return [get_late_packet_counters](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return nmos::get_late_packet_counters(resources, resource, arguments, is_deprecated, get_late_packet_counters, gate); + return nc::get_late_packet_counters(resources, resource, arguments, is_deprecated, get_late_packet_counters, gate); }; } nmos::experimental::control_protocol_method_handler make_nc_reset_monitor_handler(get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, control_protocol_property_changed_handler property_changed, reset_monitor_handler reset_monitor) { return [get_control_protocol_class_descriptor, property_changed, reset_monitor](nmos::resources& resources, const nmos::resource& resource, const web::json::value& arguments, bool is_deprecated, slog::base_gate& gate) { - return nmos::reset_monitor(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, property_changed, reset_monitor, gate); + return nc::reset_monitor(resources, resource, arguments, is_deprecated, get_control_protocol_class_descriptor, property_changed, reset_monitor, gate); }; } } - control_protocol_state::control_protocol_state(get_packet_counters_handler get_lost_packet_counters, get_packet_counters_handler get_late_packet_counters, reset_monitor_handler reset_monitor, control_protocol_property_changed_handler property_changed) + control_protocol_state::control_protocol_state(control_protocol_property_changed_handler property_changed, create_validation_fingerprint_handler create_validation_fingerprint, validate_validation_fingerprint_handler validate_validation_fingerprint, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, remove_device_model_object_handler remove_device_model_object, create_device_model_object_handler create_device_model_object, get_packet_counters_handler get_lost_packet_counters, get_packet_counters_handler get_late_packet_counters, reset_monitor_handler reset_monitor) : monitor_status_pending(false) { using web::json::value; @@ -225,7 +290,7 @@ namespace nmos { for (const auto& nc_method_descriptor : nc_method_descriptors.as_array()) { - methods.push_back(make_control_class_method(nc_method_descriptor, method_handlers.at(nmos::details::parse_nc_method_id(nmos::fields::nc::id(nc_method_descriptor))))); + methods.push_back(make_control_class_method(nc_method_descriptor, method_handlers.at(nc::details::parse_method_id(nmos::fields::nc::id(nc_method_descriptor))))); } } return methods; @@ -243,9 +308,9 @@ namespace nmos // NcObject { nc_object_class_id, make_control_class_descriptor(U("NcObject class descriptor"), nc_object_class_id, U("NcObject"), // NcObject properties - to_vector(make_nc_object_properties()), + to_vector(nc::make_object_properties()), // NcObject methods - to_methods_vector(make_nc_object_methods(), + to_methods_vector(nc::make_object_methods(), { // link NcObject method_ids with method functions { nc_object_get_method_id, details::make_nc_get_handler(get_control_protocol_class_descriptor) }, @@ -257,13 +322,13 @@ namespace nmos { nc_object_get_sequence_length_method_id, details::make_nc_get_sequence_length_handler(get_control_protocol_class_descriptor) } }), // NcObject events - to_vector(make_nc_object_events())) }, + to_vector(nc::make_object_events())) }, // NcBlock { nc_block_class_id, make_control_class_descriptor(U("NcBlock class descriptor"), nc_block_class_id, U("NcBlock"), // NcBlock properties - to_vector(make_nc_block_properties()), + to_vector(nc::make_block_properties()), // NcBlock methods - to_methods_vector(make_nc_block_methods(), + to_methods_vector(nc::make_block_methods(), { // link NcBlock method_ids with method functions { nc_block_get_member_descriptors_method_id, details::make_nc_get_member_descriptors_handler() }, @@ -272,70 +337,70 @@ namespace nmos { nc_block_find_members_by_class_id_method_id, details::make_nc_find_members_by_class_id_handler() } }), // NcBlock events - to_vector(make_nc_block_events())) }, + to_vector(nc::make_block_events())) }, // NcWorker { nc_worker_class_id, make_control_class_descriptor(U("NcWorker class descriptor"), nc_worker_class_id, U("NcWorker"), // NcWorker properties - to_vector(make_nc_worker_properties()), + to_vector(nc::make_worker_properties()), // NcWorker methods - to_methods_vector(make_nc_worker_methods(), {}), + to_methods_vector(nc::make_worker_methods(), {}), // NcWorker events - to_vector(make_nc_worker_events())) }, + to_vector(nc::make_worker_events())) }, // NcManager { nc_manager_class_id, make_control_class_descriptor(U("NcManager class descriptor"), nc_manager_class_id, U("NcManager"), // NcManager properties - to_vector(make_nc_manager_properties()), + to_vector(nc::make_manager_properties()), // NcManager methods - to_methods_vector(make_nc_manager_methods(), {}), + to_methods_vector(nc::make_manager_methods(), {}), // NcManager events - to_vector(make_nc_manager_events())) }, + to_vector(nc::make_manager_events())) }, // NcDeviceManager { nc_device_manager_class_id, make_control_class_descriptor(U("NcDeviceManager class descriptor"), nc_device_manager_class_id, U("NcDeviceManager"), U("DeviceManager"), // NcDeviceManager properties - to_vector(make_nc_device_manager_properties()), + to_vector(nc::make_device_manager_properties()), // NcDeviceManager methods - to_methods_vector(make_nc_device_manager_methods(), {}), + to_methods_vector(nc::make_device_manager_methods(), {}), // NcDeviceManager events - to_vector(make_nc_device_manager_events())) }, + to_vector(nc::make_device_manager_events())) }, // NcClassManager { nc_class_manager_class_id, make_control_class_descriptor(U("NcClassManager class descriptor"), nc_class_manager_class_id, U("NcClassManager"), U("ClassManager"), // NcClassManager properties - to_vector(make_nc_class_manager_properties()), + to_vector(nc::make_class_manager_properties()), // NcClassManager methods - to_methods_vector(make_nc_class_manager_methods(), + to_methods_vector(nc::make_class_manager_methods(), { // link NcClassManager method_ids with method functions { nc_class_manager_get_control_class_method_id, details::make_nc_get_control_class_handler(get_control_protocol_class_descriptor) }, { nc_class_manager_get_datatype_method_id, details::make_nc_get_datatype_handler(get_control_protocol_datatype_descriptor) } }), // NcClassManager events - to_vector(make_nc_class_manager_events())) }, + to_vector(nc::make_class_manager_events())) }, // Identification feature set // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/identification/#control-classes // NcIdentBeacon { nc_ident_beacon_class_id, make_control_class_descriptor(U("NcIdentBeacon class descriptor"), nc_ident_beacon_class_id, U("NcIdentBeacon"), // NcIdentBeacon properties - to_vector(make_nc_ident_beacon_properties()), + to_vector(nc::make_ident_beacon_properties()), // NcIdentBeacon methods - to_methods_vector(make_nc_ident_beacon_methods(), {}), + to_methods_vector(nc::make_ident_beacon_methods(), {}), // NcIdentBeacon events - to_vector(make_nc_ident_beacon_events())) }, + to_vector(nc::make_ident_beacon_events())) }, // Monitoring feature set // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#control-classes // NcStatusMonitor { nc_status_monitor_class_id, make_control_class_descriptor(U("NcStatusMonitor class descriptor"), nc_status_monitor_class_id, U("NcStatusMonitor"), // NcReceiverMonitor properties - to_vector(make_nc_status_monitor_properties()), + to_vector(nc::make_status_monitor_properties()), // NcReceiverMonitor methods - to_methods_vector(make_nc_status_monitor_methods(), {}), + to_methods_vector(nc::make_status_monitor_methods(), {}), // NcReceiverMonitor events - to_vector(make_nc_status_monitor_events())) }, + to_vector(nc::make_status_monitor_events())) }, // NcReceiverMonitor { nc_receiver_monitor_class_id, make_control_class_descriptor(U("NcReceiverMonitor class descriptor"), nc_receiver_monitor_class_id, U("NcReceiverMonitor"), // NcReceiverMonitor properties - to_vector(make_nc_receiver_monitor_properties()), + to_vector(nc::make_receiver_monitor_properties()), // NcReceiverMonitor methods - to_methods_vector(make_nc_receiver_monitor_methods(), + to_methods_vector(nc::make_receiver_monitor_methods(), { // link NcReceiverMonitor method_ids with method functions { nc_receiver_monitor_get_lost_packet_counters_method_id, details::make_nc_get_lost_packet_counters_handler(get_lost_packet_counters)}, @@ -343,22 +408,30 @@ namespace nmos { nc_receiver_monitor_reset_monitor_method_id, details::make_nc_reset_monitor_handler(get_control_protocol_class_descriptor, property_changed, reset_monitor)} }), // NcReceiverMonitor events - to_vector(make_nc_receiver_monitor_events())) }, + to_vector(nc::make_receiver_monitor_events())) }, // NcSenderMonitor { nc_sender_monitor_class_id, make_control_class_descriptor(U("NcSenderMonitor class descriptor"), nc_sender_monitor_class_id, U("NcSenderMonitor"), // NcSenderMonitor properties - to_vector(make_nc_sender_monitor_properties()), + to_vector(nc::make_sender_monitor_properties()), // NcSenderMonitor methods - to_methods_vector(make_nc_sender_monitor_methods(), + to_methods_vector(nc::make_sender_monitor_methods(), { // link NcSenderMonitor method_ids with method functions - // TODO: implement actual GetTransmissionError and ResetCountersAndMessages function { nc_sender_monitor_get_transmission_error_counters_method_id, details::make_nc_get_lost_packet_counters_handler(get_lost_packet_counters)}, { nc_sender_monitor_reset_monitor_method_id, details::make_nc_reset_monitor_handler(get_control_protocol_class_descriptor, property_changed, reset_monitor)} }), // NcSenderMonitor events - to_vector(make_nc_sender_monitor_events())) - } + to_vector(nc::make_sender_monitor_events())) }, + // NcBulkPropertiesManager + { nc_bulk_properties_manager_class_id, make_control_class_descriptor(U("NcBulkPropertiesManager class descriptor"), nc_bulk_properties_manager_class_id, U("NcBulkPropertiesManager"), U("BulkPropertiesManager"), + to_vector(nc::make_bulk_properties_manager_properties()), + to_methods_vector(nc::make_bulk_properties_manager_methods(), + { + { nc_bulk_properties_manager_get_properties_by_path_method_id, details::make_nc_get_properties_by_path_handler(make_get_control_protocol_class_descriptor_handler(*this), make_get_control_protocol_datatype_descriptor_handler(*this), create_validation_fingerprint)}, + { nc_bulk_properties_manager_validate_set_properties_by_path_method_id, details::make_nc_validate_set_properties_by_path_handler(make_get_control_protocol_class_descriptor_handler(*this), make_get_control_protocol_datatype_descriptor_handler(*this), validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object) }, + { nc_bulk_properties_manager_set_properties_by_path_method_id, details::make_nc_set_properties_by_path_handler(make_get_control_protocol_class_descriptor_handler(*this), make_get_control_protocol_datatype_descriptor_handler(*this), validate_validation_fingerprint, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object) } + }), + to_vector(nc::make_bulk_properties_manager_events())) } }; // setup the standard datatypes @@ -366,85 +439,97 @@ namespace nmos { // Datatype models // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/models/datatypes/ - { U("NcBoolean"), {make_nc_boolean_datatype()} }, - { U("NcInt16"), {make_nc_int16_datatype()} }, - { U("NcInt32"), {make_nc_int32_datatype()} }, - { U("NcInt64"), {make_nc_int64_datatype()} }, - { U("NcUint16"), {make_nc_uint16_datatype()} }, - { U("NcUint32"), {make_nc_uint32_datatype()} }, - { U("NcUint64"), {make_nc_uint64_datatype()} }, - { U("NcFloat32"), {make_nc_float32_datatype()} }, - { U("NcFloat64"), {make_nc_float64_datatype()} }, - { U("NcString"), {make_nc_string_datatype()} }, - { U("NcClassId"), {make_nc_class_id_datatype()} }, - { U("NcOid"), {make_nc_oid_datatype()} }, - { U("NcTouchpoint"), {make_nc_touchpoint_datatype()} }, - { U("NcElementId"), {make_nc_element_id_datatype()} }, - { U("NcPropertyId"), {make_nc_property_id_datatype()} }, - { U("NcPropertyConstraints"), {make_nc_property_contraints_datatype()} }, - { U("NcMethodResultPropertyValue"), {make_nc_method_result_property_value_datatype()} }, - { U("NcMethodStatus"), {make_nc_method_status_datatype()} }, - { U("NcMethodResult"), {make_nc_method_result_datatype()} }, - { U("NcId"), {make_nc_id_datatype()} }, - { U("NcMethodResultId"), {make_nc_method_result_id_datatype()} }, - { U("NcMethodResultLength"), {make_nc_method_result_length_datatype()} }, - { U("NcPropertyChangeType"), {make_nc_property_change_type_datatype()} }, - { U("NcPropertyChangedEventData"), {make_nc_property_changed_event_data_datatype()} }, - { U("NcDescriptor"), {make_nc_descriptor_datatype()} }, - { U("NcBlockMemberDescriptor"), {make_nc_block_member_descriptor_datatype()} }, - { U("NcMethodResultBlockMemberDescriptors"), {make_nc_method_result_block_member_descriptors_datatype()} }, - { U("NcVersionCode"), {make_nc_version_code_datatype()} }, - { U("NcOrganizationId"), {make_nc_organization_id_datatype()} }, - { U("NcUri"), {make_nc_uri_datatype()} }, - { U("NcManufacturer"), {make_nc_manufacturer_datatype()} }, - { U("NcUuid"), {make_nc_uuid_datatype()} }, - { U("NcProduct"), {make_nc_product_datatype()} }, - { U("NcDeviceGenericState"), {make_nc_device_generic_state_datatype()} }, - { U("NcDeviceOperationalState"), {make_nc_device_operational_state_datatype()} }, - { U("NcResetCause"), {make_nc_reset_cause_datatype()} }, - { U("NcName"), {make_nc_name_datatype()} }, - { U("NcPropertyDescriptor"), {make_nc_property_descriptor_datatype()} }, - { U("NcParameterDescriptor"), {make_nc_parameter_descriptor_datatype()} }, - { U("NcMethodId"), {make_nc_method_id_datatype()} }, - { U("NcMethodDescriptor"), {make_nc_method_descriptor_datatype()} }, - { U("NcEventId"), {make_nc_event_id_datatype()} }, - { U("NcEventDescriptor"), {make_nc_event_descriptor_datatype()} }, - { U("NcClassDescriptor"), {make_nc_class_descriptor_datatype()} }, - { U("NcParameterConstraints"), {make_nc_parameter_constraints_datatype()} }, - { U("NcDatatypeType"), {make_nc_datatype_type_datatype()} }, - { U("NcDatatypeDescriptor"), {make_nc_datatype_descriptor_datatype()} }, - { U("NcMethodResultClassDescriptor"), {make_nc_method_result_class_descriptor_datatype()} }, - { U("NcMethodResultDatatypeDescriptor"), {make_nc_method_result_datatype_descriptor_datatype()} }, - { U("NcMethodResultError"), {make_nc_method_result_error_datatype()} }, - { U("NcDatatypeDescriptorEnum"), {make_nc_datatype_descriptor_enum_datatype()} }, - { U("NcDatatypeDescriptorPrimitive"), {make_nc_datatype_descriptor_primitive_datatype()} }, - { U("NcDatatypeDescriptorStruct"), {make_nc_datatype_descriptor_struct_datatype()} }, - { U("NcDatatypeDescriptorTypeDef"), {make_nc_datatype_descriptor_type_def_datatype()} }, - { U("NcEnumItemDescriptor"), {make_nc_enum_item_descriptor_datatype()} }, - { U("NcFieldDescriptor"), {make_nc_field_descriptor_datatype()} }, - { U("NcPropertyConstraintsNumber"), {make_nc_property_constraints_number_datatype()} }, - { U("NcPropertyConstraintsString"), {make_nc_property_constraints_string_datatype()} }, - { U("NcRegex"), {make_nc_regex_datatype()} }, - { U("NcRolePath"), {make_nc_role_path_datatype()} }, - { U("NcParameterConstraintsNumber"), {make_nc_parameter_constraints_number_datatype()} }, - { U("NcParameterConstraintsString"), {make_nc_parameter_constraints_string_datatype()} }, - { U("NcTimeInterval"), {make_nc_time_interval_datatype()} }, - { U("NcTouchpointNmos"), {make_nc_touchpoint_nmos_datatype()} }, - { U("NcTouchpointNmosChannelMapping"), {make_nc_touchpoint_nmos_channel_mapping_datatype()} }, - { U("NcTouchpointResource"), {make_nc_touchpoint_resource_datatype()} }, - { U("NcTouchpointResourceNmos"), {make_nc_touchpoint_resource_nmos_datatype()} }, - { U("NcTouchpointResourceNmosChannelMapping"), {make_nc_touchpoint_resource_nmos_channel_mapping_datatype()} }, + { U("NcBoolean"), {nc::make_boolean_datatype()} }, + { U("NcInt16"), {nc::make_int16_datatype()} }, + { U("NcInt32"), {nc::make_int32_datatype()} }, + { U("NcInt64"), {nc::make_int64_datatype()} }, + { U("NcUint16"), {nc::make_uint16_datatype()} }, + { U("NcUint32"), {nc::make_uint32_datatype()} }, + { U("NcUint64"), {nc::make_uint64_datatype()} }, + { U("NcFloat32"), {nc::make_float32_datatype()} }, + { U("NcFloat64"), {nc::make_float64_datatype()} }, + { U("NcString"), {nc::make_string_datatype()} }, + { U("NcClassId"), {nc::make_class_id_datatype()} }, + { U("NcOid"), {nc::make_oid_datatype()} }, + { U("NcTouchpoint"), {nc::make_touchpoint_datatype()} }, + { U("NcElementId"), {nc::make_element_id_datatype()} }, + { U("NcPropertyId"), {nc::make_property_id_datatype()} }, + { U("NcPropertyConstraints"), {nc::make_property_contraints_datatype()} }, + { U("NcMethodResultPropertyValue"), {nc::make_method_result_property_value_datatype()} }, + { U("NcMethodStatus"), {nc::make_method_status_datatype()} }, + { U("NcMethodResult"), {nc::make_method_result_datatype()} }, + { U("NcId"), {nc::make_id_datatype()} }, + { U("NcMethodResultId"), {nc::make_method_result_id_datatype()} }, + { U("NcMethodResultLength"), {nc::make_method_result_length_datatype()} }, + { U("NcPropertyChangeType"), {nc::make_property_change_type_datatype()} }, + { U("NcPropertyChangedEventData"), {nc::make_property_changed_event_data_datatype()} }, + { U("NcDescriptor"), {nc::make_descriptor_datatype()} }, + { U("NcBlockMemberDescriptor"), {nc::make_block_member_descriptor_datatype()} }, + { U("NcMethodResultBlockMemberDescriptors"), {nc::make_method_result_block_member_descriptors_datatype()} }, + { U("NcVersionCode"), {nc::make_version_code_datatype()} }, + { U("NcOrganizationId"), {nc::make_organization_id_datatype()} }, + { U("NcUri"), {nc::make_uri_datatype()} }, + { U("NcManufacturer"), {nc::make_manufacturer_datatype()} }, + { U("NcUuid"), {nc::make_uuid_datatype()} }, + { U("NcProduct"), {nc::make_product_datatype()} }, + { U("NcDeviceGenericState"), {nc::make_device_generic_state_datatype()} }, + { U("NcDeviceOperationalState"), {nc::make_device_operational_state_datatype()} }, + { U("NcResetCause"), {nc::make_reset_cause_datatype()} }, + { U("NcName"), {nc::make_name_datatype()} }, + { U("NcPropertyDescriptor"), {nc::make_property_descriptor_datatype()} }, + { U("NcParameterDescriptor"), {nc::make_parameter_descriptor_datatype()} }, + { U("NcMethodId"), {nc::make_method_id_datatype()} }, + { U("NcMethodDescriptor"), {nc::make_method_descriptor_datatype()} }, + { U("NcEventId"), {nc::make_event_id_datatype()} }, + { U("NcEventDescriptor"), {nc::make_event_descriptor_datatype()} }, + { U("NcClassDescriptor"), {nc::make_class_descriptor_datatype()} }, + { U("NcParameterConstraints"), {nc::make_parameter_constraints_datatype()} }, + { U("NcDatatypeType"), {nc::make_datatype_type_datatype()} }, + { U("NcDatatypeDescriptor"), {nc::make_datatype_descriptor_datatype()} }, + { U("NcMethodResultClassDescriptor"), {nc::make_method_result_class_descriptor_datatype()} }, + { U("NcMethodResultDatatypeDescriptor"), {nc::make_method_result_datatype_descriptor_datatype()} }, + { U("NcMethodResultError"), {nc::make_method_result_error_datatype()} }, + { U("NcDatatypeDescriptorEnum"), {nc::make_datatype_descriptor_enum_datatype()} }, + { U("NcDatatypeDescriptorPrimitive"), {nc::make_datatype_descriptor_primitive_datatype()} }, + { U("NcDatatypeDescriptorStruct"), {nc::make_datatype_descriptor_struct_datatype()} }, + { U("NcDatatypeDescriptorTypeDef"), {nc::make_datatype_descriptor_type_def_datatype()} }, + { U("NcEnumItemDescriptor"), {nc::make_enum_item_descriptor_datatype()} }, + { U("NcFieldDescriptor"), {nc::make_field_descriptor_datatype()} }, + { U("NcPropertyConstraintsNumber"), {nc::make_property_constraints_number_datatype()} }, + { U("NcPropertyConstraintsString"), {nc::make_property_constraints_string_datatype()} }, + { U("NcRegex"), {nc::make_regex_datatype()} }, + { U("NcRolePath"), {nc::make_role_path_datatype()} }, + { U("NcParameterConstraintsNumber"), {nc::make_parameter_constraints_number_datatype()} }, + { U("NcParameterConstraintsString"), {nc::make_parameter_constraints_string_datatype()} }, + { U("NcTimeInterval"), {nc::make_time_interval_datatype()} }, + { U("NcTouchpointNmos"), {nc::make_touchpoint_nmos_datatype()} }, + { U("NcTouchpointNmosChannelMapping"), {nc::make_touchpoint_nmos_channel_mapping_datatype()} }, + { U("NcTouchpointResource"), {nc::make_touchpoint_resource_datatype()} }, + { U("NcTouchpointResourceNmos"), {nc::make_touchpoint_resource_nmos_datatype()} }, + { U("NcTouchpointResourceNmosChannelMapping"), {nc::make_touchpoint_resource_nmos_channel_mapping_datatype()} }, // Monitoring feature set // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#datatypes - { U("NcConnectionStatus"), {make_nc_connection_status_datatype()} }, - { U("NcCounter"), {make_nc_counter_datatype()} }, - { U("NcEssenceStatus"), {make_nc_essence_status_datatype()} }, - { U("NcLinkStatus"), {make_nc_link_status_datatype()} }, - { U("NcMethodResultCounters"), {make_nc_method_result_counters_datatype()} }, - { U("NcOverallStatus"), {make_nc_overall_status_datatype()} }, - { U("NcSynchronizationStatus"), {make_nc_synchronization_status_datatype()} }, - { U("NcStreamStatus"), {make_nc_stream_status_datatype()} }, - { U("NcTransmissionStatus"), {make_nc_transmission_status_datatype()} } + { U("NcConnectionStatus"), {nc::make_connection_status_datatype()} }, + { U("NcCounter"), {nc::make_counter_datatype()} }, + { U("NcEssenceStatus"), {nc::make_essence_status_datatype()} }, + { U("NcLinkStatus"), {nc::make_link_status_datatype()} }, + { U("NcMethodResultCounters"), {nc::make_method_result_counters_datatype()} }, + { U("NcOverallStatus"), {nc::make_overall_status_datatype()} }, + { U("NcSynchronizationStatus"), {nc::make_synchronization_status_datatype()} }, + { U("NcStreamStatus"), {nc::make_stream_status_datatype()} }, + { U("NcTransmissionStatus"), {nc::make_transmission_status_datatype()} }, + // Device configuration feature set + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#datatypes + { U("NcRestoreMode"), {nc::make_restore_mode_datatype()} }, + { U("NcPropertyHolder"), {nc::make_property_holder_datatype()} }, + { U("NcObjectPropertiesHolder"), {nc::make_object_properties_holder_datatype()} }, + { U("NcBulkPropertiesHolder"), {nc::make_bulk_properties_holder_datatype()} }, + { U("NcRestoreValidationStatus"), {nc::make_restore_validation_status_datatype()} }, + { U("NcPropertyRestoreNoticeType"), {nc::make_property_restore_notice_type_datatype()} }, + { U("NcPropertyRestoreNotice"), {nc::make_property_restore_notice_datatype()} }, + { U("NcObjectPropertiesSetValidation"), {nc::make_object_properties_set_validation_datatype()} }, + { U("NcMethodResultBulkPropertiesHolder"), {nc::make_method_result_bulk_properties_holder_datatype()} }, + { U("NcMethodResultObjectPropertiesSetValidation"), {nc::make_method_result_object_properties_set_validation_datatype()} } }; } diff --git a/Development/nmos/control_protocol_state.h b/Development/nmos/control_protocol_state.h index 162786f28..d0b13fcfb 100644 --- a/Development/nmos/control_protocol_state.h +++ b/Development/nmos/control_protocol_state.h @@ -3,6 +3,7 @@ #include #include "cpprest/json_utils.h" +#include "nmos/configuration_handlers.h" #include "nmos/control_protocol_handlers.h" #include "nmos/control_protocol_typedefs.h" #include "nmos/mutex.h" @@ -62,8 +63,7 @@ namespace nmos nmos::read_lock read_lock() const { return nmos::read_lock{ mutex }; } nmos::write_lock write_lock() const { return nmos::write_lock{ mutex }; } - control_protocol_state(get_packet_counters_handler get_lost_packet_counters = nullptr, get_packet_counters_handler get_late_packet_counters = nullptr, reset_monitor_handler reset_monitor = nullptr, control_protocol_property_changed_handler property_changed = nullptr); - + control_protocol_state(control_protocol_property_changed_handler property_changed = nullptr, create_validation_fingerprint_handler create_validation_fingerprint = nullptr, validate_validation_fingerprint_handler validate_validation_fingerprintget_read_only_modification_allow_list_handler = nullptr, get_read_only_modification_allow_list_handler get_read_only_modification_allow_list = nullptr, remove_device_model_object_handler remove_device_model_object = nullptr, create_device_model_object_handler create_device_model_object = nullptr, get_packet_counters_handler get_lost_packet_counters = nullptr, get_packet_counters_handler get_late_packet_counters = nullptr, reset_monitor_handler reset_monitor = nullptr); // insert control class descriptor, false if class descriptor already inserted bool insert(const experimental::control_class_descriptor& control_class_descriptor); // erase control class of the given class id, false if the required class not found diff --git a/Development/nmos/control_protocol_typedefs.h b/Development/nmos/control_protocol_typedefs.h index 462574721..33e0311d6 100644 --- a/Development/nmos/control_protocol_typedefs.h +++ b/Development/nmos/control_protocol_typedefs.h @@ -190,6 +190,41 @@ namespace nmos }; } + // NcRestoreMode + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestoremode + namespace nc_restore_mode + { + enum restore_mode + { + modify = 0, // Restore mode is Modify + rebuild = 1 // Restore mode is Rebuild + }; + } + + // NcRestoreValidationStatus + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncrestorevalidationstatus + namespace nc_restore_validation_status + { + enum status + { + ok = 200, // Restore was successful + failed = 400, // Restore failed because relevant backup data set provided is invalid + not_found = 404, // Restore failed because the role path is not found in the device model or the device cannot create the role path from the data set + device_error = 500 // Restore failed due to an internal device error preventing the restore from happening + }; + } + + // NcPropertyRestoreNoticeType + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncpropertyrestorenoticetype + namespace nc_property_restore_notice_type + { + enum type + { + warning = 300, // Warning property restore notice + error = 400 // Error property restore notice + }; + } + // NcElementId // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncelementid struct nc_element_id @@ -246,6 +281,11 @@ namespace nmos // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor const nc_method_id nc_sender_monitor_get_transmission_error_counters_method_id(4, 1); const nc_method_id nc_sender_monitor_reset_monitor_method_id(4, 2); + // NcMethodsIds for NcBulkPropertiesManager + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesholder + const nc_method_id nc_bulk_properties_manager_get_properties_by_path_method_id(3, 1); + const nc_method_id nc_bulk_properties_manager_validate_set_properties_by_path_method_id(3, 2); + const nc_method_id nc_bulk_properties_manager_set_properties_by_path_method_id(3, 3); // NcPropertyId // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncpropertyid @@ -334,8 +374,6 @@ namespace nmos // NcOid // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncoid typedef uint32_t nc_oid; - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Blocks.html - const nc_oid root_block_oid{ 1 }; // NcUri // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncuri @@ -356,6 +394,11 @@ namespace nmos // NcClassId // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncclassid typedef std::vector nc_class_id; + + // NcRolePath + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncrolepath + typedef std::vector nc_role_path; + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncobject const nc_class_id nc_object_class_id({ 1 }); // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncblock @@ -376,6 +419,8 @@ namespace nmos const nc_class_id nc_receiver_monitor_class_id({ 1, 2, 2, 1 }); // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/monitoring/#ncsendermonitor const nc_class_id nc_sender_monitor_class_id({ 1, 2, 2, 2 }); + // See https://specs.amwa.tv/nmos-control-feature-sets/branches/main/device-configuration/#ncbulkpropertiesmanager + const nc_class_id nc_bulk_properties_manager_class_id({ 1, 3, 3 }); // NcTouchpoint // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#nctouchpoint @@ -457,7 +502,7 @@ namespace nmos , id(id) {} - nc_touchpoint_resource_nmos(const ncp_nmos_resource_type& resource_type, nc_uuid id) + nc_touchpoint_resource_nmos(const ncp_touchpoint_resource_type& resource_type, nc_uuid id) : nc_touchpoint_resource(resource_type.name) , id(id) {} @@ -485,6 +530,14 @@ namespace nmos friend bool operator!=(const nc_touchpoint_resource_nmos_channel_mapping& lhs, const nc_touchpoint_resource_nmos_channel_mapping& rhs) { return !(lhs == rhs); } friend bool operator<(const nc_touchpoint_resource_nmos_channel_mapping& lhs, const nc_touchpoint_resource_nmos_channel_mapping& rhs) { return lhs.tied() < rhs.tied(); } }; + + // Root block specification + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Blocks.html + const nc_oid root_block_oid{ 1 }; + const utility::string_t root_block_role{ U("root") }; + + // Device Configuration + const utility::string_t bulk_properties_manager_role{ root_block_role + U(".BulkPropertiesManager") }; } #endif diff --git a/Development/nmos/control_protocol_utils.cpp b/Development/nmos/control_protocol_utils.cpp index 502da3602..a9fd83d24 100644 --- a/Development/nmos/control_protocol_utils.cpp +++ b/Development/nmos/control_protocol_utils.cpp @@ -1,7 +1,9 @@ #include "nmos/control_protocol_utils.h" +#include #include #include +#include #include #include "bst/regex.h" #include "cpprest/json_utils.h" @@ -13,1364 +15,1493 @@ namespace nmos { - namespace details + namespace nc { - bool is_control_class(const nc_class_id& control_class_id, const nc_class_id& class_id_) + namespace details { - nc_class_id class_id{ class_id_ }; - if (control_class_id.size() < class_id.size()) + bool is_control_class(const nc_class_id& control_class_id, const nc_class_id& class_id_) { - // truncate test class_id to relevant class_id - class_id.resize(control_class_id.size()); + nc_class_id class_id{class_id_}; + if (control_class_id.size() < class_id.size()) + { + // truncate test class_id to relevant class_id + class_id.resize(control_class_id.size()); + } + return control_class_id == class_id; } - return control_class_id == class_id; - } - - // get the runtime property constraints of a specific property_id - web::json::value get_runtime_property_constraints(const nc_property_id& property_id, const web::json::value& runtime_property_constraints) - { - using web::json::value; - if (!runtime_property_constraints.is_null()) + // get the runtime property constraints of a specific property_id + web::json::value get_runtime_property_constraints(const nc_property_id& property_id, const web::json::value& runtime_property_constraints) { - auto& runtime_prop_constraints = runtime_property_constraints.as_array(); - auto found_constraints = std::find_if(runtime_prop_constraints.begin(), runtime_prop_constraints.end(), [&property_id](const web::json::value& constraints) - { - return property_id == parse_nc_property_id(nmos::fields::nc::property_id(constraints)); - }); + using web::json::value; - if (runtime_prop_constraints.end() != found_constraints) + if (!runtime_property_constraints.is_null()) { - return *found_constraints; + auto& runtime_prop_constraints = runtime_property_constraints.as_array(); + auto found_constraints = std::find_if(runtime_prop_constraints.begin(), runtime_prop_constraints.end(), [&property_id](const web::json::value& constraints) + { + return property_id == parse_property_id(nmos::fields::nc::property_id(constraints)); + }); + + if (runtime_prop_constraints.end() != found_constraints) + { + return *found_constraints; + } } + return value::null(); } - return value::null(); - } - - // get the datatype descriptor of a specific type_name - web::json::value get_datatype_descriptor(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) - { - using web::json::value; - if (!type_name.is_null()) + // get the datatype descriptor of a specific type_name + web::json::value get_datatype_descriptor(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { - return get_control_protocol_datatype_descriptor(type_name.as_string()).descriptor; - } - return value::null(); - } + using web::json::value; - // get the datatype property constraints of a specific type_name - web::json::value get_datatype_constraints(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) - { - using web::json::value; + if (!type_name.is_null()) + { + return get_control_protocol_datatype_descriptor(type_name.as_string()).descriptor; + } + return value::null(); + } - // NcDatatypeDescriptor - const auto& datatype_descriptor = get_datatype_descriptor(type_name, get_control_protocol_datatype_descriptor); - if (!datatype_descriptor.is_null()) + // get the datatype property constraints of a specific type_name + web::json::value get_datatype_constraints(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { - return nmos::fields::nc::constraints(datatype_descriptor); + using web::json::value; + + // NcDatatypeDescriptor + const auto& datatype_descriptor = get_datatype_descriptor(type_name, get_control_protocol_datatype_descriptor); + if (!datatype_descriptor.is_null()) + { + return nmos::fields::nc::constraints(datatype_descriptor); + } + return value::null(); } - return value::null(); - } - // constraints validation, may throw nmos::control_protocol_exception - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring - void constraints_validation(const web::json::value& data, const web::json::value& constraints) - { - auto parameter_constraints_validation = [&constraints](const web::json::value& value) + // constraints validation, may throw nmos::control_protocol_exception + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring + void constraints_validation(const web::json::value& data, const web::json::value& constraints) { - // is numeric constraints - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber - if (constraints.has_field(nmos::fields::nc::step) && !nmos::fields::nc::step(constraints).is_null()) + auto parameter_constraints_validation = [&constraints](const web::json::value& value) { - if (value.is_null()) { throw control_protocol_exception("value is null"); } + // is numeric constraints + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsnumber + if (constraints.has_field(nmos::fields::nc::step) && !nmos::fields::nc::step(constraints).is_null()) + { + if (value.is_null()) { throw control_protocol_exception("value is null"); } - if (!value.is_integer()) { throw control_protocol_exception("value is not an integer"); } + if (!value.is_integer()) { throw control_protocol_exception("value is not an integer"); } - const auto step = nmos::fields::nc::step(constraints).as_double(); - if (step <= 0) { throw control_protocol_exception("step is not a positive integer"); } + const auto step = nmos::fields::nc::step(constraints).as_double(); + if (step <= 0) { throw control_protocol_exception("step is not a positive integer"); } - const auto value_double = value.as_double(); + const auto value_double = value.as_double(); + if (constraints.has_field(nmos::fields::nc::minimum) && !nmos::fields::nc::minimum(constraints).is_null()) + { + auto min = nmos::fields::nc::minimum(constraints).as_double(); + if (0 != std::fmod(value_double - min, step)) { throw control_protocol_exception("value is not divisible by step"); } + } + else if (constraints.has_field(nmos::fields::nc::maximum) && !nmos::fields::nc::maximum(constraints).is_null()) + { + auto max = nmos::fields::nc::maximum(constraints).as_double(); + if (0 != std::fmod(max - value_double, step)) { throw control_protocol_exception("value is not divisible by step"); } + } + else + { + if (0 != std::fmod(value_double, step)) { throw control_protocol_exception("value is not divisible by step"); } + } + } if (constraints.has_field(nmos::fields::nc::minimum) && !nmos::fields::nc::minimum(constraints).is_null()) { - auto min = nmos::fields::nc::minimum(constraints).as_double(); - if (0 != std::fmod(value_double - min, step)) { throw control_protocol_exception("value is not divisible by step"); } + if (value.is_null()) { throw control_protocol_exception("value is null"); } + + if (!value.is_integer() || value.as_double() < nmos::fields::nc::minimum(constraints).as_double()) { throw control_protocol_exception("value is less than minimum"); } } - else if (constraints.has_field(nmos::fields::nc::maximum) && !nmos::fields::nc::maximum(constraints).is_null()) + if (constraints.has_field(nmos::fields::nc::maximum) && !nmos::fields::nc::maximum(constraints).is_null()) { - auto max = nmos::fields::nc::maximum(constraints).as_double(); - if (0 != std::fmod(max - value_double, step)) { throw control_protocol_exception("value is not divisible by step"); } + if (value.is_null()) { throw control_protocol_exception("value is null"); } + + if (!value.is_integer() || value.as_double() > nmos::fields::nc::maximum(constraints).as_double()) { throw control_protocol_exception("value is greater than maximum"); } } - else + + // is string constraints + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring + if (constraints.has_field(nmos::fields::nc::max_characters) && !constraints.at(nmos::fields::nc::max_characters).is_null()) { - if (0 != std::fmod(value_double, step)) { throw control_protocol_exception("value is not divisible by step"); } - } - } - if (constraints.has_field(nmos::fields::nc::minimum) && !nmos::fields::nc::minimum(constraints).is_null()) - { - if (value.is_null()) { throw control_protocol_exception("value is null"); } + if (value.is_null()) { throw control_protocol_exception("value is null"); } - if (!value.is_integer() || value.as_double() < nmos::fields::nc::minimum(constraints).as_double()) { throw control_protocol_exception("value is less than minimum"); } - } - if (constraints.has_field(nmos::fields::nc::maximum) && !nmos::fields::nc::maximum(constraints).is_null()) - { - if (value.is_null()) { throw control_protocol_exception("value is null"); } + const size_t max_characters = nmos::fields::nc::max_characters(constraints); + if (!value.is_string() || value.as_string().length() > max_characters) { throw control_protocol_exception("value is longer than maximum characters"); } + } + if (constraints.has_field(nmos::fields::nc::pattern) && !constraints.at(nmos::fields::nc::pattern).is_null()) + { + if (value.is_null()) { throw control_protocol_exception("value is null"); } - if (!value.is_integer() || value.as_double() > nmos::fields::nc::maximum(constraints).as_double()) { throw control_protocol_exception("value is greater than maximum"); } - } + if (!value.is_string()) { throw control_protocol_exception("value is not a string"); } + const auto value_string = utility::us2s(value.as_string()); + bst::regex pattern(utility::us2s(nmos::fields::nc::pattern(constraints))); + if (!bst::regex_match(value_string, pattern)) { throw control_protocol_exception("value dose not match the pattern"); } + } - // is string constraints - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Framework.html#ncparameterconstraintsstring - if (constraints.has_field(nmos::fields::nc::max_characters) && !constraints.at(nmos::fields::nc::max_characters).is_null()) - { - if (value.is_null()) { throw control_protocol_exception("value is null"); } + // reaching here, parameter validation successfully + }; - const size_t max_characters = nmos::fields::nc::max_characters(constraints); - if (!value.is_string() || value.as_string().length() > max_characters) { throw control_protocol_exception("value is longer than maximum characters"); } - } - if (constraints.has_field(nmos::fields::nc::pattern) && !constraints.at(nmos::fields::nc::pattern).is_null()) + if (data.is_array()) { - if (value.is_null()) { throw control_protocol_exception("value is null"); } - - if (!value.is_string()) { throw control_protocol_exception("value is not a string"); } - const auto value_string = utility::us2s(value.as_string()); - bst::regex pattern(utility::us2s(nmos::fields::nc::pattern(constraints))); - if (!bst::regex_match(value_string, pattern)) { throw control_protocol_exception("value dose not match the pattern"); } + for (const auto& value : data.as_array()) + { + parameter_constraints_validation(value); + } } - - // reaching here, parameter validation successfully - }; - - if (data.is_array()) - { - for (const auto& value : data.as_array()) + else { - parameter_constraints_validation(value); + parameter_constraints_validation(data); } } - else - { - parameter_constraints_validation(data); - } - } - // level 0 datatype constraints validation, may throw nmos::control_protocol_exception - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - void datatype_constraints_validation(const web::json::value& data, const datatype_constraints_validation_parameters& params) - { - auto parameter_constraints_validation = [¶ms](const web::json::value& value_) + // level 0 datatype constraints validation, may throw nmos::control_protocol_exception + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html + void datatype_constraints_validation(const web::json::value& data, const datatype_constraints_validation_parameters& params) { - // no constraints validation required - if (params.datatype_descriptor.is_null()) { return; } + auto parameter_constraints_validation = [¶ms](const web::json::value& value_) + { + // no constraints validation required + if (params.datatype_descriptor.is_null()) { return; } - const auto& datatype_type = nmos::fields::nc::type(params.datatype_descriptor); + const auto& datatype_type = nmos::fields::nc::type(params.datatype_descriptor); - // do NcDatatypeDescriptorPrimitive constraints validation - if (nc_datatype_type::Primitive == datatype_type) - { - // hmm, for the primitive type, it should not have datatype constraints specified via the datatype_descriptor but just in case - const auto& datatype_constraints = nmos::fields::nc::constraints(params.datatype_descriptor); - if (datatype_constraints.is_null()) + // do NcDatatypeDescriptorPrimitive constraints validation + if (nc_datatype_type::Primitive == datatype_type) { - auto primitive_validation = [](const nc_name& name, const web::json::value& value) + // hmm, for the primitive type, it should not have datatype constraints specified via the datatype_descriptor but just in case + const auto& datatype_constraints = nmos::fields::nc::constraints(params.datatype_descriptor); + if (datatype_constraints.is_null()) { - auto is_int16 = [](int32_t value) - { - return value >= (std::numeric_limits::min)() - && value <= (std::numeric_limits::max)(); - }; - auto is_uint16 = [](uint32_t value) - { - return value >= (std::numeric_limits::min)() - && value <= (std::numeric_limits::max)(); - }; - auto is_float32 = [](double value) + auto primitive_validation = [](const nc_name& name, const web::json::value& value) { - return value >= (std::numeric_limits::lowest)() - && value <= (std::numeric_limits::max)(); + auto is_int16 = [](int32_t value) + { + return value >= (std::numeric_limits::min)() + && value <= (std::numeric_limits::max)(); + }; + auto is_uint16 = [](uint32_t value) + { + return value >= (std::numeric_limits::min)() + && value <= (std::numeric_limits::max)(); + }; + auto is_float32 = [](double value) + { + return value >= (std::numeric_limits::lowest)() + && value <= (std::numeric_limits::max)(); + }; + + if (U("NcBoolean") == name) { return value.is_boolean(); } + if (U("NcInt16") == name && value.is_number()) { return is_int16(value.as_number().to_int32()); } + if (U("NcInt32") == name && value.is_number()) { return value.as_number().is_int32(); } + if (U("NcInt64") == name && value.is_number()) { return value.as_number().is_int64(); } + if (U("NcUint16") == name && value.is_number()) { return is_uint16(value.as_number().to_uint32()); } + if (U("NcUint32") == name && value.is_number()) { return value.as_number().is_uint32(); } + if (U("NcUint64") == name && value.is_number()) { return value.as_number().is_uint64(); } + if (U("NcFloat32") == name && value.is_number()) { return is_float32(value.as_number().to_double()); } + if (U("NcFloat64") == name && value.is_number()) { return !value.as_number().is_integral(); } + if (U("NcString") == name) { return value.is_string(); } + + // invalid primitive type + return false; }; - if (U("NcBoolean") == name) { return value.is_boolean(); } - if (U("NcInt16") == name && value.is_number()) { return is_int16(value.as_number().to_int32()); } - if (U("NcInt32") == name && value.is_number()) { return value.as_number().is_int32(); } - if (U("NcInt64") == name && value.is_number()) { return value.as_number().is_int64(); } - if (U("NcUint16") == name && value.is_number()) { return is_uint16(value.as_number().to_uint32()); } - if (U("NcUint32") == name && value.is_number()) { return value.as_number().is_uint32(); } - if (U("NcUint64") == name && value.is_number()) { return value.as_number().is_uint64(); } - if (U("NcFloat32") == name && value.is_number()) { return is_float32(value.as_number().to_double()); } - if (U("NcFloat64") == name && value.is_number()) { return !value.as_number().is_integral(); } - if (U("NcString") == name) { return value.is_string(); } - - // invalid primitive type - return false; - }; - - // do primitive type constraints validation - const auto& name = nmos::fields::nc::name(params.datatype_descriptor); - if (!primitive_validation(name, value_)) + // do primitive type constraints validation + const auto& name = nmos::fields::nc::name(params.datatype_descriptor); + if (!primitive_validation(name, value_)) + { + throw control_protocol_exception("value is not a " + utility::us2s(name) + " type");; + } + } + else { - throw control_protocol_exception("value is not a " + utility::us2s(name) + " type");; + constraints_validation(value_, datatype_constraints); } - } - else - { - constraints_validation(value_, datatype_constraints); - } - - return; - } - // do NcDatatypeDescriptorTypeDef constraints validation - if (nc_datatype_type::Typedef == datatype_type) - { - // do the datatype constraints specified via the datatype_descriptor if presented - const auto& datatype_constraints = nmos::fields::nc::constraints(params.datatype_descriptor); - if (datatype_constraints.is_null()) - { - // do parent typename constraints validation - const auto& type_name = params.datatype_descriptor.at(nmos::fields::nc::parent_type); // parent type_name - datatype_constraints_validation(value_, { details::get_datatype_descriptor(type_name, params.get_control_protocol_datatype_descriptor), params.get_control_protocol_datatype_descriptor }); + return; } - else + + // do NcDatatypeDescriptorTypeDef constraints validation + if (nc_datatype_type::Typedef == datatype_type) { - constraints_validation(value_, datatype_constraints); - } + // do the datatype constraints specified via the datatype_descriptor if presented + const auto& datatype_constraints = nmos::fields::nc::constraints(params.datatype_descriptor); + if (datatype_constraints.is_null()) + { + // do parent typename constraints validation + const auto& type_name = params.datatype_descriptor.at(nmos::fields::nc::parent_type); // parent type_name + datatype_constraints_validation(value_, {details::get_datatype_descriptor(type_name, params.get_control_protocol_datatype_descriptor), params.get_control_protocol_datatype_descriptor}); + } + else + { + constraints_validation(value_, datatype_constraints); + } - return; - } + return; + } - // do NcDatatypeDescriptorEnum constraints validation - if (nc_datatype_type::Enum == datatype_type) - { - const auto& items = nmos::fields::nc::items(params.datatype_descriptor); - if (items.end() == std::find_if(items.begin(), items.end(), [&](const web::json::value& nc_enum_item_descriptor) { return nmos::fields::nc::value(nc_enum_item_descriptor) == value_; })) + // do NcDatatypeDescriptorEnum constraints validation + if (nc_datatype_type::Enum == datatype_type) { - const auto& name = nmos::fields::nc::name(params.datatype_descriptor); - throw control_protocol_exception("value is not an enum " + utility::us2s(name) + " type"); - } + const auto& items = nmos::fields::nc::items(params.datatype_descriptor); + if (items.end() == std::find_if(items.begin(), items.end(), [&](const web::json::value& nc_enum_item_descriptor) { return nmos::fields::nc::value(nc_enum_item_descriptor) == value_; })) + { + const auto& name = nmos::fields::nc::name(params.datatype_descriptor); + throw control_protocol_exception("value is not an enum " + utility::us2s(name) + " type"); + } - return; - } + return; + } - // do NcDatatypeDescriptorStruct constraints validation - if (nc_datatype_type::Struct == datatype_type) - { - const auto& datatype_name = nmos::fields::nc::name(params.datatype_descriptor); - const auto& fields = nmos::fields::nc::fields(params.datatype_descriptor); - // NcFieldDescriptor - for (const web::json::value& nc_field_descriptor : fields) + // do NcDatatypeDescriptorStruct constraints validation + if (nc_datatype_type::Struct == datatype_type) { - const auto& field_name = nmos::fields::nc::name(nc_field_descriptor); - // is field in strurcture - if (!value_.has_field(field_name)) { throw control_protocol_exception("missing " + utility::us2s(field_name) + " in " + utility::us2s(datatype_name)); } + const auto& datatype_name = nmos::fields::nc::name(params.datatype_descriptor); + const auto& fields = nmos::fields::nc::fields(params.datatype_descriptor); + // NcFieldDescriptor + for (const web::json::value& nc_field_descriptor : fields) + { + const auto& field_name = nmos::fields::nc::name(nc_field_descriptor); + // is field in strurcture + if (!value_.has_field(field_name)) { throw control_protocol_exception("missing " + utility::us2s(field_name) + " in " + utility::us2s(datatype_name)); } - // is field nullable - if (!nmos::fields::nc::is_nullable(nc_field_descriptor) && value_.at(field_name).is_null()) { throw control_protocol_exception(utility::us2s(field_name) + " is not nullable"); } + // is field nullable + if (!nmos::fields::nc::is_nullable(nc_field_descriptor) && value_.at(field_name).is_null()) { throw control_protocol_exception(utility::us2s(field_name) + " is not nullable"); } - // if field value is null continue to next field - if (value_.at(field_name).is_null()) continue; + // if field value is null continue to next field + if (value_.at(field_name).is_null()) continue; - // is field sequenceable - if (nmos::fields::nc::is_sequence(nc_field_descriptor) != value_.at(field_name).is_array()) { throw control_protocol_exception(utility::us2s(field_name) + " is not sequenceable"); } + // is field sequenceable + if (nmos::fields::nc::is_sequence(nc_field_descriptor) != value_.at(field_name).is_array()) { throw control_protocol_exception(utility::us2s(field_name) + " is not sequenceable"); } - // check constraints of its typeName - const auto& field_type_name = nc_field_descriptor.at(nmos::fields::nc::type_name); + // check constraints of its typeName + const auto& field_type_name = nc_field_descriptor.at(nmos::fields::nc::type_name); - if (!field_type_name.is_null()) - { - auto value = value_.at(field_name); + if (!field_type_name.is_null()) + { + auto value = value_.at(field_name); - // do typename constraints validation - datatype_constraints_validation(value, { details::get_datatype_descriptor(field_type_name, params.get_control_protocol_datatype_descriptor), params.get_control_protocol_datatype_descriptor }); - } + // do typename constraints validation + datatype_constraints_validation(value, {details::get_datatype_descriptor(field_type_name, params.get_control_protocol_datatype_descriptor), params.get_control_protocol_datatype_descriptor}); + } - // check against field constraints if present - const auto& constraints = nmos::fields::nc::constraints(nc_field_descriptor); - if (!constraints.is_null()) - { - // do field constraints validation - const auto& value = value_.at(field_name); - constraints_validation(value, constraints); + // check against field constraints if present + const auto& constraints = nmos::fields::nc::constraints(nc_field_descriptor); + if (!constraints.is_null()) + { + // do field constraints validation + const auto& value = value_.at(field_name); + constraints_validation(value, constraints); + } } + // unsupported datatype_type, no validation is required + return; } - // unsupported datatype_type, no validation is required - return; - } - }; + }; - if (data.is_array()) - { - for (const auto& value : data.as_array()) + if (data.is_array()) + { + for (const auto& value : data.as_array()) + { + parameter_constraints_validation(value); + } + } + else { - parameter_constraints_validation(value); + parameter_constraints_validation(data); } } - else + + // multiple levels of constraints validation, may throw nmos::control_protocol_exception + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html + void constraints_validation(const web::json::value& data, const web::json::value& runtime_property_constraints, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) { - parameter_constraints_validation(data); - } - } + // do level 2 runtime property constraints validation + if (!runtime_property_constraints.is_null()) { constraints_validation(data, runtime_property_constraints); return; } - // multiple levels of constraints validation, may throw nmos::control_protocol_exception - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - void constraints_validation(const web::json::value& data, const web::json::value& runtime_property_constraints, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) - { - // do level 2 runtime property constraints validation - if (!runtime_property_constraints.is_null()) { constraints_validation(data, runtime_property_constraints); return; } + // do level 1 property constraints validation + if (!property_constraints.is_null()) { constraints_validation(data, property_constraints); return; } - // do level 1 property constraints validation - if (!property_constraints.is_null()) { constraints_validation(data, property_constraints); return; } + // do level 0 datatype constraints validation + datatype_constraints_validation(data, params); + } - // do level 0 datatype constraints validation - datatype_constraints_validation(data, params); - } + // method parameter constraints validation, may throw nmos::control_protocol_exception + void method_parameter_constraints_validation(const web::json::value& data, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) + { + using web::json::value; - // method parameter constraints validation, may throw nmos::control_protocol_exception - void method_parameter_constraints_validation(const web::json::value& data, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) - { - using web::json::value; + // do level 1 property constraints & level 0 datatype constraints validation + constraints_validation(data, value::null(), property_constraints, params); + } - // do level 1 property constraints & level 0 datatype constraints validation - constraints_validation(data, value::null(), property_constraints, params); - } + web::json::value get_nc_block_member_descriptor(const resources& resources, const nmos::resource& parent_nc_block_resource, web::json::array& role_path_segments) + { + if (parent_nc_block_resource.data.has_field(nmos::fields::nc::members)) + { + const auto& members = nmos::fields::nc::members(parent_nc_block_resource.data); - // Set status and status message - bool set_monitor_status(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, - const nc_property_id& status_property_id, - const nc_property_id& status_message_property_id, - const nc_property_id& status_transition_counter_property_id, - const utility::string_t& status_pending_received_time_field_name, - get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, - slog::base_gate& gate) - { - auto current_connection_status = get_control_protocol_property(resources, oid, status_property_id, get_control_protocol_class_descriptor, gate); + const auto role_path_segement = web::json::front(role_path_segments); + role_path_segments.erase(0); + // find the role_path_segment member + auto member_found = std::find_if(members.begin(), members.end(), [&](const web::json::value& member) + { + return role_path_segement.as_string() == nmos::fields::nc::role(member); + }); - web::json::value json_status_message = status_message.size() ? web::json::value::string(status_message) : web::json::value::null(); + if (members.end() != member_found) + { + if (role_path_segments.size() == 0) + { + // NcBlockMemberDescriptor + return *member_found; + } - set_control_protocol_property_and_notify(resources, oid, status_property_id, status, get_control_protocol_class_descriptor, gate); - set_control_protocol_property_and_notify(resources, oid, status_message_property_id, json_status_message, get_control_protocol_class_descriptor, gate); - // Cancel any pending status updates - set_control_protocol_property(resources, oid, status_pending_received_time_field_name, web::json::value::number(0), gate); + // get the role_path_segement member resource + if (is_block(parse_class_id(nmos::fields::nc::class_id(*member_found)))) + { + // get resource based on the oid + const auto& oid = nmos::fields::nc::oid(*member_found); + const auto& found = nmos::find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + return get_nc_block_member_descriptor(resources, *found, role_path_segments); + } + } + } + } + return web::json::value{}; + } - // if status is "partially unhealthy" (2) or "unhealthy" (3) and less healthy than current state - if (status > 1 && status > current_connection_status.as_integer()) + web::json::value parse_role_path(const utility::string_t& role_path_) { - // increment transition_counter - auto transition_counter = get_control_protocol_property(resources, oid, status_transition_counter_property_id, get_control_protocol_class_descriptor, gate).as_integer(); - set_control_protocol_property_and_notify(resources, oid, status_transition_counter_property_id, ++transition_counter, get_control_protocol_class_descriptor, gate); + // tokenize the role_path with the '.' delimiter + std::list role_path_segments; + boost::algorithm::split(role_path_segments, role_path_, [](utility::char_t c) { return '.' == c; }); + + return web::json::value_from_elements(role_path_segments); } - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + + // Set status and status message + bool set_monitor_status(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, + const nc_property_id& status_property_id, + const nc_property_id& status_message_property_id, + const nc_property_id& status_transition_counter_property_id, + const utility::string_t& status_pending_received_time_field_name, + get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, + slog::base_gate& gate) { - if (nmos::is_nc_sender_monitor(details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)))) + auto current_connection_status = get_property(resources, oid, status_property_id, get_control_protocol_class_descriptor, gate); + + web::json::value json_status_message = status_message.size() ? web::json::value::string(status_message) : web::json::value::null(); + + set_property_and_notify(resources, oid, status_property_id, status, get_control_protocol_class_descriptor, gate); + set_property_and_notify(resources, oid, status_message_property_id, json_status_message, get_control_protocol_class_descriptor, gate); + // Cancel any pending status updates + set_property(resources, oid, status_pending_received_time_field_name, web::json::value::number(0), gate); + + // if status is "partially unhealthy" (2) or "unhealthy" (3) and less healthy than current state + if (status > 1 && status > current_connection_status.as_integer()) { - return details::update_sender_monitor_overall_status(resources, oid, get_control_protocol_class_descriptor, gate); + // increment transition_counter + auto transition_counter = get_property(resources, oid, status_transition_counter_property_id, get_control_protocol_class_descriptor, gate).as_integer(); + set_property_and_notify(resources, oid, status_transition_counter_property_id, ++transition_counter, get_control_protocol_class_descriptor, gate); + } + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + if (nmos::nc::is_sender_monitor(parse_class_id(nmos::fields::nc::class_id(found->data)))) + { + return details::update_sender_monitor_overall_status(resources, oid, get_control_protocol_class_descriptor, gate); + } + return details::update_receiver_monitor_overall_status(resources, oid, get_control_protocol_class_descriptor, gate); } - return details::update_receiver_monitor_overall_status(resources, oid, get_control_protocol_class_descriptor, gate); - } - return false; - } - - // Set monitor status and status message - bool set_monitor_status_with_delay(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, - const nc_property_id& status_property_id, - const nc_property_id& status_message_property_id, - const nc_property_id& status_transition_counter_property_id, - const utility::string_t& status_pending_field_name, - const utility::string_t& status_message_pending_time_field_name, - const utility::string_t& status_pending_received_time_field_name, - long long now_time, - monitor_status_pending_handler monitor_status_pending, - get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, - slog::base_gate& gate) - { - const auto& current_status = get_control_protocol_property(resources, oid, status_property_id, get_control_protocol_class_descriptor, gate); - if (current_status.is_null()) - { - // should never happen, missing receiver/sender monitor status property - slog::log(gate, SLOG_FLF) << U("receiver/sender monitor status property: {level=") << status_property_id.level << U(", index=") << status_property_id.index << U("} not found"); return false; } - // check whether the the status message changed when the status is unchanged - if (status == current_status.as_integer()) + // Set monitor status and status message + bool set_monitor_status_with_delay(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, + const nc_property_id& status_property_id, + const nc_property_id& status_message_property_id, + const nc_property_id& status_transition_counter_property_id, + const utility::string_t& status_pending_field_name, + const utility::string_t& status_message_pending_time_field_name, + const utility::string_t& status_pending_received_time_field_name, + long long now_time, + monitor_status_pending_handler monitor_status_pending, + get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, + slog::base_gate& gate) { - // has status message changed? - const auto& current_status_message = get_control_protocol_property(resources, oid, status_message_property_id, get_control_protocol_class_descriptor, gate); - if ((current_status_message.is_null() && status_message.size()) || (!current_status_message.is_null() && current_status_message.as_string() != status_message)) + const auto& current_status = get_property(resources, oid, status_property_id, get_control_protocol_class_descriptor, gate); + if (current_status.is_null()) { - // If the status message has changed then update only that - web::json::value json_status_message = status_message.size() ? web::json::value::string(status_message) : web::json::value::null(); - return set_control_protocol_property_and_notify(resources, oid, status_message_property_id, json_status_message, get_control_protocol_class_descriptor, gate); + // should never happen, missing receiver/sender monitor status property + slog::log(gate, SLOG_FLF) << U("receiver/sender monitor status property: {level=") << status_property_id.level << U(", index=") << status_property_id.index << U("} not found"); + return false; } - // no update required, no changes on status or status message - return true; - } - // status has changed + // check whether the the status message changed when the status is unchanged + if (status == current_status.as_integer()) + { + // has status message changed? + const auto& current_status_message = get_property(resources, oid, status_message_property_id, get_control_protocol_class_descriptor, gate); + if ((current_status_message.is_null() && status_message.size()) || (!current_status_message.is_null() && current_status_message.as_string() != status_message)) + { + // If the status message has changed then update only that + web::json::value json_status_message = status_message.size() ? web::json::value::string(status_message) : web::json::value::null(); + return set_property_and_notify(resources, oid, status_message_property_id, json_status_message, get_control_protocol_class_descriptor, gate); + } + // no update required, no changes on status or status message + return true; + } - utility::string_t updated_status_message = status_message; + // status has changed - // if status is "healthy" then preserve the previous status message - if (1 == status && status_message.size() == 0) - { - // Get existing status message and prepend with "Previously: " - const auto& current_status_message = get_control_protocol_property(resources, oid, status_message_property_id, get_control_protocol_class_descriptor, gate); + utility::string_t updated_status_message = status_message; - if (!current_status_message.is_null()) + // if status is "healthy" then preserve the previous status message + if (1 == status && status_message.size() == 0) { - utility::ostringstream_t ss; - ss << U("Previously: ") << current_status_message.as_string(); - updated_status_message = ss.str(); - } - } - // if status or current state is "inactive" (0), update status and status message immediately - if (0 == status || 0 == current_status.as_integer()) - { - return set_monitor_status(resources, oid, status, updated_status_message, status_property_id, status_message_property_id, status_transition_counter_property_id, status_pending_received_time_field_name, get_control_protocol_class_descriptor, gate); - } - else - { - const auto& activation_time = get_control_protocol_property(resources, oid, nmos::fields::nc::monitor_activation_time, gate); - const auto& status_reporting_delay = get_control_protocol_property(resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); + // Get existing status message and prepend with "Previously: " + const auto& current_status_message = get_property(resources, oid, status_message_property_id, get_control_protocol_class_descriptor, gate); - if (status > current_status.as_integer() && now_time > (static_cast(activation_time.as_integer()) + status_reporting_delay.as_integer())) + if (!current_status_message.is_null()) + { + utility::ostringstream_t ss; + ss << U("Previously: ") << current_status_message.as_string(); + updated_status_message = ss.str(); + } + } + // if status or current state is "inactive" (0), update status and status message immediately + if (0 == status || 0 == current_status.as_integer()) { - // becoming less health and not in the initial activation state - // immediately set the status return set_monitor_status(resources, oid, status, updated_status_message, status_property_id, status_message_property_id, status_transition_counter_property_id, status_pending_received_time_field_name, get_control_protocol_class_descriptor, gate); } else { - web::json::value json_status_message = updated_status_message.size() ? web::json::value::string(updated_status_message) : web::json::value::null(); - // becoming more health or in the initial activation state - // set the status with delay - const auto& pending_received_time = get_control_protocol_property(resources, oid, status_pending_received_time_field_name, gate); + const auto& activation_time = get_property(resources, oid, nmos::fields::nc::monitor_activation_time, gate); + const auto& status_reporting_delay = get_property(resources, oid, nc_status_monitor_status_reporting_delay, get_control_protocol_class_descriptor, gate); - // only update pending received time if not already set - if (pending_received_time.as_integer() == 0) + if (status > current_status.as_integer() && now_time > (static_cast(activation_time.as_integer()) + status_reporting_delay.as_integer())) + { + // becoming less health and not in the initial activation state + // immediately set the status + return set_monitor_status(resources, oid, status, updated_status_message, status_property_id, status_message_property_id, status_transition_counter_property_id, status_pending_received_time_field_name, get_control_protocol_class_descriptor, gate); + } + else { - if (!set_control_protocol_property(resources, oid, status_pending_received_time_field_name, now_time, gate)) + web::json::value json_status_message = updated_status_message.size() ? web::json::value::string(updated_status_message) : web::json::value::null(); + // becoming more health or in the initial activation state + // set the status with delay + const auto& pending_received_time = get_property(resources, oid, status_pending_received_time_field_name, gate); + + // only update pending received time if not already set + if (pending_received_time.as_integer() == 0) { - return false; + if (!set_property(resources, oid, status_pending_received_time_field_name, now_time, gate)) + { + return false; + } } - } - if (set_control_protocol_property(resources, oid, status_pending_field_name, status, gate) - && set_control_protocol_property(resources, oid, status_message_pending_time_field_name, json_status_message, gate)) - { - monitor_status_pending(); - return true; + if (set_property(resources, oid, status_pending_field_name, status, gate) + && set_property(resources, oid, status_message_pending_time_field_name, json_status_message, gate)) + { + monitor_status_pending(); + return true; + } + return false; } - return false; } } - } - - web::json::value get_overall_status_message(const resources& resources, nc_oid oid, const std::vector>& status_property_ids, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - // overall status message displays the most unhealthy status message. Priority lowest to highest -> inactive, healthy, partially unhealthy, unhealthy - // overall status message displays root cause of problem. Priority of messages lowest to highest -> sync, payload, transport, link - auto overall_status_message = web::json::value::null(); - for (int status_health = 0; status_health < 5; ++status_health) // Iterate through health of statuses + web::json::value get_overall_status_message(const resources& resources, nc_oid oid, const std::vector>& status_property_ids, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - for (const auto& property_id_pair : status_property_ids) + // overall status message displays the most unhealthy status message. Priority lowest to highest -> inactive, healthy, partially unhealthy, unhealthy + // overall status message displays root cause of problem. Priority of messages lowest to highest -> sync, payload, transport, link + auto overall_status_message = web::json::value::null(); + + for (int status_health = 0; status_health < 5; ++status_health) // Iterate through health of statuses { - auto status = get_control_protocol_property(resources, oid, property_id_pair.first, get_control_protocol_class_descriptor, gate); + for (const auto& property_id_pair : status_property_ids) + { + auto status = get_property(resources, oid, property_id_pair.first, get_control_protocol_class_descriptor, gate); - if (status.as_integer() != status_health) continue; + if (status.as_integer() != status_health) continue; - auto status_message = get_control_protocol_property(resources, oid, property_id_pair.second, get_control_protocol_class_descriptor, gate); + auto status_message = get_property(resources, oid, property_id_pair.second, get_control_protocol_class_descriptor, gate); - if (!status_message.is_null()) - { - overall_status_message = status_message; + if (!status_message.is_null()) + { + overall_status_message = status_message; + } } } + return overall_status_message; } - return overall_status_message; - } - bool update_receiver_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - std::vector> status_message_property_ids = { - std::pair(nc_receiver_monitor_external_synchronization_status_property_id, nc_receiver_monitor_external_synchronization_status_message_property_id), - std::pair(nc_receiver_monitor_stream_status_property_id, nc_receiver_monitor_stream_status_message_property_id), - std::pair(nc_receiver_monitor_connection_status_property_id, nc_receiver_monitor_connection_status_message_property_id), - std::pair(nc_receiver_monitor_link_status_property_id, nc_receiver_monitor_link_status_message_property_id)}; - - // Update Overall Status - auto connection_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); - auto stream_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); - const auto& overall_status_message = get_overall_status_message(resources, oid, status_message_property_ids, get_control_protocol_class_descriptor, gate); - - // if connection or stream status is Inactive - if (nc_connection_status::status::inactive == connection_status.as_integer() || nc_stream_status::status::inactive == stream_status.as_integer()) + bool update_receiver_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - // Overall status is set to Inactive - bool success = set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, nc_overall_status::status::inactive, get_control_protocol_class_descriptor, gate); - return success && set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); - } + std::vector> status_message_property_ids = { + std::pair(nc_receiver_monitor_external_synchronization_status_property_id, nc_receiver_monitor_external_synchronization_status_message_property_id), + std::pair(nc_receiver_monitor_stream_status_property_id, nc_receiver_monitor_stream_status_message_property_id), + std::pair(nc_receiver_monitor_connection_status_property_id, nc_receiver_monitor_connection_status_message_property_id), + std::pair(nc_receiver_monitor_link_status_property_id, nc_receiver_monitor_link_status_message_property_id)}; + + // Update Overall Status + auto connection_status = get_property(resources, oid, nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto stream_status = get_property(resources, oid, nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + const auto& overall_status_message = get_overall_status_message(resources, oid, status_message_property_ids, get_control_protocol_class_descriptor, gate); + + // if connection or stream status is Inactive + if (nc_connection_status::status::inactive == connection_status.as_integer() || nc_stream_status::status::inactive == stream_status.as_integer()) + { + // Overall status is set to Inactive + bool success = set_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, nc_overall_status::status::inactive, get_control_protocol_class_descriptor, gate); + return success && set_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); + } - auto link_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); - auto external_synchronization_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto link_status = get_property(resources, oid, nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto external_synchronization_status = get_property(resources, oid, nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); - // otherwise take the least healthy status as the overall status - std::vector statuses = { link_status.as_integer(), connection_status.as_integer(), stream_status.as_integer() }; + // otherwise take the least healthy status as the overall status + std::vector statuses = {link_status.as_integer(), connection_status.as_integer(), stream_status.as_integer()}; - // Ignore external synchronization status if it is not used - if (nc_synchronization_status::status::not_used != external_synchronization_status.as_integer()) - { - statuses.push_back(external_synchronization_status.as_integer()); + // Ignore external synchronization status if it is not used + if (nc_synchronization_status::status::not_used != external_synchronization_status.as_integer()) + { + statuses.push_back(external_synchronization_status.as_integer()); + } + // Find most unhealthy status + auto overall_status = *std::max_element(statuses.begin(), statuses.end()); + bool success = set_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, web::json::value::number(overall_status), get_control_protocol_class_descriptor, gate); + return success && set_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); } - // Find most unhealthy status - auto overall_status = *std::max_element(statuses.begin(), statuses.end()); - bool success = set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, web::json::value::number(overall_status), get_control_protocol_class_descriptor, gate); - return success && set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); - } - bool update_sender_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - std::vector> status_message_property_ids = { - std::pair(nc_sender_monitor_external_synchronization_status_property_id, nc_sender_monitor_external_synchronization_status_message_property_id), - std::pair(nc_sender_monitor_essence_status_property_id, nc_sender_monitor_essence_status_message_property_id), - std::pair(nc_sender_monitor_transmission_status_property_id, nc_sender_monitor_transmission_status_message_property_id), - std::pair(nc_sender_monitor_link_status_property_id, nc_sender_monitor_link_status_message_property_id)}; + bool update_sender_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + std::vector> status_message_property_ids = { + std::pair(nc_sender_monitor_external_synchronization_status_property_id, nc_sender_monitor_external_synchronization_status_message_property_id), + std::pair(nc_sender_monitor_essence_status_property_id, nc_sender_monitor_essence_status_message_property_id), + std::pair(nc_sender_monitor_transmission_status_property_id, nc_sender_monitor_transmission_status_message_property_id), + std::pair(nc_sender_monitor_link_status_property_id, nc_sender_monitor_link_status_message_property_id)}; - // Update Overall Status - auto transmission_status = get_control_protocol_property(resources, oid, nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); - auto essence_status = get_control_protocol_property(resources, oid, nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + // Update Overall Status + auto transmission_status = get_property(resources, oid, nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto essence_status = get_property(resources, oid, nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); - const auto& overall_status_message = get_overall_status_message(resources, oid, status_message_property_ids, get_control_protocol_class_descriptor, gate); + const auto& overall_status_message = get_overall_status_message(resources, oid, status_message_property_ids, get_control_protocol_class_descriptor, gate); - // if transmission or stream status is Inactive - if (nc_transmission_status::status::inactive == transmission_status.as_integer() || nc_essence_status::status::inactive == essence_status.as_integer()) - { - // Overall status is set to Inactive - bool success = set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, nc_overall_status::status::inactive, get_control_protocol_class_descriptor, gate); - return success && set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); - } + // if transmission or stream status is Inactive + if (nc_transmission_status::status::inactive == transmission_status.as_integer() || nc_essence_status::status::inactive == essence_status.as_integer()) + { + // Overall status is set to Inactive + bool success = set_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, nc_overall_status::status::inactive, get_control_protocol_class_descriptor, gate); + return success && set_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); + } - auto link_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); - auto external_synchronization_status = get_control_protocol_property(resources, oid, nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto link_status = get_property(resources, oid, nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto external_synchronization_status = get_property(resources, oid, nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); - // otherwise take the least healthy status as the overall status - std::vector statuses = { link_status.as_integer(), transmission_status.as_integer(), essence_status.as_integer() }; + // otherwise take the least healthy status as the overall status + std::vector statuses = {link_status.as_integer(), transmission_status.as_integer(), essence_status.as_integer()}; - // Ignore external synchronization status if it is not used - if (nc_synchronization_status::status::not_used != external_synchronization_status.as_integer()) - { - statuses.push_back(external_synchronization_status.as_integer()); + // Ignore external synchronization status if it is not used + if (nc_synchronization_status::status::not_used != external_synchronization_status.as_integer()) + { + statuses.push_back(external_synchronization_status.as_integer()); + } + // Find most unhealthy status + auto overall_status = *std::max_element(statuses.begin(), statuses.end()); + bool success = set_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, web::json::value::number(overall_status), get_control_protocol_class_descriptor, gate); + return success && set_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); } - // Find most unhealthy status - auto overall_status = *std::max_element(statuses.begin(), statuses.end()); - bool success = set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_property_id, web::json::value::number(overall_status), get_control_protocol_class_descriptor, gate); - return success && set_control_protocol_property_and_notify(resources, oid, nc_status_monitor_overall_status_message_property_id, overall_status_message, get_control_protocol_class_descriptor, gate); } - } - // is the given class_id a NcBlock - bool is_nc_block(const nc_class_id& class_id) - { - return details::is_control_class(nc_block_class_id, class_id); - } + // is the given class_id a NcBlock + bool is_block(const nc_class_id& class_id) + { + return details::is_control_class(nc_block_class_id, class_id); + } - // is the given class_id a NcWorker - bool is_nc_worker(const nc_class_id& class_id) - { - return details::is_control_class(nc_worker_class_id, class_id); - } + // is the given class_id a NcWorker + bool is_worker(const nc_class_id& class_id) + { + return details::is_control_class(nc_worker_class_id, class_id); + } - // is the given class_id a NcManager - bool is_nc_manager(const nc_class_id& class_id) - { - return details::is_control_class(nc_manager_class_id, class_id); - } + // is the given class_id a NcManager + bool is_manager(const nc_class_id& class_id) + { + return details::is_control_class(nc_manager_class_id, class_id); + } - // is the given class_id a NcDeviceManager - bool is_nc_device_manager(const nc_class_id& class_id) - { - return details::is_control_class(nc_device_manager_class_id, class_id); - } + // is the given class_id a NcDeviceManager + bool is_device_manager(const nc_class_id& class_id) + { + return details::is_control_class(nc_device_manager_class_id, class_id); + } - // is the given class_id a NcClassManager - bool is_nc_class_manager(const nc_class_id& class_id) - { - return details::is_control_class(nc_class_manager_class_id, class_id); - } + // is the given class_id a NcClassManager + bool is_class_manager(const nc_class_id& class_id) + { + return details::is_control_class(nc_class_manager_class_id, class_id); + } - // is the given class_id a NcStatusMonitor - bool is_nc_status_monitor(const nc_class_id& class_id) - { - return details::is_control_class(nc_status_monitor_class_id, class_id); - } + // is the given class_id a NcStatusMonitor + bool is_status_monitor(const nc_class_id& class_id) + { + return details::is_control_class(nc_status_monitor_class_id, class_id); + } - // is the given class_id a NcStatusMonitor - bool is_nc_sender_monitor(const nc_class_id& class_id) - { - return details::is_control_class(nc_sender_monitor_class_id, class_id); - } + // is the given class_id a NcStatusMonitor + bool is_sender_monitor(const nc_class_id& class_id) + { + return details::is_control_class(nc_sender_monitor_class_id, class_id); + } - // construct NcClassId - nc_class_id make_nc_class_id(const nc_class_id& prefix, int32_t authority_key, const std::vector& suffix) - { - nc_class_id class_id = prefix; - class_id.push_back(authority_key); - class_id.insert(class_id.end(), suffix.begin(), suffix.end()); - return class_id; - } - nc_class_id make_nc_class_id(const nc_class_id& prefix, const std::vector& suffix) - { - return make_nc_class_id(prefix, 0, suffix); - } + // construct NcClassId + nc_class_id make_class_id(const nc_class_id& prefix, int32_t authority_key, const std::vector& suffix) + { + nc_class_id class_id = prefix; + class_id.push_back(authority_key); + class_id.insert(class_id.end(), suffix.begin(), suffix.end()); + return class_id; + } + nc_class_id make_class_id(const nc_class_id& prefix, const std::vector& suffix) + { + return make_class_id(prefix, 0, suffix); + } - // find control class property descriptor (NcPropertyDescriptor) - web::json::value find_property_descriptor(const nc_property_id& property_id, const nc_class_id& class_id_, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) - { - using web::json::value; + // find control class property descriptor (NcPropertyDescriptor) + web::json::value find_property_descriptor(const nc_property_id& property_id, const nc_class_id& class_id_, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) + { + using web::json::value; - auto class_id = class_id_; + auto class_id = class_id_; - while (!class_id.empty()) - { - const auto& control_class = get_control_protocol_class_descriptor(class_id); - auto& property_descriptors = control_class.property_descriptors.as_array(); - auto found = std::find_if(property_descriptors.begin(), property_descriptors.end(), [&property_id](const web::json::value& property_descriptor) + while (!class_id.empty()) { - return (property_id == nmos::details::parse_nc_property_id(nmos::fields::nc::id(property_descriptor))); - }); - if (property_descriptors.end() != found) { return *found; } + const auto& control_class = get_control_protocol_class_descriptor(class_id); + const auto& property_descriptors = control_class.property_descriptors.as_array(); + auto found = std::find_if(property_descriptors.begin(), property_descriptors.end(), [&property_id](const web::json::value& property_descriptor) + { + return (property_id == nc::details::parse_property_id(nmos::fields::nc::id(property_descriptor))); + }); + if (property_descriptors.end() != found) { return *found; } - class_id.pop_back(); - } + class_id.pop_back(); + } - return value::null(); - } + return value::null(); + } - // get block member descriptors - void get_member_descriptors(const resources& resources, const resource& resource, bool recurse, web::json::array& descriptors) - { - if (resource.data.has_field(nmos::fields::nc::members)) + // get block member descriptors + void get_member_descriptors(const resources& resources, const resource& resource, bool recurse, web::json::array& descriptors) { - const auto& members = nmos::fields::nc::members(resource.data); - - for (const auto& member : members) + if (resource.data.has_field(nmos::fields::nc::members)) { - web::json::push_back(descriptors, member); - } + const auto& members = nmos::fields::nc::members(resource.data); - if (recurse) - { - // get members on all NcBlock(s) for (const auto& member : members) { - if (is_nc_block(nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(member)))) + web::json::push_back(descriptors, member); + } + + if (recurse) + { + // get members on all NcBlock(s) + for (const auto& member : members) { - // get resource based on the oid - const auto& oid = nmos::fields::nc::oid(member); - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + if (is_block(nc::details::parse_class_id(nmos::fields::nc::class_id(member)))) { - get_member_descriptors(resources, *found, recurse, descriptors); + // get resource based on the oid + const auto& oid = nmos::fields::nc::oid(member); + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + nc::get_member_descriptors(resources, *found, recurse, descriptors); + } } } } } } - } - // find members with given role name or fragment - void find_members_by_role(const resources& resources, const resource& resource, const utility::string_t& role, bool match_whole_string, bool case_sensitive, bool recurse, web::json::array& descriptors) - { - auto find_members_by_matching_role = [&](const web::json::array& members) + // find members with given role name or fragment + void find_members_by_role(const resources& resources, const resource& resource, const utility::string_t& role, bool match_whole_string, bool case_sensitive, bool recurse, web::json::array& descriptors) { - using web::json::value; - - auto match = [&](const web::json::value& descriptor) - { - if (match_whole_string) - { - if (case_sensitive) { return role == nmos::fields::nc::role(descriptor); } - else { return boost::algorithm::to_upper_copy(role) == boost::algorithm::to_upper_copy(nmos::fields::nc::role(descriptor)); } - } - else + auto find_members_by_matching_role = [&](const web::json::array& members) { - if (case_sensitive) { return !boost::find_first(nmos::fields::nc::role(descriptor), role).empty(); } - else { return !boost::ifind_first(nmos::fields::nc::role(descriptor), role).empty(); } - } - }; + using web::json::value; - return boost::make_iterator_range(boost::make_filter_iterator(match, members.begin(), members.end()), boost::make_filter_iterator(match, members.end(), members.end())); - }; + auto match = [&](const web::json::value& descriptor) + { + if (match_whole_string) + { + if (case_sensitive) { return role == nmos::fields::nc::role(descriptor); } + else { return boost::algorithm::to_upper_copy(role) == boost::algorithm::to_upper_copy(nmos::fields::nc::role(descriptor)); } + } + else + { + if (case_sensitive) { return !boost::find_first(nmos::fields::nc::role(descriptor), role).empty(); } + else { return !boost::ifind_first(nmos::fields::nc::role(descriptor), role).empty(); } + } + }; - if (resource.data.has_field(nmos::fields::nc::members)) - { - const auto& members = nmos::fields::nc::members(resource.data); + return boost::make_iterator_range(boost::make_filter_iterator(match, members.begin(), members.end()), boost::make_filter_iterator(match, members.end(), members.end())); + }; - auto members_found = find_members_by_matching_role(members); - for (const auto& member : members_found) + if (resource.data.has_field(nmos::fields::nc::members)) { - web::json::push_back(descriptors, member); - } + const auto& members = nmos::fields::nc::members(resource.data); - if (recurse) - { - // do role match on all NcBlock(s) - for (const auto& member : members) + auto members_found = find_members_by_matching_role(members); + for (const auto& member : members_found) { - if (is_nc_block(nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(member)))) + web::json::push_back(descriptors, member); + } + + if (recurse) + { + // do role match on all NcBlock(s) + for (const auto& member : members) { - // get resource based on the oid - const auto& oid = nmos::fields::nc::oid(member); - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + if (is_block(nc::details::parse_class_id(nmos::fields::nc::class_id(member)))) { - find_members_by_role(resources, *found, role, match_whole_string, case_sensitive, recurse, descriptors); + // get resource based on the oid + const auto& oid = nmos::fields::nc::oid(member); + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + nc::find_members_by_role(resources, *found, role, match_whole_string, case_sensitive, recurse, descriptors); + } } } } } } - } - // find members with given class id - void find_members_by_class_id(const resources& resources, const nmos::resource& resource, const nc_class_id& class_id_, bool include_derived, bool recurse, web::json::array& descriptors) - { - auto find_members_by_matching_class_id = [&](const web::json::array& members) + // find members with given class id + void find_members_by_class_id(const resources& resources, const nmos::resource& resource, const nc_class_id& class_id_, bool include_derived, bool recurse, web::json::array& descriptors) { - using web::json::value; - - auto match = [&](const web::json::value& descriptor) - { - const auto class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(descriptor)); + auto find_members_by_matching_class_id = [&](const web::json::array& members) + { + using web::json::value; - if (include_derived) { return !boost::find_first(class_id, class_id_).empty(); } - else { return class_id == class_id_; } - }; + auto match = [&](const web::json::value& descriptor) + { + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(descriptor)); - return boost::make_iterator_range(boost::make_filter_iterator(match, members.begin(), members.end()), boost::make_filter_iterator(match, members.end(), members.end())); - }; + if (include_derived) { return !boost::find_first(class_id, class_id_).empty(); } + else { return class_id == class_id_; } + }; - if (resource.data.has_field(nmos::fields::nc::members)) - { - auto& members = nmos::fields::nc::members(resource.data); + return boost::make_iterator_range(boost::make_filter_iterator(match, members.begin(), members.end()), boost::make_filter_iterator(match, members.end(), members.end())); + }; - auto members_found = find_members_by_matching_class_id(members); - for (const auto& member : members_found) + if (resource.data.has_field(nmos::fields::nc::members)) { - web::json::push_back(descriptors, member); - } + auto& members = nmos::fields::nc::members(resource.data); - if (recurse) - { - // do class_id match on all NcBlock(s) - for (const auto& member : members) + auto members_found = find_members_by_matching_class_id(members); + for (const auto& member : members_found) + { + web::json::push_back(descriptors, member); + } + + if (recurse) { - if (is_nc_block(nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(member)))) + // do class_id match on all NcBlock(s) + for (const auto& member : members) { - // get resource based on the oid - const auto& oid = nmos::fields::nc::oid(member); - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + if (is_block(nc::details::parse_class_id(nmos::fields::nc::class_id(member)))) { - find_members_by_class_id(resources, *found, class_id_, include_derived, recurse, descriptors); + // get resource based on the oid + const auto& oid = nmos::fields::nc::oid(member); + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + nc::find_members_by_class_id(resources, *found, class_id_, include_derived, recurse, descriptors); + } } } } } } - } - // push a control protocol resource into other control protocol NcBlock resource - void push_back(control_protocol_resource& nc_block_resource, const control_protocol_resource& resource) - { - // note, model write lock should already be applied by the outer function, so access to control_protocol_resources is OK... + // push a control protocol resource into other control protocol NcBlock resource + void push_back(control_protocol_resource& nc_block_resource, const control_protocol_resource& resource) + { + using web::json::value; - using web::json::value; + auto& parent = nc_block_resource.data; + const auto& child = resource.data; - auto& parent = nc_block_resource.data; - const auto& child = resource.data; + if (!is_block(details::parse_class_id(nmos::fields::nc::class_id(parent)))) throw std::logic_error("non-NcBlock cannot be nested"); - if (!is_nc_block(details::parse_nc_class_id(nmos::fields::nc::class_id(parent)))) throw std::logic_error("non-NcBlock cannot be nested"); + web::json::push_back(parent[nmos::fields::nc::members], + details::make_block_member_descriptor(nmos::fields::description(child), nmos::fields::nc::role(child), nmos::fields::nc::oid(child), nmos::fields::nc::constant_oid(child), nc::details::parse_class_id(nmos::fields::nc::class_id(child)), nmos::fields::nc::user_label(child), nmos::fields::nc::oid(parent))); - web::json::push_back(parent[nmos::fields::nc::members], - details::make_nc_block_member_descriptor(nmos::fields::description(child), nmos::fields::nc::role(child), nmos::fields::nc::oid(child), nmos::fields::nc::constant_oid(child), details::parse_nc_class_id(nmos::fields::nc::class_id(child)), nmos::fields::nc::user_label(child), nmos::fields::nc::oid(parent))); + nc_block_resource.resources.push_back(resource); + } - // add to temporary storage until they are moved to the model resources - nc_block_resource.resources.push_back(resource); - } + // insert root block and all sub control protocol resources + void insert_root(resources& resources, control_protocol_resource& root) + { + // note, model write lock should already be applied by the outer function, so access to control_protocol_resources is OK... - // insert a control protocol resource - std::pair insert_control_protocol_resource(resources& resources, resource&& resource) - { - // set the creation and update timestamps, before inserting the resource - resource.updated = resource.created = nmos::strictly_increasing_update(resources); + std::function insert_resources; - auto result = resources.insert(std::move(resource)); - // replacement of a deleted or expired resource is also allowed - // (currently, with no further checks on api_version, type, etc.) - if (!result.second && !result.first->has_data()) + insert_resources = [&insert_resources](nmos::resources& resources, nmos::control_protocol_resource& resource) + { + for (auto& r : resource.resources) + { + insert_resources(resources, r); + nmos::nc::insert_resource(resources, std::move(r)); + } + resource.resources.clear(); + }; + + insert_resources(resources, root); + nmos::nc::insert_resource(resources, std::move(root)); + } + + // insert a control protocol resource + std::pair insert_resource(resources& resources, resource&& resource) { - // if the insertion was banned, resource has not been moved from - result.second = resources.replace(result.first, std::move(resource)); + // set the creation and update timestamps, before inserting the resource + resource.updated = resource.created = nmos::strictly_increasing_update(resources); + + auto result = resources.insert(std::move(resource)); + // replacement of a deleted or expired resource is also allowed + // (currently, with no further checks on api_version, type, etc.) + if (!result.second && !result.first->has_data()) + { + // if the insertion was banned, resource has not been moved from + result.second = resources.replace(result.first, std::move(resource)); + } + return result; } - return result; - } - // modify a control protocol resource, and insert notification event to all subscriptions - bool modify_control_protocol_resource(resources& resources, const id& id, std::function modifier, const web::json::value& notification_event) - { - // note, model write lock should already be applied by the outer function, so access to control_protocol_resources is OK... + // modify a control protocol resource, and insert notification event to all subscriptions + bool modify_resource(resources& resources, const id& id, std::function modifier, const web::json::value& notification_event) + { + // note, model write lock should already be applied by the outer function, so access to control_protocol_resources is OK... - auto found = resources.find(id); - if (resources.end() == found || !found->has_data()) return false; + auto found = resources.find(id); + if (resources.end() == found || !found->has_data()) return false; - auto pre = notification_event != web::json::value::null() ? found->data : web::json::value::null(); + auto pre = notification_event != web::json::value::null() ? found->data : web::json::value::null(); - // "If an exception is thrown by some user-provided operation, then the element pointed to by position is erased." - // This seems too surprising, despite the fact that it means that a modification may have been partially completed, - // so capture and rethrow. - // See https://www.boost.org/doc/libs/1_68_0/libs/multi_index/doc/reference/ord_indices.html#modify - std::exception_ptr modifier_exception; + // "If an exception is thrown by some user-provided operation, then the element pointed to by position is erased." + // This seems too surprising, despite the fact that it means that a modification may have been partially completed, + // so capture and rethrow. + // See https://www.boost.org/doc/libs/1_68_0/libs/multi_index/doc/reference/ord_indices.html#modify + std::exception_ptr modifier_exception; - auto resource_updated = nmos::strictly_increasing_update(resources); - auto result = resources.modify(found, [&resource_updated, &modifier, &modifier_exception](resource& resource) - { - try + auto resource_updated = nmos::strictly_increasing_update(resources); + auto result = resources.modify(found, [&resource_updated, &modifier, &modifier_exception](resource& resource) + { + try + { + modifier(resource); + } + catch (...) + { + modifier_exception = std::current_exception(); + } + + // set the update timestamp + resource.updated = resource_updated; + }); + + if (web::json::value::null() != notification_event && result) { - modifier(resource); + auto& modified = *found; + nc::insert_notification_events(resources, modified.version, modified.downgrade_version, modified.type, pre, modified.data, notification_event); } - catch (...) + + if (modifier_exception) { - modifier_exception = std::current_exception(); + std::rethrow_exception(modifier_exception); } - // set the update timestamp - resource.updated = resource_updated; - }); + return result; + } - if (web::json::value::null() != notification_event && result) + // erase a control protocol resource + resources::size_type erase_resource(resources& resources, const id& id) { - auto& modified = *found; - insert_notification_events(resources, modified.version, modified.downgrade_version, modified.type, pre, modified.data, notification_event); + // hmm, may be also erasing all it's member blocks? + resources::size_type count = 0; + auto found = resources.find(id); + if (resources.end() != found && found->has_data()) + { + resources.erase(found); + ++count; + } + return count; } - if (modifier_exception) + // find the control protocol resource which is assoicated with the given IS-04/IS-05/IS-08 resource id + resources::const_iterator find_resource(resources& resources, type type, const id& resource_id) { - std::rethrow_exception(modifier_exception); + return find_resource_if(resources, type, [resource_id](const nmos::resource& resource) + { + auto& touchpoints = resource.data.at(nmos::fields::nc::touchpoints); + if (!touchpoints.is_null() && touchpoints.is_array()) + { + auto& tps = touchpoints.as_array(); + auto found_tp = std::find_if(tps.begin(), tps.end(), [resource_id](const web::json::value& touchpoint) + { + auto& resource = nmos::fields::nc::resource(touchpoint); + return (resource_id == nmos::fields::nc::id(resource).as_string()); + }); + return (tps.end() != found_tp); + } + return false; + }); } - return result; - } - - // erase a control protocol resource - resources::size_type erase_control_protocol_resource(resources& resources, const id& id) - { - // hmm, may be also erasing all it's member blocks? - resources::size_type count = 0; - auto found = resources.find(id); - if (resources.end() != found && found->has_data()) + // method parameters constraints validation + void method_parameters_contraints_validation(const web::json::value& arguments, const web::json::value& nc_method_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { - resources.erase(found); - ++count; + for (const auto& param : nmos::fields::nc::parameters(nc_method_descriptor)) + { + const auto& name = nmos::fields::nc::name(param); + const auto& constraints = nmos::fields::nc::constraints(param); + const auto& type_name = param.at(nmos::fields::nc::type_name); + if (arguments.is_null() || !arguments.has_field(name)) + { + // missing argument parameter + throw control_protocol_exception("missing argument parameter " + utility::us2s(name)); + } + details::method_parameter_constraints_validation(arguments.at(name), constraints, { nmos::nc::details::get_datatype_descriptor(type_name, get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor }); + } } - return count; - } - // find the control protocol resource which is associated with the given IS-04/IS-05/IS-08 resource id - resources::const_iterator find_control_protocol_resource(resources& resources, type type, const id& resource_id) - { - return find_resource_if(resources, type, [resource_id](const nmos::resource& resource) + resources::const_iterator find_resource_by_role_path(const resources& resources, const web::json::array& role_path_) { - auto& touchpoints = resource.data.at(nmos::fields::nc::touchpoints); - if (!touchpoints.is_null() && touchpoints.is_array()) + auto role_path = role_path_; + auto resource = nmos::find_resource(resources, utility::s2us(std::to_string(nmos::root_block_oid))); + if (resources.end() != resource) { - auto& tps = touchpoints.as_array(); - auto found_tp = std::find_if(tps.begin(), tps.end(), [resource_id](const web::json::value& touchpoint) + const auto role = nmos::fields::nc::role(resource->data); + + if (role_path.size() && role == web::json::front(role_path).as_string()) { - auto& resource = nmos::fields::nc::resource(touchpoint); - return (resource_id == nmos::fields::nc::id(resource).as_string()); - }); - return (tps.end() != found_tp); + role_path.erase(0); + + if (role_path.size()) + { + const auto& block_member_descriptor = details::get_nc_block_member_descriptor(resources, *resource, role_path); + if (!block_member_descriptor.is_null()) + { + const auto& oid = nmos::fields::nc::oid(block_member_descriptor); + const auto& found = nmos::find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) + { + return found; + } + } + } + else + { + return resource; + } + } } - return false; - }); - } + return resources.end(); + } - // method parameters constraints validation - void method_parameters_contraints_validation(const web::json::value& arguments, const web::json::value& nc_method_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) - { - for (const auto& param : nmos::fields::nc::parameters(nc_method_descriptor)) + resources::const_iterator find_resource_by_role_path(const resources& resources, const utility::string_t& role_path_) { - const auto& name = nmos::fields::nc::name(param); - const auto& constraints = nmos::fields::nc::constraints(param); - const auto& type_name = param.at(nmos::fields::nc::type_name); - if (arguments.is_null() || !arguments.has_field(name)) + const auto& role_path = details::parse_role_path(role_path_); + + return find_resource_by_role_path(resources, role_path.as_array()); + } + + resources::const_iterator find_touchpoint_resource(const resources& resources, const resource& resource) + { + if (!resource.has_data()) { - // missing argument parameter - throw control_protocol_exception("missing argument parameter " + utility::us2s(name)); + return resources.end(); } - details::method_parameter_constraints_validation(arguments.at(name), constraints, { nmos::details::get_datatype_descriptor(type_name, get_control_protocol_datatype_descriptor), get_control_protocol_datatype_descriptor }); - } - } - // insert 'value changed', 'sequence item added', 'sequence item changed' or 'sequence item removed' notification events into all grains whose subscriptions match the specified version, type and "pre" or "post" values - // this is used for the IS-12 propertry changed event - void insert_notification_events(nmos::resources& resources, const nmos::api_version& version, const nmos::api_version& downgrade_version, const nmos::type& type, const web::json::value& pre, const web::json::value& post, const web::json::value& event) - { - using web::json::value; + const auto& touchpoints = resource.data.at(nmos::fields::nc::touchpoints); - if (pre == post) return; + if (touchpoints.size() == 0) + { + return resources.end(); + } - auto& by_type = resources.get(); - const auto subscriptions = by_type.equal_range(details::has_data(nmos::types::subscription)); + // Hmmmmm we're only getting the first touchpoint resource. There could be more than one. + const auto& touchpoint_uuid = nmos::fields::nc::id(nmos::fields::nc::resource(*touchpoints.as_array().begin())); + return nmos::find_resource(resources, touchpoint_uuid.as_string()); + } - for (auto it = subscriptions.first; subscriptions.second != it; ++it) + // insert 'value changed', 'sequence item added', 'sequence item changed' or 'sequence item removed' notification events into all grains whose subscriptions match the specified version, type and "pre" or "post" values + // this is used for the IS-12 propertry changed event + void insert_notification_events(nmos::resources& resources, const nmos::api_version& version, const nmos::api_version& downgrade_version, const nmos::type& type, const web::json::value& pre, const web::json::value& post, const web::json::value& event) { - // for each subscription - const auto& subscription = *it; + using web::json::value; - // check whether the resource_path matches the resource type and the query parameters match either the "pre" or "post" resource + if (pre == post) return; - const auto resource_path = nmos::fields::resource_path(subscription.data); - const resource_query match(subscription.version, resource_path, nmos::fields::params(subscription.data)); + auto& by_type = resources.get(); + const auto subscriptions = by_type.equal_range(nmos::details::has_data(nmos::types::subscription)); - const bool pre_match = match(version, downgrade_version, type, pre, resources); - const bool post_match = match(version, downgrade_version, type, post, resources); + for (auto it = subscriptions.first; subscriptions.second != it; ++it) + { + // for each subscription + const auto& subscription = *it; - if (!pre_match && !post_match) continue; + // check whether the resource_path matches the resource type and the query parameters match either the "pre" or "post" resource - // add the event to the grain for each websocket connection to this subscription + const auto resource_path = nmos::fields::resource_path(subscription.data); + const resource_query match(subscription.version, resource_path, nmos::fields::params(subscription.data)); - for (const auto& id : subscription.sub_resources) - { - auto grain = find_resource(resources, { id, nmos::types::grain }); - if (resources.end() == grain) continue; // check websocket connection is still open + const bool pre_match = match(version, downgrade_version, type, pre, resources); + const bool post_match = match(version, downgrade_version, type, post, resources); + + if (!pre_match && !post_match) continue; - resources.modify(grain, [&resources, &event](nmos::resource& grain) + // add the event to the grain for each websocket connection to this subscription + + for (const auto& id : subscription.sub_resources) { - auto& events = nmos::fields::message_grain_data(grain.data); - web::json::push_back(events, event); - grain.updated = strictly_increasing_update(resources); - }); + auto grain = find_resource(resources, { id, nmos::types::grain }); + if (resources.end() == grain) continue; // check websocket connection is still open + + resources.modify(grain, [&resources, &event](nmos::resource& grain) + { + auto& events = nmos::fields::message_grain_data(grain.data); + web::json::push_back(events, event); + grain.updated = strictly_increasing_update(resources); + }); + } } } - } - web::json::value get_control_protocol_property(const resources& resources, nc_oid oid, const nc_property_id& property_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - // get resource based on the oid - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + web::json::value get_property(const resources& resources, nc_oid oid, const nc_property_id& property_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - // find the relevant nc_property_descriptor - const auto& property = find_property_descriptor(property_id, details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)), get_control_protocol_class_descriptor); - if (!property.is_null() && found->has_data() && found->data.has_field(nmos::fields::nc::name(property))) + // get resource based on the oid + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) { - return found->data.at(nmos::fields::nc::name(property)); + // find the relevant nc_property_descriptor + const auto& property = nc::find_property_descriptor(property_id, nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)), get_control_protocol_class_descriptor); + if (!property.is_null() && found->has_data() && found->data.has_field(nmos::fields::nc::name(property))) + { + return found->data.at(nmos::fields::nc::name(property)); + } } + // unknown property + slog::log(gate, SLOG_FLF) << U("unknown property: {level=") << property_id.level << U(", index=") << property_id.index << U("} to do Get"); + return web::json::value::null(); } - // unknown property - slog::log(gate, SLOG_FLF) << U("unknown property: {level=") << property_id.level << U(", index=") << property_id.index << U("} to do Get"); - return web::json::value::null(); - } - bool set_control_protocol_property_and_notify(resources& resources, nc_oid oid, const nc_property_id& property_id, const web::json::value& value, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + bool set_property_and_notify(resources& resources, nc_oid oid, const nc_property_id& property_id, const web::json::value& value, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - const auto& property = find_property_descriptor(property_id, details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)), get_control_protocol_class_descriptor); - if (!property.is_null()) + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) { - try + const auto& property = nc::find_property_descriptor(property_id, nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)), get_control_protocol_class_descriptor); + if (!property.is_null()) { - // update property - modify_control_protocol_resource(resources, found->id, [&](nmos::resource& resource) + try { - resource.data[nmos::fields::nc::name(property)] = value; + // update property + nc::modify_resource(resources, found->id, [&](nmos::resource& resource) + { + resource.data[nmos::fields::nc::name(property)] = value; - }, make_property_changed_event(oid, { { property_id, nc_property_change_type::type::value_changed, value } })); + }, make_property_changed_event(oid, { { property_id, nc_property_change_type::type::value_changed, value } })); - return true; - } - catch (const nmos::control_protocol_exception& e) - { - slog::log(gate, SLOG_FLF) << "Set property: {level=" << property_id.level << ", index=" << property_id.index << "} error: " << e.what(); - return false; + return true; + } + catch (const nmos::control_protocol_exception& e) + { + slog::log(gate, SLOG_FLF) << "Set property: {level=" << property_id.level << ", index=" << property_id.index << "} error: " << e.what(); + return false; + } } + + // unknown property + slog::log(gate, SLOG_FLF) << "unknown property: {level=" << property_id.level << ", index=" << property_id.index << "} to do Set."; + return false; } - // unknown property - slog::log(gate, SLOG_FLF) << "unknown property: {level=" << property_id.level << ", index=" << property_id.index << "} to do Set."; + // unknown resource + slog::log(gate, SLOG_FLF) << "unknown control protocol resource: oid=" << oid; return false; } - // unknown resource - slog::log(gate, SLOG_FLF) << "unknown control protocol resource: oid=" << oid; - return false; - } + bool set_property(resources& resources, nc_oid oid, const utility::string_t& property_name, const web::json::value& value, slog::base_gate& gate) + { + try + { + nc::modify_resource(resources, utility::s2us(std::to_string(oid)), [&](nmos::resource& resource) + { + resource.data[property_name] = value; + }); + return true; + } + catch (const nmos::control_protocol_exception& e) + { + slog::log(gate, SLOG_FLF) << "Set property name : " << property_name.c_str() << " error: " << e.what(); + return false; + } + } - bool set_control_protocol_property(resources& resources, nc_oid oid, const utility::string_t& property_name, const web::json::value& value, slog::base_gate& gate) - { - try + web::json::value get_property(const resources& resources, nc_oid oid, const utility::string_t& property_name, slog::base_gate& gate) { - modify_control_protocol_resource(resources, utility::s2us(std::to_string(oid)), [&](nmos::resource& resource) + // get resource based on the oid + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found) { - resource.data[property_name] = value; - }); - return true; + // find the relevant nc_property_descriptor + return found->data.at(property_name); + } + // unknown resource + slog::log(gate, SLOG_FLF) << "unknown control protocol resource: oid=" << oid; + return web::json::value::null(); } - catch (const nmos::control_protocol_exception& e) + + // Set link status and link status message + bool set_receiver_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - slog::log(gate, SLOG_FLF) << "Set property name : " << property_name.c_str() << " error: " << e.what(); - return false; + return nc::details::set_monitor_status(resources, oid, link_status, link_status_message, + nc_receiver_monitor_link_status_property_id, + nc_receiver_monitor_link_status_message_property_id, + nc_receiver_monitor_link_status_transition_counter_property_id, + nmos::fields::nc::link_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); } - } - web::json::value get_control_protocol_property(const resources& resources, nc_oid oid, const utility::string_t& property_name, slog::base_gate& gate) - { - // get resource based on the oid - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found) + bool set_receiver_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - // find the relevant nc_property_descriptor - return found->data.at(property_name); + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, link_status, link_status_message, + nc_receiver_monitor_link_status_property_id, + nc_receiver_monitor_link_status_message_property_id, + nc_receiver_monitor_link_status_transition_counter_property_id, + nmos::fields::nc::link_status_pending, + nmos::fields::nc::link_status_message_pending, + nmos::fields::nc::link_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); } - // unknown resource - slog::log(gate, SLOG_FLF) << "unknown control protocol resource: oid=" << oid; - return web::json::value::null(); - } - // Set link status and link status message - bool set_receiver_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, link_status, link_status_message, - nc_receiver_monitor_link_status_property_id, - nc_receiver_monitor_link_status_message_property_id, - nc_receiver_monitor_link_status_transition_counter_property_id, - nmos::fields::nc::link_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } + bool set_receiver_monitor_connection_status(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, connection_status, connection_status_message, + nc_receiver_monitor_connection_status_property_id, + nc_receiver_monitor_connection_status_message_property_id, + nc_receiver_monitor_connection_status_transition_counter_property_id, + nmos::fields::nc::connection_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); + } - bool set_receiver_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, link_status, link_status_message, - nc_receiver_monitor_link_status_property_id, - nc_receiver_monitor_link_status_message_property_id, - nc_receiver_monitor_link_status_transition_counter_property_id, - nmos::fields::nc::link_status_pending, - nmos::fields::nc::link_status_message_pending, - nmos::fields::nc::link_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } + bool set_receiver_monitor_connection_status_with_delay(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, connection_status, connection_status_message, + nc_receiver_monitor_connection_status_property_id, + nc_receiver_monitor_connection_status_message_property_id, + nc_receiver_monitor_connection_status_transition_counter_property_id, + nmos::fields::nc::connection_status_pending, + nmos::fields::nc::connection_status_message_pending, + nmos::fields::nc::connection_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); + } - bool set_receiver_monitor_connection_status(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, connection_status, connection_status_message, - nc_receiver_monitor_connection_status_property_id, - nc_receiver_monitor_connection_status_message_property_id, - nc_receiver_monitor_connection_status_transition_counter_property_id, - nmos::fields::nc::connection_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } + // Set external synchronization status and external synchronization status message + bool set_receiver_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, external_synchronization_status, external_synchronization_status_message, + nc_receiver_monitor_external_synchronization_status_property_id, + nc_receiver_monitor_external_synchronization_status_message_property_id, + nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, + nmos::fields::nc::external_synchronization_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); + } - bool set_receiver_monitor_connection_status_with_delay(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, connection_status, connection_status_message, - nc_receiver_monitor_connection_status_property_id, - nc_receiver_monitor_connection_status_message_property_id, - nc_receiver_monitor_connection_status_transition_counter_property_id, - nmos::fields::nc::connection_status_pending, - nmos::fields::nc::connection_status_message_pending, - nmos::fields::nc::connection_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } + bool set_receiver_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, + nc_receiver_monitor_external_synchronization_status_property_id, + nc_receiver_monitor_external_synchronization_status_message_property_id, + nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, + nmos::fields::nc::external_synchronization_status_pending, + nmos::fields::nc::external_synchronization_status_message_pending, + nmos::fields::nc::external_synchronization_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); + } - // Set external synchronization status and external synchronization status message - bool set_receiver_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, external_synchronization_status, external_synchronization_status_message, - nc_receiver_monitor_external_synchronization_status_property_id, - nc_receiver_monitor_external_synchronization_status_message_property_id, - nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, - nmos::fields::nc::external_synchronization_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } + // Set stream status and stream status message + bool set_receiver_monitor_stream_status(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, stream_status, stream_status_message, + nc_receiver_monitor_stream_status_property_id, + nc_receiver_monitor_stream_status_message_property_id, + nc_receiver_monitor_stream_status_transition_counter_property_id, + nmos::fields::nc::stream_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); + } - bool set_receiver_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, - nc_receiver_monitor_external_synchronization_status_property_id, - nc_receiver_monitor_external_synchronization_status_message_property_id, - nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, - nmos::fields::nc::external_synchronization_status_pending, - nmos::fields::nc::external_synchronization_status_message_pending, - nmos::fields::nc::external_synchronization_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } + bool set_receiver_monitor_stream_status_with_delay(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, stream_status, stream_status_message, + nc_receiver_monitor_stream_status_property_id, + nc_receiver_monitor_stream_status_message_property_id, + nc_receiver_monitor_stream_status_transition_counter_property_id, + nmos::fields::nc::stream_status_pending, + nmos::fields::nc::stream_status_message_pending, + nmos::fields::nc::stream_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); + } - // Set stream status and stream status message - bool set_receiver_monitor_stream_status(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, stream_status, stream_status_message, - nc_receiver_monitor_stream_status_property_id, - nc_receiver_monitor_stream_status_message_property_id, - nc_receiver_monitor_stream_status_transition_counter_property_id, - nmos::fields::nc::stream_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } + // Set synchronization source id + bool set_monitor_synchronization_source_id(resources& resources, nc_oid oid, const bst::optional& source_id_, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + web::json::value source_id = source_id_ ? web::json::value::string(*source_id_) : web::json::value{}; + return set_property_and_notify(resources, oid, nc_receiver_monitor_synchronization_source_id_property_id, source_id, get_control_protocol_class_descriptor, gate); + } - bool set_receiver_monitor_stream_status_with_delay(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, stream_status, stream_status_message, - nc_receiver_monitor_stream_status_property_id, - nc_receiver_monitor_stream_status_message_property_id, - nc_receiver_monitor_stream_status_transition_counter_property_id, - nmos::fields::nc::stream_status_pending, - nmos::fields::nc::stream_status_message_pending, - nmos::fields::nc::stream_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } + bool activate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, slog::base_gate& gate) + { + // A monitor is expected to go through a period of instability upon activation. Therefore, on monitor activation + // domain specific statuses offering an Inactive option MUST transition immediately to the Healthy state. + // Furthermore, after activation, as long as the monitor isn’t being deactivated, it MUST delay the reporting + // of non Healthy states for the duration specified by statusReportingDelay, and then transition to any other appropriate state. + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found && nc::is_status_monitor(nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)))) + { + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)); - // Set synchronization source id - bool set_monitor_synchronization_source_id(resources& resources, nc_oid oid, const bst::optional& source_id_, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - web::json::value source_id = source_id_ ? web::json::value::string(*source_id_) : web::json::value{}; - return set_control_protocol_property_and_notify(resources, oid, nc_receiver_monitor_synchronization_source_id_property_id, source_id, get_control_protocol_class_descriptor, gate); - } + auto activation_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + auto succeed = set_property(resources, oid, nmos::fields::nc::monitor_activation_time, activation_time, gate); + // If autoResetCountersAndMessages set to true then reset the transition counters + bool auto_reset_monitor{false}; - bool activate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, slog::base_gate& gate) - { - // A monitor is expected to go through a period of instability upon activation. Therefore, on monitor activation - // domain specific statuses offering an Inactive option MUST transition immediately to the Healthy state. - // Furthermore, after activation, as long as the monitor isn’t being deactivated, it MUST delay the reporting - // of non Healthy states for the duration specified by statusReportingDelay, and then transition to any other appropriate state. - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found && is_nc_status_monitor(details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)))) - { - const auto& class_id = details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)); + if (nc::is_sender_monitor(class_id)) + { + if (succeed) succeed = set_sender_monitor_transmission_status(resources, oid, nmos::nc_transmission_status::status::healthy, U("Sender activated"), get_control_protocol_class_descriptor, gate); + if (succeed) succeed = set_sender_monitor_essence_status(resources, oid, nmos::nc_essence_status::status::healthy, U("Sender activated"), get_control_protocol_class_descriptor, gate); + } + else + { + if (succeed) succeed = set_receiver_monitor_connection_status(resources, oid, nmos::nc_connection_status::status::healthy, U("Receiver activated"), get_control_protocol_class_descriptor, gate); + if (succeed) succeed = set_receiver_monitor_stream_status(resources, oid, nmos::nc_stream_status::status::healthy, U("Receiver activated"), get_control_protocol_class_descriptor, gate); + } - auto activation_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - auto succeed = set_control_protocol_property(resources, oid, nmos::fields::nc::monitor_activation_time, activation_time, gate); - // If autoResetCountersAndMessages set to true then reset the transition counters - bool auto_reset_monitor{false}; + if (succeed) + { + auto auto_reset_property_id = nc::is_sender_monitor(class_id) ? nmos::nc_sender_monitor_auto_reset_monitor_property_id : nmos::nc_receiver_monitor_auto_reset_monitor_property_id; + auto auto_reset_monitor_ = get_property(resources, oid, auto_reset_property_id, get_control_protocol_class_descriptor, gate); + if (auto_reset_monitor_.is_null()) succeed = false; + else auto_reset_monitor = auto_reset_monitor_.as_bool(); + } - if (is_nc_sender_monitor(class_id)) - { - if (succeed) succeed = set_sender_monitor_transmission_status(resources, oid, nmos::nc_transmission_status::status::healthy, U("Sender activated"), get_control_protocol_class_descriptor, gate); - if (succeed) succeed = set_sender_monitor_essence_status(resources, oid, nmos::nc_essence_status::status::healthy, U("Sender activated"), get_control_protocol_class_descriptor, gate); + if (succeed && auto_reset_monitor) + { + auto reset_monitor_method_id = nc::is_sender_monitor(class_id) ? nmos::nc_sender_monitor_reset_monitor_method_id : nmos::nc_receiver_monitor_reset_monitor_method_id; + // find the method_handler for the reset monitor method + auto method = get_control_protocol_method_descriptor(class_id, reset_monitor_method_id); + auto& nc_method_descriptor = method.first; + auto& reset_monitor = method.second; + if (reset_monitor) + { + // this callback should not throw exceptions + const auto method_result = reset_monitor(resources, *found, web::json::value::null(), nmos::fields::nc::is_deprecated(nc_method_descriptor), gate); + const auto status = nmos::fields::nc::status(method_result); + succeed = (nmos::nc_method_status::ok == status || nmos::nc_method_status::property_deprecated == status || nmos::nc_method_status::method_deprecated == status); + } + } + if (succeed) slog::log(gate, SLOG_FLF) << "Activating monitor oid: " << oid; + else slog::log(gate, SLOG_FLF) << "Fail to activating monitor oid: " << oid; + + return succeed; } else { - if (succeed) succeed = set_receiver_monitor_connection_status(resources, oid, nmos::nc_connection_status::status::healthy, U("Receiver activated"), get_control_protocol_class_descriptor, gate); - if (succeed) succeed = set_receiver_monitor_stream_status(resources, oid, nmos::nc_stream_status::status::healthy, U("Receiver activated"), get_control_protocol_class_descriptor, gate); + // should never happen + slog::log(gate, SLOG_FLF) << "Invalid logic found in activate monitor oid: " << oid; } + return false; + } - if (succeed) + bool deactivate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); + if (resources.end() != found && nc::is_status_monitor(nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)))) { - auto auto_reset_property_id = is_nc_sender_monitor(class_id) ? nmos::nc_sender_monitor_auto_reset_monitor_property_id : nmos::nc_receiver_monitor_auto_reset_monitor_property_id; - auto auto_reset_monitor_ = get_control_protocol_property(resources, oid, auto_reset_property_id, get_control_protocol_class_descriptor, gate); - if (auto_reset_monitor_.is_null()) succeed = false; - else auto_reset_monitor = auto_reset_monitor_.as_bool(); - } + const auto& class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(found->data)); - if (succeed && auto_reset_monitor) - { - auto reset_monitor_method_id = is_nc_sender_monitor(class_id) ? nmos::nc_sender_monitor_reset_monitor_method_id : nmos::nc_receiver_monitor_reset_monitor_method_id; - // find the method_handler for the reset monitor method - auto method = get_control_protocol_method_descriptor(class_id, reset_monitor_method_id); - auto& nc_method_descriptor = method.first; - auto& reset_monitor = method.second; - if (reset_monitor) + auto succeed = set_property(resources, oid, nmos::fields::nc::monitor_activation_time, web::json::value::number(0), gate); + + if (nc::is_sender_monitor(class_id)) { - // this callback should not throw exceptions - const auto method_result = reset_monitor(resources, *found, web::json::value::null(), nmos::fields::nc::is_deprecated(nc_method_descriptor), gate); - const auto status = nmos::fields::nc::status(method_result); - succeed = (nmos::nc_method_status::ok == status || nmos::nc_method_status::property_deprecated == status || nmos::nc_method_status::method_deprecated == status); + if (succeed) succeed = set_sender_monitor_transmission_status(resources, oid, nmos::nc_transmission_status::status::inactive, U("Sender deactivated"), get_control_protocol_class_descriptor, gate); + if (succeed) succeed = set_sender_monitor_essence_status(resources, oid, nmos::nc_essence_status::status::inactive, U("Sender deactivated"), get_control_protocol_class_descriptor, gate); } + else + { + if (succeed) succeed = set_receiver_monitor_connection_status(resources, oid, nmos::nc_connection_status::status::inactive, U("Receiver deactivated"), get_control_protocol_class_descriptor, gate); + if (succeed) succeed = set_receiver_monitor_stream_status(resources, oid, nmos::nc_stream_status::status::inactive, U("Receiver deactivated"), get_control_protocol_class_descriptor, gate); + } + return succeed; + } + else + { + // should never happen + slog::log(gate, SLOG_FLF) << "Invalid logic found in deactivate monitor oid: " << oid; } - if (succeed) slog::log(gate, SLOG_FLF) << "Activating monitor oid: " << oid; - else slog::log(gate, SLOG_FLF) << "Fail to activating monitor oid: " << oid; + return false; + } - return succeed; + // Set link status and link status message + bool set_sender_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, link_status, link_status_message, + nc_sender_monitor_link_status_property_id, + nc_sender_monitor_link_status_message_property_id, + nc_sender_monitor_link_status_transition_counter_property_id, + nmos::fields::nc::link_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); } - else + // Set link status and status message and apply status reporting delay + bool set_sender_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - // should never happen - slog::log(gate, SLOG_FLF) << "Invalid logic found in activate monitor oid: " << oid; + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, link_status, link_status_message, + nc_sender_monitor_link_status_property_id, + nc_sender_monitor_link_status_message_property_id, + nc_sender_monitor_link_status_transition_counter_property_id, + nmos::fields::nc::link_status_pending, + nmos::fields::nc::link_status_message_pending, + nmos::fields::nc::link_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); } - return false; - } - bool deactivate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto& found = find_resource(resources, utility::s2us(std::to_string(oid))); - if (resources.end() != found && is_nc_status_monitor(details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)))) + // Set transmission status and transmission status message + bool set_sender_monitor_transmission_status(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - const auto& class_id = details::parse_nc_class_id(nmos::fields::nc::class_id(found->data)); - - auto succeed = set_control_protocol_property(resources, oid, nmos::fields::nc::monitor_activation_time, web::json::value::number(0), gate); - - if (is_nc_sender_monitor(class_id)) - { - if (succeed) succeed = set_sender_monitor_transmission_status(resources, oid, nmos::nc_transmission_status::status::inactive, U("Sender deactivated"), get_control_protocol_class_descriptor, gate); - if (succeed) succeed = set_sender_monitor_essence_status(resources, oid, nmos::nc_essence_status::status::inactive, U("Sender deactivated"), get_control_protocol_class_descriptor, gate); - } - else - { - if (succeed) succeed = set_receiver_monitor_connection_status(resources, oid, nmos::nc_connection_status::status::inactive, U("Receiver deactivated"), get_control_protocol_class_descriptor, gate); - if (succeed) succeed = set_receiver_monitor_stream_status(resources, oid, nmos::nc_stream_status::status::inactive, U("Receiver deactivated"), get_control_protocol_class_descriptor, gate); - } - return succeed; + return nc::details::set_monitor_status(resources, oid, transmission_status, transmission_status_message, + nc_sender_monitor_transmission_status_property_id, + nc_sender_monitor_transmission_status_message_property_id, + nc_sender_monitor_transmission_status_transition_counter_property_id, + nmos::fields::nc::connection_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); } - else + // Set transmission status and status message and apply status reporting delay + bool set_sender_monitor_transmission_status_with_delay(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { - // should never happen - slog::log(gate, SLOG_FLF) << "Invalid logic found in deactivate monitor oid: " << oid; + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, transmission_status, transmission_status_message, + nc_sender_monitor_transmission_status_property_id, + nc_sender_monitor_transmission_status_message_property_id, + nc_sender_monitor_transmission_status_transition_counter_property_id, + nmos::fields::nc::transmission_status_pending, + nmos::fields::nc::transmission_status_message_pending, + nmos::fields::nc::transmission_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); } - return false; - } - // Set link status and link status message - bool set_sender_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, link_status, link_status_message, - nc_sender_monitor_link_status_property_id, - nc_sender_monitor_link_status_message_property_id, - nc_sender_monitor_link_status_transition_counter_property_id, - nmos::fields::nc::link_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } - // Set link status and status message and apply status reporting delay - bool set_sender_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, link_status, link_status_message, - nc_sender_monitor_link_status_property_id, - nc_sender_monitor_link_status_message_property_id, - nc_sender_monitor_link_status_transition_counter_property_id, - nmos::fields::nc::link_status_pending, - nmos::fields::nc::link_status_message_pending, - nmos::fields::nc::link_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } - - // Set transmission status and transmission status message - bool set_sender_monitor_transmission_status(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, transmission_status, transmission_status_message, - nc_sender_monitor_transmission_status_property_id, - nc_sender_monitor_transmission_status_message_property_id, - nc_sender_monitor_transmission_status_transition_counter_property_id, - nmos::fields::nc::connection_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } - // Set transmission status and status message and apply status reporting delay - bool set_sender_monitor_transmission_status_with_delay(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, transmission_status, transmission_status_message, - nc_sender_monitor_transmission_status_property_id, - nc_sender_monitor_transmission_status_message_property_id, - nc_sender_monitor_transmission_status_transition_counter_property_id, - nmos::fields::nc::transmission_status_pending, - nmos::fields::nc::transmission_status_message_pending, - nmos::fields::nc::transmission_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } + // Set external synchronization status and external synchronization status message + bool set_sender_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, external_synchronization_status, external_synchronization_status_message, + nc_sender_monitor_external_synchronization_status_property_id, + nc_sender_monitor_external_synchronization_status_message_property_id, + nc_sender_monitor_external_synchronization_status_transition_counter_property_id, + nmos::fields::nc::external_synchronization_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); + } + // Set external synchronization status and status message and apply status reporting delay + bool set_sender_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, + nc_sender_monitor_external_synchronization_status_property_id, + nc_sender_monitor_external_synchronization_status_message_property_id, + nc_sender_monitor_external_synchronization_status_transition_counter_property_id, + nmos::fields::nc::external_synchronization_status_pending, + nmos::fields::nc::external_synchronization_status_message_pending, + nmos::fields::nc::external_synchronization_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); + } - // Set external synchronization status and external synchronization status message - bool set_sender_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, external_synchronization_status, external_synchronization_status_message, - nc_sender_monitor_external_synchronization_status_property_id, - nc_sender_monitor_external_synchronization_status_message_property_id, - nc_sender_monitor_external_synchronization_status_transition_counter_property_id, - nmos::fields::nc::external_synchronization_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } - // Set external synchronization status and status message and apply status reporting delay - bool set_sender_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, external_synchronization_status, external_synchronization_status_message, - nc_sender_monitor_external_synchronization_status_property_id, - nc_sender_monitor_external_synchronization_status_message_property_id, - nc_sender_monitor_external_synchronization_status_transition_counter_property_id, - nmos::fields::nc::external_synchronization_status_pending, - nmos::fields::nc::external_synchronization_status_message_pending, - nmos::fields::nc::external_synchronization_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); + // Set essence status and stream status message + bool set_sender_monitor_essence_status(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + return nc::details::set_monitor_status(resources, oid, essence_status, essence_status_message, + nc_sender_monitor_essence_status_property_id, + nc_sender_monitor_essence_status_message_property_id, + nc_sender_monitor_essence_status_transition_counter_property_id, + nmos::fields::nc::stream_status_pending_received_time, + get_control_protocol_class_descriptor, + gate); + } + // Set essence status and status message and apply status reporting delay + bool set_sender_monitor_essence_status_with_delay(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) + { + const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); + + return nc::details::set_monitor_status_with_delay(resources, oid, essence_status, essence_status_message, + nc_sender_monitor_essence_status_property_id, + nc_sender_monitor_essence_status_message_property_id, + nc_sender_monitor_essence_status_transition_counter_property_id, + nmos::fields::nc::essence_status_pending, + nmos::fields::nc::essence_status_message_pending, + nmos::fields::nc::essence_status_pending_received_time, + now_time, + monitor_status_pending, + get_control_protocol_class_descriptor, + gate); + } } - // Set essence status and stream status message - bool set_sender_monitor_essence_status(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - return details::set_monitor_status(resources, oid, essence_status, essence_status_message, - nc_sender_monitor_essence_status_property_id, - nc_sender_monitor_essence_status_message_property_id, - nc_sender_monitor_essence_status_transition_counter_property_id, - nmos::fields::nc::stream_status_pending_received_time, - get_control_protocol_class_descriptor, - gate); - } - // Set essence status and status message and apply status reporting delay - bool set_sender_monitor_essence_status_with_delay(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) - { - const auto now_time = std::chrono::duration_cast(std::chrono::steady_clock::now().time_since_epoch()).count(); - - return details::set_monitor_status_with_delay(resources, oid, essence_status, essence_status_message, - nc_sender_monitor_essence_status_property_id, - nc_sender_monitor_essence_status_message_property_id, - nc_sender_monitor_essence_status_transition_counter_property_id, - nmos::fields::nc::essence_status_pending, - nmos::fields::nc::essence_status_message_pending, - nmos::fields::nc::essence_status_pending_received_time, - now_time, - monitor_status_pending, - get_control_protocol_class_descriptor, - gate); - } } diff --git a/Development/nmos/control_protocol_utils.h b/Development/nmos/control_protocol_utils.h index c8ecdd12e..7e11c4f2d 100644 --- a/Development/nmos/control_protocol_utils.h +++ b/Development/nmos/control_protocol_utils.h @@ -13,167 +13,262 @@ namespace nmos control_protocol_exception(const std::string& message) : std::runtime_error(message) {} }; - namespace details + namespace nc { - // get the runtime property constraints of a given property_id - web::json::value get_runtime_property_constraints(const nc_property_id& property_id, const web::json::value& runtime_property_constraints_list); + namespace details + { + // get the runtime property constraints of a given property_id + web::json::value get_runtime_property_constraints(const nc_property_id& property_id, const web::json::value& runtime_property_constraints_list); - // get the datatype descriptor of a specific type_name - web::json::value get_datatype_descriptor(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype); + // get the datatype descriptor of a specific type_name + web::json::value get_datatype_descriptor(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype); - // get the datatype property constraints of a given type_name - web::json::value get_datatype_constraints(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype); + // get the datatype property constraints of a given type_name + web::json::value get_datatype_constraints(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype); - struct datatype_constraints_validation_parameters - { - web::json::value datatype_descriptor; - get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor; - }; - // multiple levels of constraints validation, may throw nmos::control_protocol_exception - // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html - void constraints_validation(const web::json::value& value, const web::json::value& runtime_property_constraints, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params); - - // method parameter constraints validation, may throw nmos::control_protocol_exception - void method_parameter_constraints_validation(const web::json::value& data, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params); - - bool set_monitor_status(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, const nc_property_id& status_property_id, - const nc_property_id& status_message_property_id, - const nc_property_id& status_transition_counter_property_id, - const utility::string_t& status_pending_received_time_field_name, - get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, - slog::base_gate& gate); - bool set_monitor_status_with_delay(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, - const nc_property_id& status_property_id, - const nc_property_id& status_message_property_id, - const nc_property_id& status_transition_counter_property_id, - const utility::string_t& status_pending_field_name, - const utility::string_t& status_message_pending_time_field_name, - const utility::string_t& status_pending_received_time_field_name, - long long current_time, - monitor_status_pending_handler monitor_status_pending, - get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, - slog::base_gate& gate); - bool update_receiver_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - bool update_sender_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - } + struct datatype_constraints_validation_parameters + { + web::json::value datatype_descriptor; + get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor; + }; + // multiple levels of constraints validation, may throw nmos::control_protocol_exception + // See https://specs.amwa.tv/ms-05-02/branches/v1.0.x/docs/Constraints.html + void constraints_validation(const web::json::value& value, const web::json::value& runtime_property_constraints, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params); + + // method parameter constraints validation, may throw nmos::control_protocol_exception + void method_parameter_constraints_validation(const web::json::value& data, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params); + + // convert . delimited string into role path object + web::json::value parse_role_path(const utility::string_t& role_path); + + bool set_monitor_status(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, const nc_property_id& status_property_id, + const nc_property_id& status_message_property_id, + const nc_property_id& status_transition_counter_property_id, + const utility::string_t& status_pending_received_time_field_name, + get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, + slog::base_gate& gate); + bool set_monitor_status_with_delay(resources& resources, nc_oid oid, int status, const utility::string_t& status_message, + const nc_property_id& status_property_id, + const nc_property_id& status_message_property_id, + const nc_property_id& status_transition_counter_property_id, + const utility::string_t& status_pending_field_name, + const utility::string_t& status_message_pending_time_field_name, + const utility::string_t& status_pending_received_time_field_name, + long long current_time, + monitor_status_pending_handler monitor_status_pending, + get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, + slog::base_gate& gate); + bool update_receiver_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + bool update_sender_monitor_overall_status(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + } + + // is the given class_id a NcBlock + bool is_block(const nc_class_id& class_id); + + // is the given class_id a NcWorker + bool is_worker(const nc_class_id& class_id); + + // is the given class_id a NcManager + bool is_manager(const nc_class_id& class_id); + + // is the given class_id a NcDeviceManager + bool is_device_manager(const nc_class_id& class_id); + + // is the given class_id a NcClassManager + bool is_class_manager(const nc_class_id& class_id); + + // is the given class_id a NcStatusMonitor + bool is_status_monitor(const nc_class_id& class_id); + + // is the given class_id a NcSenderMonitor + bool is_sender_monitor(const nc_class_id& class_id); + + // construct NcClassId + nc_class_id make_class_id(const nc_class_id& prefix, int32_t authority_key, const std::vector& suffix); + nc_class_id make_class_id(const nc_class_id& prefix, const std::vector& suffix); // using default authority_key 0 + + // find control class property descriptor (NcPropertyDescriptor) + web::json::value find_property_descriptor(const nc_property_id& property_id, const nc_class_id& class_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor); + + // get block memeber descriptors + void get_member_descriptors(const resources& resources, const resource& resource, bool recurse, web::json::array& descriptors); + + // find members with given role name or fragment + void find_members_by_role(const resources& resources, const resource& resource, const utility::string_t& role, bool match_whole_string, bool case_sensitive, bool recurse, web::json::array& nc_block_member_descriptors); + + // find members with given class id + void find_members_by_class_id(const resources& resources, const resource& resource, const nc_class_id& class_id, bool include_derived, bool recurse, web::json::array& descriptors); + + // push control protocol resource into other control protocol NcBlock resource + void push_back(control_protocol_resource& nc_block_resource, const control_protocol_resource& resource); - // is the given class_id a NcBlock - bool is_nc_block(const nc_class_id& class_id); + // insert root block and all sub control protocol resources + void insert_root(resources& resources, control_protocol_resource& root); - // is the given class_id a NcWorker - bool is_nc_worker(const nc_class_id& class_id); + // insert a control protocol resource + std::pair insert_resource(resources& resources, resource&& resource); - // is the given class_id a NcManager - bool is_nc_manager(const nc_class_id& class_id); + // modify a control protocol resource, and insert notification event to all subscriptions + bool modify_resource(resources& resources, const id& id, std::function modifier, const web::json::value& notification_event=web::json::value::null()); - // is the given class_id a NcDeviceManager - bool is_nc_device_manager(const nc_class_id& class_id); + // erase a control protocol resource + resources::size_type erase_resource(resources& resources, const id& id); - // is the given class_id a NcClassManager - bool is_nc_class_manager(const nc_class_id& class_id); + // find the control protocol resource which is associated with the given IS-04/IS-05/IS-08 resource id + resources::const_iterator find_resource(resources& resources, type type, const id& id); - // is the given class_id a NcStatusMonitor - bool is_nc_status_monitor(const nc_class_id& class_id); + // find resource based on role path. + resources::const_iterator find_resource_by_role_path(const resources& resources, const web::json::array& role_path); - // is the given class_id a NcSenderMonitor - bool is_nc_sender_monitor(const nc_class_id& class_id); + // find resource based on role path. Roles in role path string must be delimited with a '.' + resources::const_iterator find_resource_by_role_path(const resources& resources, const utility::string_t& role_path); - // construct NcClassId - nc_class_id make_nc_class_id(const nc_class_id& prefix, int32_t authority_key, const std::vector& suffix); - nc_class_id make_nc_class_id(const nc_class_id& prefix, const std::vector& suffix); // using default authority_key 0 + // method parameters constraints validation, may throw nmos::control_protocol_exception + void method_parameters_contraints_validation(const web::json::value& arguments, const web::json::value& nc_method_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor); - // find control class property descriptor (NcPropertyDescriptor) - web::json::value find_property_descriptor(const nc_property_id& property_id, const nc_class_id& class_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor); + resources::const_iterator find_touchpoint_resource(const resources& resources, const resource& resource); - // get block member descriptors - void get_member_descriptors(const resources& resources, const resource& resource, bool recurse, web::json::array& descriptors); + // insert 'value changed', 'sequence item added', 'sequence item changed' or 'sequence item removed' notification events into all grains whose subscriptions match the specified version, type and "pre" or "post" values + void insert_notification_events(resources& resources, const api_version& version, const api_version& downgrade_version, const type& type, const web::json::value& pre, const web::json::value& post, const web::json::value& event); - // find members with given role name or fragment - void find_members_by_role(const resources& resources, const resource& resource, const utility::string_t& role, bool match_whole_string, bool case_sensitive, bool recurse, web::json::array& nc_block_member_descriptors); + // get property value given oid and property_id + web::json::value get_property(const resources& resources, nc_oid oid, const nc_property_id& property_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // find members with given class id - void find_members_by_class_id(const resources& resources, const resource& resource, const nc_class_id& class_id, bool include_derived, bool recurse, web::json::array& descriptors); + // set property value given oid and property_id and notify + bool set_property_and_notify(resources& resources, nc_oid oid, const nc_property_id& property_id, const web::json::value& value, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // push control protocol resource into other control protocol NcBlock resource - void push_back(control_protocol_resource& nc_block_resource, const control_protocol_resource& resource); + // set hidden property but don't notify, as property isn't part of class definition + bool set_property(resources& resources, nc_oid oid, const utility::string_t& property_name, const web::json::value& value, slog::base_gate& gate); - // insert a control protocol resource - std::pair insert_control_protocol_resource(resources& resources, resource&& resource); + // Set link status and link status message + bool set_receiver_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set link status and status message and apply status reporting delay + bool set_receiver_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // modify a control protocol resource, and insert notification event to all subscriptions - bool modify_control_protocol_resource(resources& resources, const id& id, std::function modifier, const web::json::value& notification_event = web::json::value::null()); + // Set connection status and connection status message + bool set_receiver_monitor_connection_status(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set connection status and status message and apply status reporting delay + bool set_receiver_monitor_connection_status_with_delay(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set external synchronization status and external synchronization status message + bool set_receiver_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set external synchronization status and status message and apply status reporting delay + bool set_receiver_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set stream status and stream status message + bool set_receiver_monitor_stream_status(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set stream status and status message and apply status reporting delay + bool set_receiver_monitor_stream_status_with_delay(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set synchronization source id + bool set_monitor_synchronization_source_id(resources& resources, nc_oid oid, const bst::optional& source_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Call when monitor is activated + bool activate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, slog::base_gate& gate); + // Call when monitor is deactivated + bool deactivate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set link status and link status message + bool set_sender_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set link status and status message and apply status reporting delay + bool set_sender_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set transmission status and transmission status message + bool set_sender_monitor_transmission_status(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set transmission status and status message and apply status reporting delay + bool set_sender_monitor_transmission_status_with_delay(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set external synchronization status and external synchronization status message + bool set_sender_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set external synchronization status and status message and apply status reporting delay + bool set_sender_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Set essence status and stream status message + bool set_sender_monitor_essence_status(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Set essence status and status message and apply status reporting delay + bool set_sender_monitor_essence_status_with_delay(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + + // Get property by name, rather than by property id. Used to get "hidden" resource properties + web::json::value get_property(const resources& resources, nc_oid oid, const utility::string_t& property_name, slog::base_gate& gate); + } + + namespace details + { + // Deprecated: use nc::details::get_runtime_property_constraints + inline web::json::value get_runtime_property_constraints(const nc_property_id& property_id, const web::json::value& runtime_property_constraints_list) { return nc::details::get_runtime_property_constraints(property_id, runtime_property_constraints_list); }; + + // Deprecated: use nc::details::get_datatype_descriptor + inline web::json::value get_datatype_descriptor(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype) { return nc::details::get_datatype_descriptor(type_name, get_control_protocol_datatype); }; + + // Deprecated: use nc::details::get_datatype_constraints + inline web::json::value get_datatype_constraints(const web::json::value& type_name, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype) { return nc::details::get_datatype_constraints(type_name, get_control_protocol_datatype); }; + + struct datatype_constraints_validation_parameters + { + web::json::value datatype_descriptor; + get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor; + }; + // Deprecated: use nc::details::constraints_validation + inline void constraints_validation(const web::json::value& value, const web::json::value& runtime_property_constraints, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) { return nc::details::constraints_validation(value, runtime_property_constraints, property_constraints, nc::details::datatype_constraints_validation_parameters{params.datatype_descriptor, params.get_control_protocol_datatype_descriptor}); }; + + // Deprecated: use nc::details::method_parameter_constraints_validation + inline void method_parameter_constraints_validation(const web::json::value& data, const web::json::value& property_constraints, const datatype_constraints_validation_parameters& params) { return nc::details::method_parameter_constraints_validation(data, property_constraints, nc::details::datatype_constraints_validation_parameters{params.datatype_descriptor, params.get_control_protocol_datatype_descriptor}); }; + } - // erase a control protocol resource - resources::size_type erase_control_protocol_resource(resources& resources, const id& id); + // Deprecated: use nc::is_block + inline bool is_nc_block(const nc_class_id& class_id) { return nc::is_block(class_id); }; - // find the control protocol resource which is associated with the given IS-04/IS-05/IS-08 resource id - resources::const_iterator find_control_protocol_resource(resources& resources, type type, const id& id); + // Deprecated: use nc::is_worker + inline bool is_nc_worker(const nc_class_id& class_id) { return nc::is_worker(class_id); }; - // method parameters constraints validation, may throw nmos::control_protocol_exception - void method_parameters_contraints_validation(const web::json::value& arguments, const web::json::value& nc_method_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor); + // Deprecated: use nc::is_manager + inline bool is_nc_manager(const nc_class_id& class_id) { return nc::is_manager(class_id); }; - // insert 'value changed', 'sequence item added', 'sequence item changed' or 'sequence item removed' notification events into all grains whose subscriptions match the specified version, type and "pre" or "post" values - void insert_notification_events(resources& resources, const api_version& version, const api_version& downgrade_version, const type& type, const web::json::value& pre, const web::json::value& post, const web::json::value& event); + // Deprecated: use nc::is_device_manager + inline bool is_nc_device_manager(const nc_class_id& class_id) { return nc::is_device_manager(class_id); }; - // get property value given oid and property_id - web::json::value get_control_protocol_property(const resources& resources, nc_oid oid, const nc_property_id& property_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::is_class_manager + inline bool is_nc_class_manager(const nc_class_id& class_id) { return nc::is_class_manager(class_id); }; - // set property value given oid and property_id and notify - bool set_control_protocol_property_and_notify(resources& resources, nc_oid oid, const nc_property_id& property_id, const web::json::value& value, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::make_class_id + inline nc_class_id make_nc_class_id(const nc_class_id& prefix, int32_t authority_key, const std::vector& suffix) { return nc::make_class_id(prefix, authority_key, suffix); }; + inline nc_class_id make_nc_class_id(const nc_class_id& prefix, const std::vector& suffix) { return nc::make_class_id(prefix, suffix); }; - // set hidden property but don't notify, as property isn't part of class definition - bool set_control_protocol_property(resources& resources, nc_oid oid, const utility::string_t& property_name, const web::json::value& value, slog::base_gate& gate); + // Deprecated: use nc::find_property_descriptor + inline web::json::value find_property_descriptor(const nc_property_id& property_id, const nc_class_id& class_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor) { return nc::find_property_descriptor(property_id, class_id, get_control_protocol_class_descriptor); }; - // Set link status and link status message - bool set_receiver_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set link status and status message and apply status reporting delay - bool set_receiver_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::get_member_descriptors + inline void get_member_descriptors(const resources& resources, const resource& resource, bool recurse, web::json::array& descriptors) { return nc::get_member_descriptors(resources, resource, recurse, descriptors); }; - // Set connection status and connection status message - bool set_receiver_monitor_connection_status(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set connection status and status message and apply status reporting delay - bool set_receiver_monitor_connection_status_with_delay(resources& resources, nc_oid oid, nmos::nc_connection_status::status connection_status, const utility::string_t& connection_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::find_members_by_role + inline void find_members_by_role(const resources& resources, const resource& resource, const utility::string_t& role, bool match_whole_string, bool case_sensitive, bool recurse, web::json::array& nc_block_member_descriptors) { return nc::find_members_by_role(resources, resource, role, match_whole_string, case_sensitive, recurse, nc_block_member_descriptors); }; - // Set external synchronization status and external synchronization status message - bool set_receiver_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set external synchronization status and status message and apply status reporting delay - bool set_receiver_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::find_members_by_class_id + inline void find_members_by_class_id(const resources& resources, const resource& resource, const nc_class_id& class_id, bool include_derived, bool recurse, web::json::array& descriptors) { return nc::find_members_by_class_id(resources, resource, class_id, include_derived, recurse, descriptors); }; - // Set stream status and stream status message - bool set_receiver_monitor_stream_status(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set stream status and status message and apply status reporting delay - bool set_receiver_monitor_stream_status_with_delay(resources& resources, nc_oid oid, nmos::nc_stream_status::status stream_status, const utility::string_t& stream_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::push_back + inline void push_back(control_protocol_resource& nc_block_resource, const control_protocol_resource& resource) { return nc::push_back(nc_block_resource, resource); }; - // Set synchronization source id - bool set_monitor_synchronization_source_id(resources& resources, nc_oid oid, const bst::optional& source_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::insert_resource + inline std::pair insert_control_protocol_resource(resources& resources, resource&& resource) { return nc::insert_resource(resources, std::move(resource)); }; - // Call when monitor is activated - bool activate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, slog::base_gate& gate); - // Call when monitor is deactivated - bool deactivate_monitor(resources& resources, nc_oid oid, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::modify_resource + inline bool modify_control_protocol_resource(resources& resources, const id& id, std::function modifier, const web::json::value& notification_event = web::json::value::null()) { return nc::modify_resource(resources, id, modifier, notification_event); }; - // Set link status and link status message - bool set_sender_monitor_link_status(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set link status and status message and apply status reporting delay - bool set_sender_monitor_link_status_with_delay(resources& resources, nc_oid oid, nmos::nc_link_status::status link_status, const utility::string_t& link_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::erase_resource + inline resources::size_type erase_control_protocol_resource(resources& resources, const id& id) { return nc::erase_resource(resources, id); }; - // Set transmission status and transmission status message - bool set_sender_monitor_transmission_status(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set transmission status and status message and apply status reporting delay - bool set_sender_monitor_transmission_status_with_delay(resources& resources, nc_oid oid, nmos::nc_transmission_status::status transmission_status, const utility::string_t& transmission_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::find_resource + inline resources::const_iterator find_control_protocol_resource(resources& resources, type type, const id& id) { return nc::find_resource(resources, type, id); }; - // Set external synchronization status and external synchronization status message - bool set_sender_monitor_external_synchronization_status(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set external synchronization status and status message and apply status reporting delay - bool set_sender_monitor_external_synchronization_status_with_delay(resources& resources, nc_oid oid, nmos::nc_synchronization_status::status external_synchronization_status, const utility::string_t& external_synchronization_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::method_parameters_contraints_validation + inline void method_parameters_contraints_validation(const web::json::value& arguments, const web::json::value& nc_method_descriptor, get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { return nc::method_parameters_contraints_validation(arguments, nc_method_descriptor, get_control_protocol_datatype_descriptor); }; - // Set essence status and stream status message - bool set_sender_monitor_essence_status(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); - // Set essence status and status message and apply status reporting delay - bool set_sender_monitor_essence_status_with_delay(resources& resources, nc_oid oid, nmos::nc_essence_status::status essence_status, const utility::string_t& essence_status_message, monitor_status_pending_handler monitor_status_pending, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate); + // Deprecated: use nc::insert_notification_events + inline void insert_notification_events(resources& resources, const api_version& version, const api_version& downgrade_version, const type& type, const web::json::value& pre, const web::json::value& post, const web::json::value& event) { return nc::insert_notification_events(resources, version, downgrade_version, type, pre, post, event); }; - // Used to get "hidden" resource properties - web::json::value get_control_protocol_property(const resources& resources, nc_oid oid, const utility::string_t& property_name, slog::base_gate& gate); + // Deprecated: use nc::get_property + inline web::json::value get_control_protocol_property(const resources& resources, nc_oid oid, const nc_property_id& property_id, get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, slog::base_gate& gate) { return nc::get_property(resources, oid, property_id, get_control_protocol_class_descriptor, gate); }; } #endif \ No newline at end of file diff --git a/Development/nmos/control_protocol_ws_api.cpp b/Development/nmos/control_protocol_ws_api.cpp index 7cace44cc..855d09026 100644 --- a/Development/nmos/control_protocol_ws_api.cpp +++ b/Development/nmos/control_protocol_ws_api.cpp @@ -246,7 +246,7 @@ namespace nmos const auto oid = nmos::fields::nc::oid(cmd); // get methodId - const auto& method_id = nmos::details::parse_nc_method_id(nmos::fields::nc::method_id(cmd)); + const auto& method_id = nc::details::parse_method_id(nmos::fields::nc::method_id(cmd)); // get arguments const auto& arguments = nmos::fields::nc::arguments(cmd); @@ -256,7 +256,7 @@ namespace nmos auto resource = nmos::find_resource(resources, utility::s2us(std::to_string(oid))); if (resources.end() != resource) { - const auto class_id = nmos::details::parse_nc_class_id(nmos::fields::nc::class_id(resource->data)); + const auto class_id = nc::details::parse_class_id(nmos::fields::nc::class_id(resource->data)); // find the relevant method handler to execute // method tuple definition described in control_protocol_handlers.h @@ -268,7 +268,7 @@ namespace nmos try { // do method arguments constraints validation - method_parameters_contraints_validation(arguments, nc_method_descriptor, get_control_protocol_datatype_descriptor); + nc::method_parameters_contraints_validation(arguments, nc_method_descriptor, get_control_protocol_datatype_descriptor); // execute the relevant control method handler, then accumulating up their response to responses // wrap the NcMethodResuls here @@ -280,7 +280,7 @@ namespace nmos utility::ostringstream_t ss; ss << "invalid argument: " << arguments.serialize() << " error: " << e.what(); slog::log(gate, SLOG_FLF) << ss.str(); - nc_method_result = details::make_nc_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); + nc_method_result = nc::details::make_method_result_error({ nmos::nc_method_status::parameter_error }, ss.str()); } } else @@ -290,7 +290,7 @@ namespace nmos ss << U("unsupported method_id: ") << nmos::fields::nc::method_id(cmd).serialize() << U(" for control class class_id: ") << resource->data.at(nmos::fields::nc::class_id).serialize(); slog::log(gate, SLOG_FLF) << ss.str(); - nc_method_result = details::make_nc_method_result_error({ nc_method_status::method_not_implemented }, ss.str()); + nc_method_result = nc::details::make_method_result_error({ nc_method_status::method_not_implemented }, ss.str()); } } else @@ -299,10 +299,10 @@ namespace nmos utility::ostringstream_t ss; ss << U("unknown oid: ") << oid; slog::log(gate, SLOG_FLF) << ss.str(); - nc_method_result = details::make_nc_method_result_error({ nc_method_status::bad_oid }, ss.str()); + nc_method_result = nc::details::make_method_result_error({ nc_method_status::bad_oid }, ss.str()); } // accumulating up response - auto response = make_control_protocol_response(handle, nc_method_result); + auto response = nc::make_response(handle, nc_method_result); web::json::push_back(responses, response); } @@ -310,7 +310,7 @@ namespace nmos // add command_response to the grain ready to transfer to the client in nmos::send_control_protocol_ws_messages_thread resources.modify(grain, [&](nmos::resource& grain) { - web::json::push_back(nmos::fields::message_grain_data(grain.data), make_control_protocol_command_response(responses)); + web::json::push_back(nmos::fields::message_grain_data(grain.data), nc::make_command_response(responses)); grain.updated = strictly_increasing_update(resources); }); @@ -347,7 +347,7 @@ namespace nmos // add subscription_response to the grain ready to transfer to the client in nmos::send_control_protocol_ws_messages_thread resources.modify(grain, [&](nmos::resource& grain) { - web::json::push_back(nmos::fields::message_grain_data(grain.data), make_control_protocol_subscription_response(valid_subscriptions)); + web::json::push_back(nmos::fields::message_grain_data(grain.data), nc::make_subscription_response(valid_subscriptions)); grain.updated = strictly_increasing_update(resources); }); @@ -369,7 +369,7 @@ namespace nmos resources.modify(grain, [&](nmos::resource& grain) { web::json::push_back(nmos::fields::message_grain_data(grain.data), - make_control_protocol_error_message({ nc_method_status::bad_command_format }, utility::s2us(e.what()))); + nc::make_error_message({ nc_method_status::bad_command_format }, utility::s2us(e.what()))); grain.updated = strictly_increasing_update(resources); }); @@ -381,7 +381,7 @@ namespace nmos resources.modify(grain, [&](nmos::resource& grain) { web::json::push_back(nmos::fields::message_grain_data(grain.data), - make_control_protocol_error_message({ nc_method_status::bad_command_format }, utility::s2us(std::string("Unexpected exception while handing control protocol command : ") + e.what()))); + nc::make_error_message({ nc_method_status::bad_command_format }, utility::s2us(std::string("Unexpected exception while handing control protocol command : ") + e.what()))); grain.updated = strictly_increasing_update(resources); }); @@ -393,7 +393,7 @@ namespace nmos resources.modify(grain, [&](nmos::resource& grain) { web::json::push_back(nmos::fields::message_grain_data(grain.data), - make_control_protocol_error_message({ nc_method_status::bad_command_format }, U("Unexpected unknown exception while handing control protocol command"))); + nc::make_error_message({ nc_method_status::bad_command_format }, U("Unexpected unknown exception while handing control protocol command"))); grain.updated = strictly_increasing_update(resources); }); diff --git a/Development/nmos/is14_schemas/is14_schemas.h b/Development/nmos/is14_schemas/is14_schemas.h new file mode 100644 index 000000000..6e4e50cb9 --- /dev/null +++ b/Development/nmos/is14_schemas/is14_schemas.h @@ -0,0 +1,35 @@ +#ifndef NMOS_IS14_SCHEMAS_H +#define NMOS_IS14_SCHEMAS_H + +// Extern declarations for auto-generated constants +// could be auto-generated, but isn't currently! +namespace nmos +{ + namespace is14_schemas + { + namespace v1_0_x + { + extern const char* base; + extern const char* bulkProperties_get_response; + extern const char* bulkProperties_put_request; + extern const char* bulkProperties_put_response; + extern const char* bulkProperties_patch_request; + extern const char* bulkProperties_patch_response; + extern const char* descriptor_get; + extern const char* method_patch_request; + extern const char* method_patch_response; + extern const char* methods_base; + extern const char* ms05_error; + extern const char* properties_base; + extern const char* property; + extern const char* property_descriptor; + extern const char* property_value_get; + extern const char* property_value_put_request; + extern const char* property_value_put_response; + extern const char* rolePath; + extern const char* rolePaths_base; + } + } +} + +#endif diff --git a/Development/nmos/is14_versions.h b/Development/nmos/is14_versions.h new file mode 100644 index 000000000..a5fc9d2c5 --- /dev/null +++ b/Development/nmos/is14_versions.h @@ -0,0 +1,26 @@ +#ifndef NMOS_IS14_VERSIONS_H +#define NMOS_IS14_VERSIONS_H + +#include +#include +#include "nmos/api_version.h" +#include "nmos/settings.h" + +namespace nmos +{ + namespace is14_versions + { + const api_version v1_0{ 1, 0 }; + + const std::set all{ nmos::is14_versions::v1_0 }; + + inline std::set from_settings(const nmos::settings& settings) + { + return settings.has_field(nmos::fields::is14_versions) + ? boost::copy_range>(nmos::fields::is14_versions(settings) | boost::adaptors::transformed([](const web::json::value& v) { return nmos::parse_api_version(v.as_string()); })) + : nmos::is14_versions::all; + } + } +} + +#endif diff --git a/Development/nmos/json_fields.h b/Development/nmos/json_fields.h index 2e2abbdeb..0ff9921db 100644 --- a/Development/nmos/json_fields.h +++ b/Development/nmos/json_fields.h @@ -269,6 +269,7 @@ namespace nmos const web::json::field_as_array touchpoints{ U("touchpoints") }; const web::json::field_as_array runtime_property_constraints{ U("runtimePropertyConstraints") }; const web::json::field_as_bool recurse{ U("recurse") }; + const web::json::field_as_bool include_descriptors{ U("includeDescriptors") }; const web::json::field_as_bool enabled{ U("enabled") }; const web::json::field_as_array members{ U("members") }; const web::json::field_as_string description{ U("description") }; @@ -304,7 +305,7 @@ namespace nmos const web::json::field_as_bool is_sequence{ U("isSequence") }; const web::json::field_as_bool is_deprecated{ U("isDeprecated") }; const web::json::field_as_bool is_constant{ U("isConstant") }; - const web::json::field_as_string parent_type{ U("parentType") }; + const web::json::field_as_value parent_type{ U("parentType") }; const web::json::field_as_string event_datatype{ U("eventDatatype") }; const web::json::field_as_string result_datatype{ U("resultDatatype") }; const web::json::field_as_array parameters{ U("parameters") }; @@ -373,6 +374,18 @@ namespace nmos const web::json::field_as_integer overall_status{ U("overallStatus") }; const web::json::field_as_value overall_status_message{ U("overallStatusMessage") }; const web::json::field_as_integer status_reporting_delay{ U("statusReportingDelay") }; + const web::json::field_as_array values{ U("values") }; + const web::json::field_as_string validation_fingerprint{ U("validationFingerprint") }; + const web::json::field_as_value status_message{ U("statusMessage") }; + const web::json::field_as_value descriptor{U("descriptor")}; + const web::json::field_as_value data_set{ U("dataSet") }; // NcBulkPropertiesHolder + const web::json::field_as_bool is_rebuildable{ U("isRebuildable") }; + const web::json::field_as_integer notice_type{ U("noticeType") }; + const web::json::field_as_string notice_message{ U("noticeMessage") }; + const web::json::field_as_array notices{ U("notices") }; + const web::json::field_as_integer restore_mode{ U("restoreMode") }; + const web::json::field_as_array dependency_paths{ U("dependencyPaths") }; + const web::json::field_as_array allowed_members_classes{ U("allowedMembersClasses") }; } // NMOS Parameter Registers diff --git a/Development/nmos/json_schema.cpp b/Development/nmos/json_schema.cpp index d24f2a5df..3860509ca 100644 --- a/Development/nmos/json_schema.cpp +++ b/Development/nmos/json_schema.cpp @@ -12,6 +12,8 @@ #include "nmos/is10_schemas/is10_schemas.h" #include "nmos/is12_versions.h" #include "nmos/is12_schemas/is12_schemas.h" +#include "nmos/is14_versions.h" +#include "nmos/is14_schemas/is14_schemas.h" #include "nmos/type.h" namespace nmos @@ -170,6 +172,26 @@ namespace nmos const web::uri controlprotocolapi_subscription_message_schema_uri = make_schema_uri(tag, _XPLATSTR("subscription-message.json")); } } + + namespace is14_schemas + { + web::uri make_schema_uri(const utility::string_t& tag, const utility::string_t& ref = {}) + { + return{ _XPLATSTR("https://github.com/AMWA-TV/is-14/raw/") + tag + _XPLATSTR("/APIs/schemas/") + ref }; + } + + // See https://github.com/AMWA-TV/is-14/tree/v1.0-dev/APIs/schemas/ + namespace v1_0 + { + using namespace nmos::is14_schemas::v1_0_x; + const utility::string_t tag(_XPLATSTR("v1.0.x")); + + const web::uri configurationapi_bulkProperties_put_request_schema_uri = make_schema_uri(tag, _XPLATSTR("bulkProperties-put-request.json")); + const web::uri configurationapi_bulkProperties_patch_request_schema_uri = make_schema_uri(tag, _XPLATSTR("bulkProperties-patch-request.json")); + const web::uri configurationapi_method_patch_request_schema_uri = make_schema_uri(tag, _XPLATSTR("method-patch-request.json")); + const web::uri configurationapi_property_value_put_request_schema_uri = make_schema_uri(tag, _XPLATSTR("property-value-put-request.json")); + } + } } namespace nmos @@ -391,6 +413,20 @@ namespace nmos }; } + static std::map make_is14_schemas() + { + using namespace nmos::is14_schemas; + + return + { + // v1.0 + { make_schema_uri(v1_0::tag, _XPLATSTR("bulkProperties-put-request.json")), make_schema(v1_0::bulkProperties_put_request) }, + { make_schema_uri(v1_0::tag, _XPLATSTR("bulkProperties-patch-request.json")), make_schema(v1_0::bulkProperties_patch_request) }, + { make_schema_uri(v1_0::tag, _XPLATSTR("method-patch-request.json")), make_schema(v1_0::method_patch_request) }, + { make_schema_uri(v1_0::tag, _XPLATSTR("property-value-put-request.json")), make_schema(v1_0::property_value_put_request) } + }; + } + inline void merge(std::map& to, std::map&& from) { to.insert(from.begin(), from.end()); // std::map::merge in C++17 @@ -404,6 +440,7 @@ namespace nmos merge(result, make_is09_schemas()); merge(result, make_is10_schemas()); merge(result, make_is12_schemas()); + merge(result, make_is14_schemas()); return result; } @@ -510,6 +547,26 @@ namespace nmos return is12_schemas::v1_0::controlprotocolapi_subscription_message_schema_uri; } + web::uri make_configurationapi_bulkProperties_put_request_schema_uri(const nmos::api_version& version) + { + return is14_schemas::v1_0::configurationapi_bulkProperties_put_request_schema_uri; + } + + web::uri make_configurationapi_bulkProperties_patch_request_schema_uri(const nmos::api_version& version) + { + return is14_schemas::v1_0::configurationapi_bulkProperties_patch_request_schema_uri; + } + + web::uri make_configurationapi_method_patch_request_schema_uri(const nmos::api_version& version) + { + return is14_schemas::v1_0::configurationapi_method_patch_request_schema_uri; + } + + web::uri make_configurationapi_property_value_put_request_schema_uri(const nmos::api_version& version) + { + return is14_schemas::v1_0::configurationapi_property_value_put_request_schema_uri; + } + // load the json schema for the specified base URI web::json::value load_json_schema(const web::uri& id) { diff --git a/Development/nmos/json_schema.h b/Development/nmos/json_schema.h index 57cb0996b..28d6ea861 100644 --- a/Development/nmos/json_schema.h +++ b/Development/nmos/json_schema.h @@ -40,6 +40,11 @@ namespace nmos web::uri make_controlprotocolapi_command_message_schema_uri(const nmos::api_version& version); web::uri make_controlprotocolapi_subscription_message_schema_uri(const nmos::api_version& version); + web::uri make_configurationapi_bulkProperties_put_request_schema_uri(const nmos::api_version& version); + web::uri make_configurationapi_bulkProperties_patch_request_schema_uri(const nmos::api_version& version); + web::uri make_configurationapi_method_patch_request_schema_uri(const nmos::api_version& version); + web::uri make_configurationapi_property_value_put_request_schema_uri(const nmos::api_version& version); + // load the json schema for the specified base URI web::json::value load_json_schema(const web::uri& id); } diff --git a/Development/nmos/node_resources.cpp b/Development/nmos/node_resources.cpp index 534b6b2b8..a97bffc82 100644 --- a/Development/nmos/node_resources.cpp +++ b/Development/nmos/node_resources.cpp @@ -17,6 +17,7 @@ #include "nmos/is07_versions.h" #include "nmos/is08_versions.h" #include "nmos/is12_versions.h" +#include "nmos/is14_versions.h" #include "nmos/media_type.h" #include "nmos/resource.h" #include "nmos/sdp_utils.h" // for nmos::make_components @@ -152,6 +153,27 @@ namespace nmos } } + if (0 <= nmos::fields::configuration_port(settings)) + { + for (const auto& version : nmos::is14_versions::from_settings(settings)) + { + auto configuration_uri = web::uri_builder() + .set_scheme(nmos::http_scheme(settings)) + .set_port(nmos::fields::connection_port(settings)) + .set_path(U("/x-nmos/configuration/") + make_api_version(version)); + auto type = U("urn:x-nmos:control:configuration/") + make_api_version(version); + + for (const auto& host : hosts) + { + web::json::push_back(data[U("controls")], value_of({ + { U("href"), configuration_uri.set_host(host).to_uri().to_string() }, + { U("type"), type }, + { U("authorization"), nmos::experimental::fields::server_authorization(settings) } + })); + } + } + } + return{ is04_versions::v1_3, types::device, std::move(data), false }; } diff --git a/Development/nmos/node_server.cpp b/Development/nmos/node_server.cpp index aa7638523..ba0586f41 100644 --- a/Development/nmos/node_server.cpp +++ b/Development/nmos/node_server.cpp @@ -3,6 +3,7 @@ #include "cpprest/ws_utils.h" #include "nmos/api_utils.h" #include "nmos/channelmapping_activation.h" +#include "nmos/configuration_api.h" #include "nmos/control_protocol_ws_api.h" #include "nmos/events_api.h" #include "nmos/events_ws_api.h" @@ -22,7 +23,7 @@ namespace nmos namespace experimental { // Construct a server instance for an NMOS Node, implementing the IS-04 Node API, IS-05 Connection API, IS-07 Events API, IS-08 Audio Channel Mapping API, IS-10 Authorization API, - // IS-12 Control & Monitoring Protocol Websocket API and the experimental Logging API and Settings API, according to the specified data models and callbacks + // IS-12 Control & Monitoring Protocol Websocket API, IS-14 Configuration API and the experimental Logging API and Settings API, according to the specified data models and callbacks nmos::server make_node_server(nmos::node_model& node_model, nmos::experimental::node_implementation node_implementation, nmos::experimental::log_model& log_model, slog::base_gate& gate) { // Log the API addresses we'll be using @@ -74,6 +75,10 @@ namespace nmos node_server.api_routers[{ {}, nmos::fields::channelmapping_port(node_model.settings) }].mount({}, nmos::make_channelmapping_api(node_model, node_implementation.validate_map, validate_authorization ? validate_authorization(nmos::experimental::scopes::channelmapping) : nullptr, gate)); + // Configure the Configuration API + + node_server.api_routers[{ {}, nmos::fields::configuration_port(node_model.settings) }].mount({}, nmos::make_configuration_api(node_model, validate_authorization ? validate_authorization(nmos::experimental::scopes::configuration) : nullptr, node_implementation.get_control_protocol_class_descriptor, node_implementation.get_control_protocol_datatype_descriptor, node_implementation.get_control_protocol_method_descriptor, node_implementation.create_validation_fingerprint, node_implementation.validate_validation_fingerprint, node_implementation.get_read_only_modification_allow_list, node_implementation.remove_device_model_object, node_implementation.create_device_model_object, node_implementation.control_protocol_property_changed, gate)); + const auto& events_ws_port = nmos::fields::events_ws_port(node_model.settings); auto& events_ws_api = node_server.ws_handlers[{ {}, nmos::fields::events_ws_port(node_model.settings) }]; events_ws_api.first = nmos::make_events_ws_api(node_model, events_ws_api.second, node_implementation.ws_validate_authorization, gate); diff --git a/Development/nmos/node_server.h b/Development/nmos/node_server.h index 88dffdec9..84597a3f8 100644 --- a/Development/nmos/node_server.h +++ b/Development/nmos/node_server.h @@ -7,6 +7,7 @@ #include "nmos/channelmapping_activation.h" #include "nmos/connection_api.h" #include "nmos/connection_activation.h" +#include "nmos/configuration_handlers.h" #include "nmos/control_protocol_handlers.h" #include "nmos/node_behaviour.h" #include "nmos/node_system_behaviour.h" @@ -27,7 +28,7 @@ namespace nmos // underlying implementation into the server instance for the NMOS Node struct node_implementation { - node_implementation(nmos::load_server_certificates_handler load_server_certificates, nmos::load_dh_param_handler load_dh_param, nmos::load_ca_certificates_handler load_ca_certificates, nmos::system_global_handler system_changed, nmos::registration_handler registration_changed, nmos::transport_file_parser parse_transport_file, nmos::details::connection_resource_patch_validator validate_staged, nmos::connection_resource_auto_resolver resolve_auto, nmos::connection_sender_transportfile_setter set_transportfile, nmos::connection_activation_handler connection_activated, nmos::ocsp_response_handler get_ocsp_response, get_authorization_bearer_token_handler get_authorization_bearer_token, validate_authorization_handler validate_authorization, ws_validate_authorization_handler ws_validate_authorization, nmos::load_rsa_private_keys_handler load_rsa_private_keys, load_authorization_clients_handler load_authorization_clients, save_authorization_client_handler save_authorization_client, request_authorization_code_handler request_authorization_code, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, nmos::control_protocol_property_changed_handler control_protocol_property_changed, nmos::control_protocol_connection_activation_handler monitor_connection_activated, nmos::get_packet_counters_handler get_lost_packet_counters, nmos::get_packet_counters_handler get_late_packet_counters, nmos::reset_monitor_handler reset_monitor) + node_implementation(nmos::load_server_certificates_handler load_server_certificates, nmos::load_dh_param_handler load_dh_param, nmos::load_ca_certificates_handler load_ca_certificates, nmos::system_global_handler system_changed, nmos::registration_handler registration_changed, nmos::transport_file_parser parse_transport_file, nmos::details::connection_resource_patch_validator validate_staged, nmos::connection_resource_auto_resolver resolve_auto, nmos::connection_sender_transportfile_setter set_transportfile, nmos::connection_activation_handler connection_activated, nmos::ocsp_response_handler get_ocsp_response, get_authorization_bearer_token_handler get_authorization_bearer_token, validate_authorization_handler validate_authorization, ws_validate_authorization_handler ws_validate_authorization, nmos::load_rsa_private_keys_handler load_rsa_private_keys, load_authorization_clients_handler load_authorization_clients, save_authorization_client_handler save_authorization_client, request_authorization_code_handler request_authorization_code, nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor, nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor, nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor, nmos::control_protocol_property_changed_handler control_protocol_property_changed, nmos::create_validation_fingerprint_handler create_validation_fingerprint, nmos::validate_validation_fingerprint_handler validate_validation_fingerprint, nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list, remove_device_model_object_handler remove_device_model_object, create_device_model_object_handler create_device_model_object,nmos::control_protocol_connection_activation_handler monitor_connection_activated, nmos::get_packet_counters_handler get_lost_packet_counters, nmos::get_packet_counters_handler get_late_packet_counters, nmos::reset_monitor_handler reset_monitor) : load_server_certificates(std::move(load_server_certificates)) , load_dh_param(std::move(load_dh_param)) , load_ca_certificates(std::move(load_ca_certificates)) @@ -50,6 +51,11 @@ namespace nmos , get_control_protocol_datatype_descriptor(std::move(get_control_protocol_datatype_descriptor)) , get_control_protocol_method_descriptor(std::move(get_control_protocol_method_descriptor)) , control_protocol_property_changed(std::move(control_protocol_property_changed)) + , create_validation_fingerprint(std::move(create_validation_fingerprint)) + , validate_validation_fingerprint(std::move(validate_validation_fingerprint)) + , get_read_only_modification_allow_list(std::move(get_read_only_modification_allow_list)) + , remove_device_model_object(std::move(remove_device_model_object)) + , create_device_model_object(std::move(create_device_model_object)) , monitor_connection_activated(std::move(monitor_connection_activated)) , get_lost_packet_counters(std::move(get_lost_packet_counters)) , get_late_packet_counters(std::move(get_late_packet_counters)) @@ -86,6 +92,11 @@ namespace nmos node_implementation& on_get_control_datatype_descriptor(nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor) { this->get_control_protocol_datatype_descriptor = std::move(get_control_protocol_datatype_descriptor); return *this; } node_implementation& on_get_control_protocol_method_descriptor(nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor) { this->get_control_protocol_method_descriptor = std::move(get_control_protocol_method_descriptor); return *this; } node_implementation& on_control_protocol_property_changed(nmos::control_protocol_property_changed_handler control_protocol_property_changed) { this->control_protocol_property_changed = std::move(control_protocol_property_changed); return *this; } + node_implementation& on_create_validation_fingerprint(nmos::create_validation_fingerprint_handler create_validation_fingerprint) { this->create_validation_fingerprint = std::move(create_validation_fingerprint); return *this; } + node_implementation& on_validate_validation_fingerprint(nmos::validate_validation_fingerprint_handler validate_validation_fingerprint) { this->validate_validation_fingerprint = std::move(validate_validation_fingerprint); return *this; } + node_implementation& on_get_read_only_modification_allow_list(nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list) { this->get_read_only_modification_allow_list = std::move(get_read_only_modification_allow_list); return *this; } + node_implementation& on_remove_device_model_object(nmos::remove_device_model_object_handler remove_device_model_object) { this->remove_device_model_object = std::move(remove_device_model_object); return *this; } + node_implementation& on_create_device_model_object(nmos::create_device_model_object_handler create_device_model_object) { this->create_device_model_object = std::move(create_device_model_object); return *this; } node_implementation& on_monitor_activated(nmos::control_protocol_connection_activation_handler monitor_connection_activated) { this->monitor_connection_activated = std::move(monitor_connection_activated); return *this; } node_implementation& on_get_lost_packet_counters(nmos::get_packet_counters_handler get_lost_packet_counters) { this->get_lost_packet_counters = std::move(get_lost_packet_counters); return *this; } node_implementation& on_get_late_packet_counters(nmos::get_packet_counters_handler get_late_packet_counters) { this->get_late_packet_counters = std::move(get_late_packet_counters); return *this; } @@ -132,6 +143,15 @@ namespace nmos nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor; nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor; nmos::control_protocol_property_changed_handler control_protocol_property_changed; + + // Device Configuration handlers + nmos::create_validation_fingerprint_handler create_validation_fingerprint; + nmos::validate_validation_fingerprint_handler validate_validation_fingerprint; + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list; + nmos::remove_device_model_object_handler remove_device_model_object; + nmos::create_device_model_object_handler create_device_model_object; + + // Status Monitoring handlers nmos::control_protocol_connection_activation_handler monitor_connection_activated; nmos::get_packet_counters_handler get_lost_packet_counters; nmos::get_packet_counters_handler get_late_packet_counters; diff --git a/Development/nmos/scope.h b/Development/nmos/scope.h index 25d65004e..ee623e55f 100644 --- a/Development/nmos/scope.h +++ b/Development/nmos/scope.h @@ -26,6 +26,8 @@ namespace nmos const scope channelmapping{ U("channelmapping") }; // IS-12 const scope ncp{ U("ncp") }; + // IS-14 + const scope configuration{ U("configuration") }; } inline utility::string_t make_scope(const scope& scope) @@ -43,6 +45,7 @@ namespace nmos if (scopes::events.name == scope) { return scopes::events; } if (scopes::channelmapping.name == scope) { return scopes::channelmapping; } if (scopes::ncp.name == scope) { return scopes::ncp; } + if (scopes::configuration.name == scope) { return scopes::configuration; } return{}; } } diff --git a/Development/nmos/settings.cpp b/Development/nmos/settings.cpp index 5608fbcac..94251cb4d 100644 --- a/Development/nmos/settings.cpp +++ b/Development/nmos/settings.cpp @@ -86,6 +86,7 @@ namespace nmos web::json::insert(settings, std::make_pair(nmos::experimental::fields::authorization_redirect_port, http_port)); web::json::insert(settings, std::make_pair(nmos::experimental::fields::jwks_uri_port, http_port)); if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::control_protocol_ws_port, ncp_ws_port)); + if (!registry) web::json::insert(settings, std::make_pair(nmos::fields::configuration_port, http_port)); } } } diff --git a/Development/nmos/settings.h b/Development/nmos/settings.h index c0981f8bf..4f1a09328 100644 --- a/Development/nmos/settings.h +++ b/Development/nmos/settings.h @@ -107,6 +107,9 @@ namespace nmos // is12_versions [node]: used to specify the enabled API versions for a version-locked configuration const web::json::field_as_array is12_versions{ U("is12_versions") }; // when omitted, nmos::is12_versions::all is used + // is14_versions [node]: used to specify the enabled API versions for a version-locked configuration + const web::json::field_as_array is14_versions{ U("is14_versions") }; // when omitted, nmos::is14_versions::all is used + // pri [registry, node]: used for the 'pri' TXT record; specifying nmos::service_priorities::no_priority (maximum value) disables advertisement completely const web::json::field_as_integer_or pri{ U("pri"), 100 }; // default to highest_development_priority @@ -151,6 +154,7 @@ namespace nmos const web::json::field_as_integer_or system_port{ U("system_port"), 10641 }; // control_protocol_ws_port [node]: used to construct request URLs for the Control Protocol websocket, or negative to disable the control protocol features const web::json::field_as_integer_or control_protocol_ws_port{ U("control_protocol_ws_port"), 3218 }; + const web::json::field_as_integer_or configuration_port{ U("configuration_port"), 3219 }; // listen_backlog [registry, node]: the maximum length of the queue of pending connections, or zero for the implementation default (the implementation may not honour this value) const web::json::field_as_integer_or listen_backlog{ U("listen_backlog"), 0 }; diff --git a/Development/nmos/test/configuration_methods_test.cpp b/Development/nmos/test/configuration_methods_test.cpp new file mode 100644 index 000000000..f360777bb --- /dev/null +++ b/Development/nmos/test/configuration_methods_test.cpp @@ -0,0 +1,108 @@ +// The first "test" is of course whether the header compiles standalone +#include "nmos/control_protocol_resource.h" +#include "nmos/control_protocol_resources.h" +#include "nmos/control_protocol_state.h" +#include "nmos/control_protocol_typedefs.h" +#include "nmos/control_protocol_utils.h" +#include "nmos/configuration_handlers.h" +#include "nmos/configuration_resources.h" +#include "nmos/configuration_methods.h" +#include "nmos/configuration_utils.h" + +#include "bst/test/test.h" + + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testGetPropertiesByPath) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor = nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); + + bool create_validation_fingerprint_called = false; + // callback stubs + nmos::create_validation_fingerprint_handler create_validation_fingerprint = [&](const nmos::resources& resources, const nmos::resource& resource) + { + create_validation_fingerprint_called = true; + return U("test fingerprint"); + }; + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({{nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})}})); + // make monitor1 rebuildable + nmos::make_rebuildable(monitor1); + + auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + { + create_validation_fingerprint_called = false; + const auto target_role_path = value_of({ U("root") }); + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + auto method_result = get_properties_by_path(resources, *resource, true, true, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint); + + BST_REQUIRE_EQUAL(nmos::nc_method_status::ok, nmos::fields::nc::status(method_result)); + + const auto& bulk_properties_holder = nmos::fields::nc::value(method_result); + const auto& object_properties_holders = nmos::fields::nc::values(bulk_properties_holder); + + BST_REQUIRE_EQUAL(5, object_properties_holders.size()); + + BST_CHECK(create_validation_fingerprint_called); + } + { + create_validation_fingerprint_called = false; + const auto target_role_path = value_of({ U("root"), U("receivers") }); + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + auto method_result = get_properties_by_path(resources, *resource, true, true, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint); + + BST_REQUIRE_EQUAL(nmos::nc_method_status::ok, nmos::fields::nc::status(method_result)); + + const auto& bulk_properties_holder = nmos::fields::nc::value(method_result); + const auto& object_properties_holders = nmos::fields::nc::values(bulk_properties_holder); + + BST_REQUIRE_EQUAL(3, object_properties_holders.size()); + + BST_CHECK(create_validation_fingerprint_called); + } + { + create_validation_fingerprint_called = false; + const auto target_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + auto method_result = get_properties_by_path(resources, *resource, true, true, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, create_validation_fingerprint); + + BST_REQUIRE_EQUAL(nmos::nc_method_status::ok, nmos::fields::nc::status(method_result)); + + const auto& bulk_properties_holder = nmos::fields::nc::value(method_result); + const auto& object_properties_holders = nmos::fields::nc::values(bulk_properties_holder); + + BST_REQUIRE_EQUAL(1, object_properties_holders.size()); + + BST_CHECK(create_validation_fingerprint_called); + } +} diff --git a/Development/nmos/test/configuration_resources_test.cpp b/Development/nmos/test/configuration_resources_test.cpp new file mode 100644 index 000000000..b1950b209 --- /dev/null +++ b/Development/nmos/test/configuration_resources_test.cpp @@ -0,0 +1,70 @@ +// The first "test" is of course whether the header compiles standalone +#include "nmos/control_protocol_typedefs.h" +#include "nmos/configuration_resources.h" + +#include "bst/test/test.h" + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testMakeObjectPropertiesSetValidation) +{ + using web::json::value_of; + using web::json::value; + + auto role_path = web::json::value_of({ U("root"), U("path1") }).as_array(); + auto status = nmos::nc_restore_validation_status::ok; + auto notices = value::array().as_array(); + auto status_message = U("status message"); + + { + auto object_properties_set_validation = nmos::make_object_properties_set_validation(role_path, status, notices, status_message); + + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::path)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::notices)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status_message)); + + BST_CHECK_EQUAL(role_path, nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(status, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(notices, nmos::fields::nc::notices(object_properties_set_validation)); + BST_CHECK_EQUAL(value::string(status_message), nmos::fields::nc::status_message(object_properties_set_validation)); + } + { + auto object_properties_set_validation = nmos::make_object_properties_set_validation(role_path, status, notices); + + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::path)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::notices)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status_message)); + + BST_CHECK_EQUAL(role_path, nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(status, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(notices, nmos::fields::nc::notices(object_properties_set_validation)); + BST_CHECK_EQUAL(web::json::value::null(), nmos::fields::nc::status_message(object_properties_set_validation)); + } + { + auto object_properties_set_validation = nmos::make_object_properties_set_validation(role_path, status); + + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::path)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::notices)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status_message)); + + BST_CHECK_EQUAL(role_path, nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(status, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(web::json::value::array().as_array(), nmos::fields::nc::notices(object_properties_set_validation)); + BST_CHECK_EQUAL(web::json::value::null(), nmos::fields::nc::status_message(object_properties_set_validation)); + } + { + auto object_properties_set_validation = nmos::make_object_properties_set_validation(role_path, status, status_message); + + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::path)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::notices)); + BST_REQUIRE(object_properties_set_validation.has_field(nmos::fields::nc::status_message)); + + BST_CHECK_EQUAL(role_path, nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(status, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(web::json::value::array().as_array(), nmos::fields::nc::notices(object_properties_set_validation)); + BST_CHECK_EQUAL(value::string(status_message), nmos::fields::nc::status_message(object_properties_set_validation)); + } +} diff --git a/Development/nmos/test/configuration_utils_test.cpp b/Development/nmos/test/configuration_utils_test.cpp new file mode 100644 index 000000000..55474e1ee --- /dev/null +++ b/Development/nmos/test/configuration_utils_test.cpp @@ -0,0 +1,1682 @@ +// The first "test" is of course whether the header compiles standalone +#include "nmos/control_protocol_resource.h" +#include "nmos/control_protocol_resources.h" +#include "nmos/control_protocol_state.h" +#include "nmos/control_protocol_typedefs.h" +#include "nmos/control_protocol_utils.h" +#include "nmos/configuration_handlers.h" +#include "nmos/configuration_resources.h" +#include "nmos/configuration_utils.h" +#include "nmos/is12_versions.h" + +#include "bst/test/test.h" + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testIsRolePathRoot) +{ + { + auto role_path = web::json::value_of({ U("root"), U("path1") }).as_array(); + auto role_path_root = web::json::value_of({ U("root"), U("path1") }).as_array(); + + BST_REQUIRE(nmos::is_role_path_root(role_path_root, role_path)); + } + { + auto role_path = web::json::value_of({ U("root"), U("path1"), U("path2"), U("path3")}).as_array(); + auto role_path_root = web::json::value_of({ U("root"), U("path1"), U("path2") }).as_array(); + + BST_REQUIRE(nmos::is_role_path_root(role_path_root, role_path)); + } + { + auto role_path = web::json::value_of({ U("root"), U("path1") }).as_array(); + auto role_path_root = web::json::value_of({ U("root"), U("path1"), U("path2") }).as_array(); + + BST_REQUIRE(!nmos::is_role_path_root(role_path_root, role_path)); + } + { + auto role_path = web::json::value_of({ U("root"), U("path3"), U("path4") }).as_array(); + auto role_path_root = web::json::value_of({ U("root"), U("path1"), U("path2") }).as_array(); + + BST_REQUIRE(!nmos::is_role_path_root(role_path_root, role_path)); + } + { + auto role_path = web::json::value_of({ U("path3"), U("path4") }).as_array(); + auto role_path_root = web::json::value_of({ U("root"), U("path1"), U("path2") }).as_array(); + + BST_REQUIRE(!nmos::is_role_path_root(role_path_root, role_path)); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testIsBlockModified) +{ + using web::json::value_of; + using web::json::value; + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, receivers + auto receivers = nmos::make_block(++oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + auto receiver_block_oid = oid; + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})} })); + auto monitor_1_oid = oid; + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + auto monitor_2_oid = oid; + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + + // Create Object Properties Holder + auto role_path = value::array(); + push_back(role_path, U("root")); + push_back(role_path, U("receivers")); + + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + + // Members unchanged + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, class_id, U("monitor 1"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, class_id, U("monitor 2"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(!nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed number of members + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + const auto block_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("monitor 1"), monitor_1_oid, true, class_id, U("label"), receiver_block_oid); + push_back(members, block_descriptor); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed oids + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), 10, true, class_id, U("monitor 1"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), 20, true, class_id, U("monitor 2"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed roles + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon3"), monitor_1_oid, true, class_id, U("monitor 1"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon4"), monitor_2_oid, true, class_id, U("monitor 2"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed class id + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 1 }); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, class_id, U("monitor 1"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, class_id, U("monitor 2"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed owner oid + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 1 }); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, class_id, U("monitor 1"), 20); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, class_id, U("monitor 2"), 20); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } + + // Changed constant oid + { + auto property_holders = value::array(); + + auto members = value::array(); + const auto class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, 0, { 1 }); + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, false, class_id, U("monitor 1"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + { + const auto block_member_descriptor = nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, false, class_id, U("monitor 2"), receiver_block_oid); + push_back(members, block_member_descriptor); + } + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members); + web::json::push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + + BST_CHECK(nmos::is_block_modified(receivers, object_properties_holder)); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testGetObjectPropertiesHolder) +{ + using web::json::value_of; + using web::json::value; + + const auto enabled_property_descriptor = nmos::nc::details::make_property_descriptor(U("enabled"), nmos::nc_worker_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), false, false, false, false, web::json::value::null()); + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + + { + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + } + { + const auto role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + } + { + const auto role_path = value_of({ U("root"), U("senders"), U("mon1") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + } + + { + const auto target_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + web::json::array object_property_holder = nmos::get_object_properties_holder(object_properties_holders.as_array(), target_role_path.as_array()); + BST_REQUIRE_EQUAL(1, object_property_holder.size()); + BST_CHECK_EQUAL(target_role_path.as_array(), nmos::fields::nc::path(*object_property_holder.begin())); + } + { + const auto target_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + web::json::array object_property_holder = nmos::get_object_properties_holder(object_properties_holders.as_array(), target_role_path.as_array()); + BST_REQUIRE_EQUAL(1, object_property_holder.size()); + BST_CHECK_EQUAL(target_role_path.as_array(), nmos::fields::nc::path(*object_property_holder.begin())); + } + { + const auto target_role_path = value_of({ U("root"), U("receivers") }); + web::json::array object_property_holder = nmos::get_object_properties_holder(object_properties_holders.as_array(), target_role_path.as_array()); + BST_REQUIRE_EQUAL(0, object_property_holder.size()); + } + { + const auto target_role_path = value_of({ U("root"), U("does_not_exist") }); + web::json::array object_property_holder = nmos::get_object_properties_holder(object_properties_holders.as_array(), target_role_path.as_array()); + BST_REQUIRE_EQUAL(0, object_property_holder.size()); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testGetRolePath) +{ + // Create Fake Device Model + using web::json::value_of; + using web::json::value; + + nmos::experimental::control_protocol_state control_protocol_state; + nmos::resources resources; + + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + nmos::nc_oid receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})} })); + nmos::nc_class_id monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + auto expected_role_paths = value::array(); + push_back(expected_role_paths, value_of({ U("root") })); + push_back(expected_role_paths, value_of({ U("root"), U("ClassManager")})); + push_back(expected_role_paths, value_of({ U("root"), U("receivers") })); + push_back(expected_role_paths, value_of({ U("root"), U("receivers"), U("mon1") })); + push_back(expected_role_paths, value_of({ U("root"), U("receivers"), U("mon2") })); + + for (const auto& expected_role_path : expected_role_paths.as_array()) + { + const auto& resource = nmos::nc::find_resource_by_role_path(resources, expected_role_path.as_array()); + const auto actual_role_path = nmos::get_role_path(resources, *resource); + BST_CHECK_EQUAL(expected_role_path.as_array(), actual_role_path); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testApplyBackupDataSet) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor= nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({{nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})}})); + // make monitor1 rebuildable + nmos::make_rebuildable(monitor1); + + auto monitor_1_oid = oid; + auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + auto monitor_2_oid = oid; + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + bool get_read_only_modification_allow_list_called = false; + bool remove_device_model_object_called = false; + bool create_device_model_object_called = false; + + // callback stubs + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list = [&](const nmos::resources& resources, const nmos::resource& resource, const std::vector& target_role_path, const std::vector& property_ids) + { + get_read_only_modification_allow_list_called = true; + return property_ids; + }; + + nmos::remove_device_model_object_handler remove_device_model_object = [&](const nmos::resource& resource, const std::vector& target_role_path, bool validate) + { + remove_device_model_object_called = true; + + return true; + }; + + nmos::create_device_model_object_handler create_device_model_object = [&](const nmos::nc_class_id& class_id, nmos::nc_oid oid, bool constant_oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const web::json::value& touchpoints, bool validate, const std::map& property_values) + { + using web::json::value; + + create_device_model_object_called = true; + + auto data = nmos::nc::details::make_object(nmos::nc_receiver_monitor_class_id, oid, true, owner, role, web::json::value::string(user_label), U(""), web::json::value::null(), web::json::value::null()); + + return nmos::control_protocol_resource({ nmos::is12_versions::v1_0, nmos::types::nc_block, std::move(data), true }); + }; + + const auto enabled_property_descriptor = nmos::nc::details::make_property_descriptor(U("enabled"), nmos::nc_worker_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), false, false, false, false, web::json::value::null()); + const auto class_id_property_descriptor = nmos::nc::details::make_property_descriptor(U("classId"), nmos::nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, web::json::value::null()); + { + // Check the successful modification of the "enabled" flag of mon1's worker base class in Modify mode + // + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + const auto target_role_path = value_of({ U("root"), U("receivers")}); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::modify; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + auto object_properties_set_validation = output.as_array().at(0); + + BST_CHECK_EQUAL(role_path.as_array(), nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + + // not expecting callbacks to be invoked as no read only properties, or rebuildable blocks modified + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + const auto connection_status_property_descriptor = nmos::nc::details::make_property_descriptor(U("connectionStatusMessage"), nmos::nc_receiver_monitor_connection_status_message_property_id, nmos::fields::nc::connection_status_message, U("NcString"), true, false, false, false, web::json::value::null()); + { + // Check get_read_only_modification_allow_list_handler is called when changing a read only property of rebuildable object in Rebuild mode + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + // This is a read only property + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_receiver_monitor_connection_status_message_property_id, connection_status_property_descriptor, value(U("change this value"))); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + // must be a more efficient way of initializing these role paths + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + bool validate = true; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + + const auto object_properties_set_validation = output.as_array().at(0); + + // make sure the validation status propagates from the callback + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + + // expecting callback to get_read_only_modification_allow_list_called + // but not to modify_rebuildable_block_called + BST_CHECK(get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + { + // Check error generated when attempting to change a read only property of non-rebuidable object in Rebuild mode + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + auto property_holders = value::array(); + // This is a read only property + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_receiver_monitor_connection_status_message_property_id, connection_status_property_descriptor, value(U("change this value"))); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + // must be a more efficient way of initializing these role paths + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + bool validate = true; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + + const auto object_properties_set_validation = output.as_array().at(0); + + // make sure the validation status propagates from the callback + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + + const auto& property_restore_notices = nmos::fields::nc::notices(object_properties_set_validation); + // expectation a single notice for the read only property that couldn't be changed + BST_REQUIRE_EQUAL(1, property_restore_notices.size()); + + const auto& notice = *property_restore_notices.begin(); + BST_CHECK_EQUAL(nmos::nc_receiver_monitor_connection_status_message_property_id, nmos::nc::details::parse_property_id(nmos::fields::nc::id(notice))); + BST_CHECK_EQUAL(nmos::fields::nc::connection_status_message.key, nmos::fields::nc::name(notice)); + BST_CHECK_EQUAL(nmos::nc_property_restore_notice_type::error, nmos::fields::nc::notice_type(notice)); + BST_CHECK_NE(U(""), nmos::fields::nc::notice_message(notice)); + + // expecting callback to get_read_only_modification_allow_list_called + // but not to modify_rebuildable_block_called + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + { + // Check an error is caused by trying to modify a read only property in Modify mode + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Change a read only property in Rebuild mode + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + // This is a read only property + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_receiver_monitor_connection_status_message_property_id, connection_status_property_descriptor, value(U("change this value")))); + // This is a writable property + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false))); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + // must be a more efficient way of initializing these role paths + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::modify; + bool validate = true; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + + const auto object_properties_set_validation = output.as_array().at(0); + + // expect overall status for object to be failed as although the writable property should succeed, + // the read only property change should fail with an error notice + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + + const auto& property_restore_notices = nmos::fields::nc::notices(object_properties_set_validation); + // expectation a single notice for the read only property that couldn't be changed + BST_REQUIRE_EQUAL(1, property_restore_notices.size()); + + const auto& notice = *property_restore_notices.begin(); + BST_CHECK_EQUAL(nmos::nc_receiver_monitor_connection_status_message_property_id, nmos::nc::details::parse_property_id(nmos::fields::nc::id(notice))); + BST_CHECK_EQUAL(nmos::fields::nc::connection_status_message.key, nmos::fields::nc::name(notice)); + BST_CHECK_EQUAL(nmos::nc_property_restore_notice_type::error, nmos::fields::nc::notice_type(notice)); + BST_CHECK_NE(U(""), nmos::fields::nc::notice_message(notice)); + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + { + // Check remove_device_model_object_called is called when trying to modify a rebuildable block + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + auto property_holders = value::array(); + auto members = value::array(); + + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + const auto object_properties_set_validation = output.as_array().at(0); + + BST_CHECK_EQUAL(role_path.as_array(), nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + const auto oid_property_descriptor = nmos::nc::details::make_property_descriptor(U("oid"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, web::json::value::null()); + { + // Check create_device_model_object_called is called when trying to modify a rebuildable block + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto property_holders = value::array(); + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + // Create Object Properties Holder for new monitor + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_receiver_monitor_class_id))); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one for the block and one each for the monitors + BST_REQUIRE_EQUAL(3, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_2_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_2_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_2_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_2_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_3_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_3_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_3_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_3_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(create_device_model_object_called); + } + { + // Check that role paths outside of the scope of the target role path are errored + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("other_receivers") }); + auto property_holders = value::array(); + auto members = value::array(); + + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation no object_properties_holders as not in the restore scope + BST_REQUIRE_EQUAL(0, output.as_array().size()); + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testApplyBackupDataSet_WithoutCallbacks) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor= nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + const auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})} })); + nmos::make_rebuildable(monitor1); + auto monitor_1_oid = oid; + const auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + // undefined callback stubs + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list; + nmos::remove_device_model_object_handler remove_device_model_object; + nmos::create_device_model_object_handler create_device_model_object; + + const auto enabled_property_descriptor = nmos::nc::details::make_property_descriptor(U("enabled"), nmos::nc_worker_enabled_property_id, nmos::fields::nc::enabled, U("NcBoolean"), false, false, false, false, web::json::value::null()); + { + // Check that Modify mode is unaffected by undefined Rebuild mode callbacks + // + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::modify; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + const auto object_properties_set_validation = output.as_array().at(0); + + BST_CHECK_EQUAL(role_path.as_array(), nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + { + // Check that Rebuild mode is unaffected by undefined Rebuild mode callbacks when no objects are being rebuilt + // + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_worker_enabled_property_id, enabled_property_descriptor, value::boolean(false)); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + const auto object_properties_set_validation = output.as_array().at(0); + + BST_CHECK_EQUAL(role_path.as_array(), nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + { + // Check undefined get_read_only_modification_allow_list_handler causes an unsupported mode error when attempting to modify a read only property in Rebuild mode + // + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + auto property_holders = value::array(); + // This is a read only property + const auto property_descriptor = nmos::nc::details::make_property_descriptor(U("connectionStatusMessage"), nmos::nc_receiver_monitor_connection_status_message_property_id, nmos::fields::nc::connection_status_message, U("NcString"), true, false, false, false, web::json::value::null()); + const auto property_holder = nmos::nc::details::make_property_holder(nmos::nc_receiver_monitor_connection_status_message_property_id, property_descriptor, value(U("change this value"))); + push_back(property_holders, property_holder); + const auto object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, object_properties_holder); + // must be a more efficient way of initializing these role paths + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + bool validate = true; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + + const auto object_properties_set_validation = output.as_array().at(0); + + // make sure the validation status propagates from the callback + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + { + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + const auto oid_property_descriptor = nmos::nc::details::make_property_descriptor(U("oid"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, web::json::value::null()); + // Check undefined create_device_model_object and remove_device_model_object causes an unsupported error when attempting to modify a rebuildable block + // + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + auto property_holders = value::array(); + auto members = value::array(); + + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto monitor_1_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_1_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_1_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holder + BST_CHECK_EQUAL(2, output.as_array().size()); + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + BST_REQUIRE_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_1_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_1_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_1_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_1_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testApplyBackupDataSet_AddDeviceModelObject) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor= nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({{nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})}})); + // make monitor1 rebuildable + nmos::make_rebuildable(monitor1); + + auto monitor_1_oid = oid; + auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + auto monitor_2_oid = oid; + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + bool get_read_only_modification_allow_list_called = false; + bool remove_device_model_object_called = false; + bool create_device_model_object_called = false; + + // callback stubs + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list = [&](const nmos::resources& resources, const nmos::resource& resource, const std::vector& target_role_path, const std::vector& property_ids) + { + get_read_only_modification_allow_list_called = true; + return property_ids; + }; + + nmos::remove_device_model_object_handler remove_device_model_object = [&](const nmos::resource& resource, const std::vector& target_role_path, bool validate) + { + remove_device_model_object_called = true; + + return true; + }; + + nmos::create_device_model_object_handler create_device_model_object = [&](const nmos::nc_class_id& class_id, nmos::nc_oid oid, bool constant_oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const web::json::value& touchpoints, bool validate, const std::map& property_values) + { + using web::json::value; + + create_device_model_object_called = true; + + auto data = nmos::nc::details::make_object(nmos::nc_receiver_monitor_class_id, oid, true, owner, role, web::json::value::string(user_label), U(""), web::json::value::null(), web::json::value::null()); + + return nmos::control_protocol_resource({ nmos::is12_versions::v1_0, nmos::types::nc_block, std::move(data), true }); + }; + + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + const auto oid_property_descriptor = nmos::nc::details::make_property_descriptor(U("oid"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, web::json::value::null()); + const auto class_id_property_descriptor = nmos::nc::details::make_property_descriptor(U("classId"), nmos::nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, web::json::value::null()); + { + // Handle constant oid clash + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto property_holders = value::array(); + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + // Create Object Properties Holder for new monitor + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_receiver_monitor_class_id))); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one for the block and one each for the monitors + BST_REQUIRE_EQUAL(3, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + const auto& monitor_2_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_2_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_2_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_2_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + } + const auto& monitor_3_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_3_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_3_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_3_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::device_error, nmos::fields::nc::status(object_properties_set_validation)); + } + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + { + // Check new oid is generated for new device model object + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto property_holders = value::array(); + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, false, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + // Create Object Properties Holder for new monitor + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_receiver_monitor_class_id))); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one for the block and one each for the monitors + BST_REQUIRE_EQUAL(3, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + // Expect a warning that the oid for mon3 has changed + BST_REQUIRE_EQUAL(1, nmos::fields::nc::notices(object_properties_set_validation).size()); + const auto& notice = nmos::fields::nc::notices(object_properties_set_validation).at(0); + BST_CHECK_EQUAL(nmos::nc_property_restore_notice_type::warning, nmos::fields::nc::notice_type(notice)); + const auto& property_id = nmos::fields::nc::id(notice); + BST_CHECK_EQUAL(nmos::fields::nc::level(property_id), nmos::nc_block_members_property_id.level); + BST_CHECK_EQUAL(nmos::fields::nc::index(property_id), nmos::nc_block_members_property_id.index); + } + const auto& monitor_2_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_2_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_2_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_2_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_3_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_3_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_3_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_3_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(1, nmos::fields::nc::notices(object_properties_set_validation).size()); + const auto& notice = nmos::fields::nc::notices(object_properties_set_validation).at(0); + BST_CHECK_EQUAL(nmos::nc_property_restore_notice_type::warning, nmos::fields::nc::notice_type(notice)); + const auto& property_id = nmos::fields::nc::id(notice); + BST_CHECK_EQUAL(nmos::fields::nc::level(property_id), nmos::nc_object_oid_property_id.level); + BST_CHECK_EQUAL(nmos::fields::nc::index(property_id), nmos::nc_object_oid_property_id.index); + } + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(create_device_model_object_called); + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testApplyBackupDataSet_NegativeTests) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor= nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})} })); + // make monitor1 rebuildable + nmos::make_rebuildable(monitor1); + + auto monitor_1_oid = oid; + auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + auto monitor_2_oid = oid; + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + bool get_read_only_modification_allow_list_called = false; + bool remove_device_model_object_called = false; + bool create_device_model_object_called = false; + + // callback stubs + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list = [&](const nmos::resources& resources, const nmos::resource& resource, const std::vector& target_role_path, const std::vector& property_ids) + { + get_read_only_modification_allow_list_called = true; + return property_ids; + }; + + nmos::remove_device_model_object_handler remove_device_model_object = [&](const nmos::resource& resource, const std::vector& target_role_path, bool validate) + { + remove_device_model_object_called = true; + + // Simulate error on removing object from device model + return false; + }; + + nmos::create_device_model_object_handler create_device_model_object = [&](const nmos::nc_class_id& class_id, nmos::nc_oid oid, bool constant_oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const web::json::value& touchpoints, bool validate, const std::map& property_values) + { + create_device_model_object_called = true; + // Simulate error on adding object to device model + return nmos::control_protocol_resource(); + }; + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + const auto oid_property_descriptor = nmos::nc::details::make_property_descriptor(U("oid"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, web::json::value::null()); + { + // Check remove_device_model_object_called error is handled when attempting to modify a rebuildable block + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + auto property_holders = value::array(); + auto members = value::array(); + + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one + BST_REQUIRE_EQUAL(1, output.as_array().size()); + const auto& object_properties_set_validation = output.as_array().at(0); + + BST_CHECK_EQUAL(role_path.as_array(), nmos::fields::nc::path(object_properties_set_validation)); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + BST_REQUIRE_EQUAL(1, nmos::fields::nc::notices(object_properties_set_validation).size()); + const auto& notice = nmos::fields::nc::notices(object_properties_set_validation).at(0); + BST_CHECK_EQUAL(nmos::fields::nc::notice_type(notice), nmos::nc_property_restore_notice_type::error); + const auto& property_id = nmos::fields::nc::id(notice); + BST_CHECK_EQUAL(nmos::fields::nc::level(property_id), nmos::nc_block_members_property_id.level); + BST_CHECK_EQUAL(nmos::fields::nc::index(property_id), nmos::nc_block_members_property_id.index); + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(remove_device_model_object_called); + BST_CHECK(!create_device_model_object_called); + } + { + // Check on remove_device_model_object_called error all other object properties holders are processed + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + auto property_holders = value::array(); + auto members = value::array(); + + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto monitor_1_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_1_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_1_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders + BST_CHECK_EQUAL(2, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(1, nmos::fields::nc::notices(object_properties_set_validation).size()); + const auto& notice = nmos::fields::nc::notices(object_properties_set_validation).at(0); + BST_CHECK_EQUAL(nmos::fields::nc::notice_type(notice), nmos::nc_property_restore_notice_type::error); + const auto& property_id = nmos::fields::nc::id(notice); + BST_CHECK_EQUAL(nmos::fields::nc::level(property_id), nmos::nc_block_members_property_id.level); + BST_CHECK_EQUAL(nmos::fields::nc::index(property_id), nmos::nc_block_members_property_id.index); + } + const auto& monitor_1_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_1_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_1_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_1_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + } + const auto class_id_property_descriptor = nmos::nc::details::make_property_descriptor(U("classId"), nmos::nc_object_class_id_property_id, U("classId"), U("NcClassId"), true, false, false, false, web::json::value::null()); + { + // Check create_device_model_object_called error is handled when trying to modify a rebuildable block + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto property_holders = value::array(); + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + // Create Object Properties Holder for new monitor + const auto monitor_1_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_1_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_1_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_receiver_monitor_class_id))); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders i.e. one for the block and one each for the monitors + BST_CHECK_EQUAL(4, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_1_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_1_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_1_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_1_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_2_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_2_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_2_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_2_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + const auto& monitor_3_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_3_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_3_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_3_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::device_error, nmos::fields::nc::status(object_properties_set_validation)); + BST_CHECK_EQUAL(0, nmos::fields::nc::notices(object_properties_set_validation).size()); + } + + BST_CHECK(!get_read_only_modification_allow_list_called); + BST_CHECK(!remove_device_model_object_called); + BST_CHECK(create_device_model_object_called); + } + { + // Check duplicate block object properties holders are handled + // + get_read_only_modification_allow_list_called = false; + remove_device_model_object_called = false; + create_device_model_object_called = false; + + // Create Object Properties Holder + auto object_properties_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + auto property_holders1 = value::array(); + auto members1 = value::array(); + auto property_holders2 = value::array(); + auto members2 = value::array(); + + push_back(members1, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders1, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members1)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders1.as_array(), value::array().as_array(), value::array().as_array(), false)); + // duplicate + push_back(members2, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(property_holders2, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members2)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(role_path.as_array(), property_holders2.as_array(), value::array().as_array(), value::array().as_array(), false)); + const auto monitor_1_role_path = value_of({ U("root"), U("receivers"), U("mon1") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_1_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_1_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool recurse = true; + bool validate = true; + const auto restore_mode = nmos::nc_restore_mode::restore_mode::rebuild; + + const auto& resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + const auto output = nmos::apply_backup_data_set(resources, *resource, object_properties_holders.as_array(), recurse, restore_mode, validate, get_control_protocol_class_descriptor, get_control_protocol_datatype_descriptor, get_read_only_modification_allow_list, remove_device_model_object, create_device_model_object); + + // expectation is there will be a result for each of the object_properties_holders + BST_CHECK_EQUAL(3, output.as_array().size()); + + // Check the correct object properties holders have been returned + const auto& block_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), role_path.as_array()); + BST_REQUIRE_EQUAL(block_object_properties_holder.size(), 2); // expect a duplicate + { + const auto& object_properties_set_validation0 = block_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation0)); + const auto& object_properties_set_validation1 = block_object_properties_holder.at(1); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation1)); + } + const auto& monitor_1_object_properties_holder = nmos::get_object_properties_holder(output.as_array(), monitor_1_role_path.as_array()); + BST_REQUIRE_EQUAL(monitor_1_object_properties_holder.size(), 1); + { + const auto& object_properties_set_validation = monitor_1_object_properties_holder.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + } + } +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testModifyRebuildableBlock) +{ + using web::json::value_of; + using web::json::value; + + nmos::resources resources; + nmos::experimental::control_protocol_state control_protocol_state; + nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); + + // Create Device Model + // root + auto root_block = nmos::make_root_block(); + auto oid = nmos::root_block_oid; + // root, ClassManager + auto class_manager = nmos::make_class_manager(++oid, control_protocol_state); + auto receiver_block_oid = ++oid; + // root, receivers + auto receivers = nmos::make_block(receiver_block_oid, nmos::root_block_oid, U("receivers"), U("Receivers"), U("Receivers block")); + nmos::make_rebuildable(receivers); + nmos::set_block_allowed_member_classes(receivers, {nmos::nc_receiver_monitor_class_id}); + // root, receivers, mon1 + auto monitor1 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_1")})} })); + // make monitor1 rebuildable + nmos::make_rebuildable(monitor1); + + auto monitor_1_oid = oid; + auto monitor_class_id = nmos::nc::details::parse_class_id(nmos::fields::nc::class_id(monitor1.data)); + // root, receivers, mon2 + auto monitor2 = nmos::make_receiver_monitor(++oid, true, receiver_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, U("id_2")})} })); + auto monitor_2_oid = oid; + nmos::nc::push_back(receivers, monitor1); + // add example-control to root-block + nmos::nc::push_back(receivers, monitor2); + // add stereo-gain to root-block + nmos::nc::push_back(root_block, receivers); + // add class-manager to root-block + nmos::nc::push_back(root_block, class_manager); + + // insert root block and all sub control protocol resources to resource list + nmos::nc::insert_root(resources, root_block); + + bool get_read_only_modification_allow_list_called = false; + bool remove_device_model_object_called = false; + bool create_device_model_object_called = false; + + // callback stubs + nmos::get_read_only_modification_allow_list_handler get_read_only_modification_allow_list = [&](const nmos::resources& resources, const nmos::resource& resource, const std::vector& target_role_path, const std::vector& property_ids) + { + get_read_only_modification_allow_list_called = true; + return property_ids; + }; + + nmos::remove_device_model_object_handler remove_device_model_object = [&](const nmos::resource& resource, const std::vector& target_role_path, bool validate) + { + remove_device_model_object_called = true; + + return true; + }; + + nmos::create_device_model_object_handler create_device_model_object = [&](const nmos::nc_class_id& class_id, nmos::nc_oid oid, bool constant_oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const web::json::value& touchpoints, bool validate, const std::map& property_values) + { + using web::json::value; + + create_device_model_object_called = true; + + auto data = nmos::nc::details::make_object(nmos::nc_receiver_monitor_class_id, oid, true, owner, role, web::json::value::string(user_label), U(""), web::json::value::null(), web::json::value::null()); + + return nmos::control_protocol_resource({ nmos::is12_versions::v1_0, nmos::types::nc_block, std::move(data), true }); + }; + const auto block_members_property_descriptor = nmos::nc::details::make_property_descriptor(U("members"), nmos::nc_block_members_property_id, nmos::fields::nc::members, U("NcBlockMemberDescriptor"), true, false, true, false, web::json::value::null()); + const auto oid_property_descriptor = nmos::nc::details::make_property_descriptor(U("oid"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, web::json::value::null()); + const auto class_id_property_descriptor = nmos::nc::details::make_property_descriptor(U("classId"), nmos::nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, web::json::value::null()); + + // No class id specified in the objet properties holder for new monitor causes an error + { + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + auto block_property_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(block_property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + } + const auto block_object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), block_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, block_object_properties_holder); + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + // Create Object Properties Holder for new monitor + auto monitor3_property_holders = value::array(); + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + // No property holders, including no class id + push_back(monitor3_property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), monitor3_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool validate = true; + const value restore_mode{ nmos::nc_restore_mode::restore_mode::rebuild }; + + nmos::object_properties_map object_properties_holder_map; + + for (const auto& object_properties_holder: object_properties_holders.as_array()) + { + const auto& role_path = nmos::fields::nc::path(object_properties_holder); + object_properties_holder_map.insert({ role_path, object_properties_holder }); + } + + const auto resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + + // allowed member classes specified for block but no class_id property holder in the new monitor object properties holder + const auto object_set_validations = nmos::details::modify_rebuildable_block(resources, object_properties_holder_map, *resource, target_role_path.as_array(), block_object_properties_holder, validate, get_control_protocol_class_descriptor, remove_device_model_object, create_device_model_object); + + BST_REQUIRE_EQUAL(object_set_validations.size(), 2); + { + const auto& object_properties_set_validation = object_set_validations.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + { + // warnings perhaps? + const auto& object_properties_set_validation = object_set_validations.at(1); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + } + + // add class id to the property holders, but use a disallowed class id + { + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + auto block_property_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(block_property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + } + const auto block_object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), block_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, block_object_properties_holder); + // Create Object Properties Holder for new monitor + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + auto monitor3_property_holders = value::array(); + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + //auto property_holders = value::array(); + push_back(monitor3_property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(monitor3_property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_block_class_id))); // disallowed class id + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), monitor3_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool validate = true; + const value restore_mode{ nmos::nc_restore_mode::restore_mode::rebuild }; + + nmos::object_properties_map object_properties_holder_map; + + for (const auto& object_properties_holder: object_properties_holders.as_array()) + { + const auto& role_path = nmos::fields::nc::path(object_properties_holder); + object_properties_holder_map.insert({ role_path, object_properties_holder }); + } + + const auto resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + // allowed member classes specified for block but class_id property holder has disallowed class_id + const auto object_set_validations = nmos::details::modify_rebuildable_block(resources, object_properties_holder_map, *resource, target_role_path.as_array(), block_object_properties_holder, validate, get_control_protocol_class_descriptor, remove_device_model_object, create_device_model_object); + + BST_REQUIRE_EQUAL(object_set_validations.size(), 2); + { + const auto& object_properties_set_validation = object_set_validations.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + { + // warnings perhaps? + const auto& object_properties_set_validation = object_set_validations.at(1); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::failed, nmos::fields::nc::status(object_properties_set_validation)); + } + } + + // add class id to the property holders, and use an allowed class id + { + auto monitor_3_oid = 999; + // Create Object Properties Holder for Block, with a Property Holder for the block members + auto object_properties_holders = value::array(); + auto block_property_holders = value::array(); + const auto role_path = value_of({ U("root"), U("receivers") }); + { + auto members = value::array(); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 1"), U("mon1"), monitor_1_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 2"), U("mon2"), monitor_2_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(members, nmos::nc::details::make_block_member_descriptor(U("monitor 3"), U("mon3"), monitor_3_oid, true, monitor_class_id, U("label"), receiver_block_oid)); + push_back(block_property_holders, nmos::nc::details::make_property_holder(nmos::nc_block_members_property_id, block_members_property_descriptor, members)); + } + const auto block_object_properties_holder = nmos::nc::details::make_object_properties_holder(role_path.as_array(), block_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false); + push_back(object_properties_holders, block_object_properties_holder); + // Create Object Properties Holder for new monitor + const auto monitor_2_role_path = value_of({ U("root"), U("receivers"), U("mon2") }); + { + auto property_holders = value::array(); + push_back(property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_2_oid)); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_2_role_path.as_array(), property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + auto monitor3_property_holders = value::array(); + const auto monitor_3_role_path = value_of({ U("root"), U("receivers"), U("mon3") }); + { + //auto property_holders = value::array(); + push_back(monitor3_property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_oid_property_id, oid_property_descriptor, monitor_3_oid)); + push_back(monitor3_property_holders, nmos::nc::details::make_property_holder(nmos::nc_object_class_id_property_id, class_id_property_descriptor, nmos::nc::details::make_class_id(nmos::nc_receiver_monitor_class_id))); + push_back(object_properties_holders, nmos::nc::details::make_object_properties_holder(monitor_3_role_path.as_array(), monitor3_property_holders.as_array(), value::array().as_array(), value::array().as_array(), false)); + } + const auto target_role_path = value_of({ U("root"), U("receivers") }); + bool validate = true; + const value restore_mode{ nmos::nc_restore_mode::restore_mode::rebuild }; + + nmos::object_properties_map object_properties_holder_map; + + for (const auto& object_properties_holder: object_properties_holders.as_array()) + { + const auto& role_path = nmos::fields::nc::path(object_properties_holder); + object_properties_holder_map.insert({ role_path, object_properties_holder }); + } + + const auto resource = nmos::nc::find_resource_by_role_path(resources, target_role_path.as_array()); + // allowed member classes specified for block but class_id property holder has disallowed class_id + const auto object_set_validations = nmos::details::modify_rebuildable_block(resources, object_properties_holder_map, *resource, target_role_path.as_array(), block_object_properties_holder, validate, get_control_protocol_class_descriptor, remove_device_model_object, create_device_model_object); + + BST_REQUIRE_EQUAL(object_set_validations.size(), 2); + { + const auto& object_properties_set_validation = object_set_validations.at(0); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + } + { + // warnings perhaps? + const auto& object_properties_set_validation = object_set_validations.at(1); + BST_CHECK_EQUAL(nmos::nc_restore_validation_status::ok, nmos::fields::nc::status(object_properties_set_validation)); + } + } +} diff --git a/Development/nmos/test/control_protocol_methods_test.cpp b/Development/nmos/test/control_protocol_methods_test.cpp index ba8b97faf..26c8fd2a8 100644 --- a/Development/nmos/test/control_protocol_methods_test.cpp +++ b/Development/nmos/test/control_protocol_methods_test.cpp @@ -34,12 +34,11 @@ BST_TEST_CASE(testRemoveSequenceItem) property_changed_called = true; }; - nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, nullptr, property_changed); + nmos::experimental::control_protocol_state control_protocol_state(property_changed, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); - // Create simple non-standard class with writable sequence property - const auto writable_sequence_class_id = nmos::make_nc_class_id(nmos::nc_worker_class_id, -1234, { 1000 }); + const auto writable_sequence_class_id = nmos::nc::make_class_id(nmos::nc_worker_class_id, -1234, { 1000 }); const web::json::field_as_array writable_value{ U("writableValue") }; { // Writable sequence_class property descriptors @@ -54,7 +53,7 @@ BST_TEST_CASE(testRemoveSequenceItem) // helper function to create writable_sequence object auto make_writable_sequence = [&writable_value, &writable_sequence_class_id](nmos::nc_oid oid, nmos::nc_oid owner, const utility::string_t& role, const utility::string_t& user_label, const utility::string_t& description) { - auto data = nmos::details::make_nc_worker(writable_sequence_class_id, oid, true, owner, role, value::string(user_label), description, web::json::value::null(), web::json::value::null(), true); + auto data = nmos::nc::details::make_worker(writable_sequence_class_id, oid, true, owner, role, value::string(user_label), description, web::json::value::null(), web::json::value::null(), true); auto values = value::array(); web::json::push_back(values, value::number(10)); web::json::push_back(values, value::number(9)); @@ -83,15 +82,15 @@ BST_TEST_CASE(testRemoveSequenceItem) auto writable_sequence = make_writable_sequence(++oid, nmos::root_block_oid, U("writableSequence"), U("writable sequence"), U("writable sequence")); auto writable_sequence_id = writable_sequence.id; - nmos::push_back(receivers, monitor1); + nmos::nc::push_back(receivers, monitor1); // add example-control to root-block - nmos::push_back(receivers, monitor2); + nmos::nc::push_back(receivers, monitor2); // add stereo-gain to root-block - nmos::push_back(root_block, receivers); + nmos::nc::push_back(root_block, receivers); // add class-manager to root-block - nmos::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, class_manager); // add writable sequence to root block - nmos::push_back(root_block, writable_sequence); + nmos::nc::push_back(root_block, writable_sequence); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(receivers)); @@ -115,7 +114,7 @@ BST_TEST_CASE(testRemoveSequenceItem) auto resource = nmos::find_resource(resources, receivers_id); BST_CHECK_NE(resources.end(), resource); - auto result = nmos::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate); + auto result = nmos::nc::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate); // Expect read only error, and for property changed not to be called BST_CHECK_EQUAL(false, property_changed_called); @@ -138,7 +137,7 @@ BST_TEST_CASE(testRemoveSequenceItem) auto resource = nmos::find_resource(resources, writable_sequence_id); BST_CHECK_NE(resources.end(), resource); - auto result = nmos::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate); + auto result = nmos::nc::remove_sequence_item(resources, *resource, arguments, false, get_control_protocol_class_descriptor, property_changed, gate); // Expect success, and property changed event BST_CHECK_EQUAL(true, property_changed_called); diff --git a/Development/nmos/test/control_protocol_test.cpp b/Development/nmos/test/control_protocol_test.cpp index fef021be4..b8f418d8d 100644 --- a/Development/nmos/test/control_protocol_test.cpp +++ b/Development/nmos/test/control_protocol_test.cpp @@ -29,7 +29,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_class_id_ = nmos::details::make_nc_property_descriptor(U("Static value. All instances of the same class will have the same identity value"), nmos::nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, value::null()); + const auto property_class_id_ = nmos::nc::details::make_property_descriptor(U("Static value. All instances of the same class will have the same identity value"), nmos::nc_object_class_id_property_id, nmos::fields::nc::class_id, U("NcClassId"), true, false, false, false, value::null()); BST_REQUIRE_EQUAL(property_class_id, property_class_id_); const auto property_oid = value_of({ @@ -46,7 +46,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_oid_ = nmos::details::make_nc_property_descriptor(U("Object identifier"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, value::null()); + const auto property_oid_ = nmos::nc::details::make_property_descriptor(U("Object identifier"), nmos::nc_object_oid_property_id, nmos::fields::nc::oid, U("NcOid"), true, false, false, false, value::null()); BST_REQUIRE_EQUAL(property_oid, property_oid_); const auto property_constant_oid = value_of({ @@ -63,7 +63,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_constant_oid_ = nmos::details::make_nc_property_descriptor(U("TRUE iff OID is hardwired into device"), nmos::nc_object_constant_oid_property_id, nmos::fields::nc::constant_oid, U("NcBoolean"), true, false, false, false, value::null()); + const auto property_constant_oid_ = nmos::nc::details::make_property_descriptor(U("TRUE iff OID is hardwired into device"), nmos::nc_object_constant_oid_property_id, nmos::fields::nc::constant_oid, U("NcBoolean"), true, false, false, false, value::null()); BST_REQUIRE_EQUAL(property_constant_oid, property_constant_oid_); const auto property_owner = value_of({ @@ -80,7 +80,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_owner_ = nmos::details::make_nc_property_descriptor(U("OID of containing block. Can only ever be null for the root block"), nmos::nc_object_owner_property_id, nmos::fields::nc::owner, U("NcOid"), true, true, false, false, value::null()); + const auto property_owner_ = nmos::nc::details::make_property_descriptor(U("OID of containing block. Can only ever be null for the root block"), nmos::nc_object_owner_property_id, nmos::fields::nc::owner, U("NcOid"), true, true, false, false, value::null()); BST_REQUIRE_EQUAL(property_owner, property_owner_); const auto property_role = value_of({ @@ -97,7 +97,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_role_ = nmos::details::make_nc_property_descriptor(U("Role of object in the containing block"), nmos::nc_object_role_property_id, nmos::fields::nc::role, U("NcString"), true, false, false, false, value::null()); + const auto property_role_ = nmos::nc::details::make_property_descriptor(U("Role of object in the containing block"), nmos::nc_object_role_property_id, nmos::fields::nc::role, U("NcString"), true, false, false, false, value::null()); BST_REQUIRE_EQUAL(property_role, property_role_); const auto property_user_label = value_of({ @@ -114,7 +114,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_user_label_ = nmos::details::make_nc_property_descriptor(U("Scribble strip"), nmos::nc_object_user_label_property_id, nmos::fields::nc::user_label, U("NcString"), false, true, false, false, value::null()); + const auto property_user_label_ = nmos::nc::details::make_property_descriptor(U("Scribble strip"), nmos::nc_object_user_label_property_id, nmos::fields::nc::user_label, U("NcString"), false, true, false, false, value::null()); BST_REQUIRE_EQUAL(property_user_label, property_user_label_); const auto property_touchpoints = value_of({ @@ -131,7 +131,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_touchpoints_ = nmos::details::make_nc_property_descriptor(U("Touchpoints to other contexts"), nmos::nc_object_touchpoints_property_id, nmos::fields::nc::touchpoints, U("NcTouchpoint"), true, true, true, false, value::null()); + const auto property_touchpoints_ = nmos::nc::details::make_property_descriptor(U("Touchpoints to other contexts"), nmos::nc_object_touchpoints_property_id, nmos::fields::nc::touchpoints, U("NcTouchpoint"), true, true, true, false, value::null()); BST_REQUIRE_EQUAL(property_touchpoints, property_touchpoints_); const auto property_runtime_property_constraints = value_of({ @@ -148,7 +148,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false }, { U("constraints"), value::null() } }); - const auto property_runtime_property_constraints_ = nmos::details::make_nc_property_descriptor(U("Runtime property constraints"), nmos::nc_object_runtime_property_constraints_property_id, nmos::fields::nc::runtime_property_constraints, U("NcPropertyConstraints"), true, true, true, false, value::null()); + const auto property_runtime_property_constraints_ = nmos::nc::details::make_property_descriptor(U("Runtime property constraints"), nmos::nc_object_runtime_property_constraints_property_id, nmos::fields::nc::runtime_property_constraints, U("NcPropertyConstraints"), true, true, true, false, value::null()); BST_REQUIRE_EQUAL(property_runtime_property_constraints, property_runtime_property_constraints_); const auto method_get = value_of({ @@ -174,8 +174,8 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - const auto method_get_ = nmos::details::make_nc_method_descriptor(U("Get property value"), nmos::nc_object_get_method_id, U("Get"), U("NcMethodResultPropertyValue"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + const auto method_get_ = nmos::nc::details::make_method_descriptor(U("Get property value"), nmos::nc_object_get_method_id, U("Get"), U("NcMethodResultPropertyValue"), parameters, false); BST_REQUIRE_EQUAL(method_get, method_get_); } @@ -211,9 +211,9 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property value"), nmos::fields::nc::value, true, false, value::null())); - const auto method_set_ = nmos::details::make_nc_method_descriptor(U("Set property value"), nmos::nc_object_set_method_id, U("Set"), U("NcMethodResult"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property value"), nmos::fields::nc::value, true, false, value::null())); + const auto method_set_ = nmos::nc::details::make_method_descriptor(U("Set property value"), nmos::nc_object_set_method_id, U("Set"), U("NcMethodResult"), parameters, false); BST_REQUIRE_EQUAL(method_set, method_set_); } @@ -249,9 +249,9 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - const auto method_get_sequence_item_ = nmos::details::make_nc_method_descriptor(U("Get sequence item"), nmos::nc_object_get_sequence_item_method_id, U("GetSequenceItem"), U("NcMethodResultPropertyValue"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + const auto method_get_sequence_item_ = nmos::nc::details::make_method_descriptor(U("Get sequence item"), nmos::nc_object_get_sequence_item_method_id, U("GetSequenceItem"), U("NcMethodResultPropertyValue"), parameters, false); BST_REQUIRE_EQUAL(method_get_sequence_item, method_get_sequence_item_); } @@ -295,10 +295,10 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); - const auto method_set_sequence_item_ = nmos::details::make_nc_method_descriptor(U("Set sequence item value"), nmos::nc_object_set_sequence_item_method_id, U("SetSequenceItem"), U("NcMethodResult"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); + const auto method_set_sequence_item_ = nmos::nc::details::make_method_descriptor(U("Set sequence item value"), nmos::nc_object_set_sequence_item_method_id, U("SetSequenceItem"), U("NcMethodResult"), parameters, false); BST_REQUIRE_EQUAL(method_set_sequence_item, method_set_sequence_item_); } @@ -334,9 +334,9 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); - const auto method_add_sequence_item_ = nmos::details::make_nc_method_descriptor(U("Add item to sequence"), nmos::nc_object_add_sequence_item_method_id, U("AddSequenceItem"), U("NcMethodResultId"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Value"), nmos::fields::nc::value, true, false, value::null())); + const auto method_add_sequence_item_ = nmos::nc::details::make_method_descriptor(U("Add item to sequence"), nmos::nc_object_add_sequence_item_method_id, U("AddSequenceItem"), U("NcMethodResultId"), parameters, false); BST_REQUIRE_EQUAL(method_add_sequence_item, method_add_sequence_item_); } @@ -372,9 +372,9 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); - const auto method_remove_sequence_item_ = nmos::details::make_nc_method_descriptor(U("Delete sequence item"), nmos::nc_object_remove_sequence_item_method_id, U("RemoveSequenceItem"), U("NcMethodResult"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Index of item in the sequence"), nmos::fields::nc::index, U("NcId"), false, false, value::null())); + const auto method_remove_sequence_item_ = nmos::nc::details::make_method_descriptor(U("Delete sequence item"), nmos::nc_object_remove_sequence_item_method_id, U("RemoveSequenceItem"), U("NcMethodResult"), parameters, false); BST_REQUIRE_EQUAL(method_remove_sequence_item, method_remove_sequence_item_); } @@ -402,8 +402,8 @@ BST_TEST_CASE(testNcClassDescriptor) { auto parameters = value::array(); - web::json::push_back(parameters, nmos::details::make_nc_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); - const auto method_get_sequence_length_ = nmos::details::make_nc_method_descriptor(U("Get sequence length"), nmos::nc_object_get_sequence_length_method_id, U("GetSequenceLength"), U("NcMethodResultLength"), parameters, false); + web::json::push_back(parameters, nmos::nc::details::make_parameter_descriptor(U("Property id"), nmos::fields::nc::id, U("NcPropertyId"), false, false, value::null())); + const auto method_get_sequence_length_ = nmos::nc::details::make_method_descriptor(U("Get sequence length"), nmos::nc_object_get_sequence_length_method_id, U("GetSequenceLength"), U("NcMethodResultLength"), parameters, false); BST_REQUIRE_EQUAL(method_get_sequence_length, method_get_sequence_length_); } @@ -419,7 +419,7 @@ BST_TEST_CASE(testNcClassDescriptor) { U("isDeprecated"), false } }); - const auto event_property_changed_ = nmos::details::make_nc_event_descriptor(U("Property changed event"), nmos::nc_object_property_changed_event_id, U("PropertyChanged"), U("NcPropertyChangedEventData"), false); + const auto event_property_changed_ = nmos::nc::details::make_event_descriptor(U("Property changed event"), nmos::nc_object_property_changed_event_id, U("PropertyChanged"), U("NcPropertyChangedEventData"), false); BST_REQUIRE_EQUAL(event_property_changed, event_property_changed_); const auto nc_object_class = value_of({ @@ -452,7 +452,7 @@ BST_TEST_CASE(testNcClassDescriptor) event_property_changed }) } }); - const auto nc_object_class_ = nmos::details::make_nc_class_descriptor(U("NcObject class descriptor"), nmos::nc_object_class_id, U("NcObject"), nmos::make_nc_object_properties(), nmos::make_nc_object_methods(), nmos::make_nc_object_events()); + const auto nc_object_class_ = nmos::nc::details::make_class_descriptor(U("NcObject class descriptor"), nmos::nc_object_class_id, U("NcObject"), nmos::nc::make_object_properties(), nmos::nc::make_object_methods(), nmos::nc::make_object_events()); BST_REQUIRE_EQUAL(nc_object_class, nc_object_class_); } @@ -522,13 +522,13 @@ BST_TEST_CASE(testNcDatatypeDescriptorStruct) }); auto fields = value::array(); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Role of member in its containing block"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("OID of member"), nmos::fields::nc::oid, U("NcOid"), false, false, value::null())); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("TRUE iff member's OID is hardwired into device"), nmos::fields::nc::constant_oid, U("NcBoolean"), false, false, value::null())); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("User label"), nmos::fields::nc::user_label, U("NcString"), true, false, value::null())); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Containing block's OID"), nmos::fields::nc::owner, U("NcOid"), false, false, value::null())); - const auto nc_datatype_descriptor_ = nmos::details::make_nc_datatype_descriptor_struct(U("Descriptor which is specific to a block member"), U("NcBlockMemberDescriptor"), fields, U("NcDescriptor"), value::null()); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Role of member in its containing block"), nmos::fields::nc::role, U("NcString"), false, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("OID of member"), nmos::fields::nc::oid, U("NcOid"), false, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("TRUE iff member's OID is hardwired into device"), nmos::fields::nc::constant_oid, U("NcBoolean"), false, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Class ID"), nmos::fields::nc::class_id, U("NcClassId"), false, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("User label"), nmos::fields::nc::user_label, U("NcString"), true, false, value::null())); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Containing block's OID"), nmos::fields::nc::owner, U("NcOid"), false, false, value::null())); + const auto nc_datatype_descriptor_ = nmos::nc::details::make_datatype_descriptor_struct(U("Descriptor which is specific to a block member"), U("NcBlockMemberDescriptor"), fields, U("NcDescriptor"), value::null()); BST_REQUIRE_EQUAL(nc_datatype_descriptor, nc_datatype_descriptor_); } @@ -548,7 +548,7 @@ BST_TEST_CASE(testNcDatatypeTypedef) { U("isSequence"), true }, { U("constraints"), value::null() } }); - const auto nc_class_id_ = nmos::details::make_nc_datatype_typedef(U("Sequence of class ID fields"), U("NcClassId"), true, U("NcInt32"), value::null()); + const auto nc_class_id_ = nmos::nc::details::make_datatype_typedef(U("Sequence of class ID fields"), U("NcClassId"), true, U("NcInt32"), value::null()); BST_REQUIRE_EQUAL(nc_class_id, nc_class_id_); } @@ -600,13 +600,13 @@ BST_TEST_CASE(testNcDatatypeDescriptorEnum) }); auto items = value::array(); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Normal operation"), U("NormalOperation"), 1)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Device is initializing"), U("Initializing"), 2)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Device is performing a software or firmware update"), U("Updating"), 3)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Device is experiencing a licensing error"), U("LicensingError"), 4)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("Device is experiencing an internal error"), U("InternalError"), 5)); - const auto nc_device_generic_state_ = nmos::details::make_nc_datatype_descriptor_enum(U("Device generic operational state"), U("NcDeviceGenericState"), items, value::null()); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Unknown"), U("Unknown"), 0)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Normal operation"), U("NormalOperation"), 1)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Device is initializing"), U("Initializing"), 2)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Device is performing a software or firmware update"), U("Updating"), 3)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Device is experiencing a licensing error"), U("LicensingError"), 4)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("Device is experiencing an internal error"), U("InternalError"), 5)); + const auto nc_device_generic_state_ = nmos::nc::details::make_datatype_descriptor_enum(U("Device generic operational state"), U("NcDeviceGenericState"), items, value::null()); BST_REQUIRE_EQUAL(nc_device_generic_state, nc_device_generic_state_); } @@ -623,49 +623,49 @@ BST_TEST_CASE(testNcDatatypeDescriptorPrimitive) { U("constraints"), value::null() } }); - const auto test_primitive_ = nmos::details::make_nc_datatype_descriptor_primitive(U("Primitive datatype descriptor"), U("test_primitive"), value::null()); + const auto test_primitive_ = nmos::nc::details::make_datatype_descriptor_primitive(U("Primitive datatype descriptor"), U("test_primitive"), value::null()); BST_REQUIRE_EQUAL(test_primitive, test_primitive_); } BST_TEST_CASE(testNcClassId) { - BST_REQUIRE_EQUAL(false, nmos::is_nc_block({ })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_block({ 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_block({ 1, 2 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_block({ 1, 2, 0 })); - BST_REQUIRE(nmos::is_nc_block(nmos::nc_block_class_id)); - BST_REQUIRE(nmos::is_nc_block(nmos::make_nc_class_id(nmos::nc_block_class_id, { 1 }))); - - BST_REQUIRE_EQUAL(false, nmos::is_nc_worker({ })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_worker({ 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_worker({ 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_worker({ 1, 1, 1 })); - BST_REQUIRE(nmos::is_nc_worker(nmos::nc_worker_class_id)); - BST_REQUIRE(nmos::is_nc_worker(nmos::make_nc_class_id(nmos::nc_worker_class_id, { 1 }))); - - BST_REQUIRE_EQUAL(false, nmos::is_nc_manager({ })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_manager({ 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_manager({ 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_manager({ 1, 1, 1 })); - BST_REQUIRE(nmos::is_nc_manager(nmos::nc_manager_class_id)); - BST_REQUIRE(nmos::is_nc_manager(nmos::make_nc_class_id(nmos::nc_manager_class_id, { 1 }))); - - BST_REQUIRE_EQUAL(false, nmos::is_nc_device_manager({ })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_device_manager({ 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_device_manager({ 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_device_manager({ 1, 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_device_manager({ 1, 3, 2 })); - BST_REQUIRE(nmos::is_nc_device_manager(nmos::nc_device_manager_class_id)); - BST_REQUIRE(nmos::is_nc_device_manager(nmos::make_nc_class_id(nmos::nc_device_manager_class_id, { 1 }))); - - BST_REQUIRE_EQUAL(false, nmos::is_nc_class_manager({ })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_class_manager({ 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_class_manager({ 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_class_manager({ 1, 1, 1 })); - BST_REQUIRE_EQUAL(false, nmos::is_nc_class_manager({ 1, 3, 1 })); - BST_REQUIRE(nmos::is_nc_class_manager(nmos::nc_class_manager_class_id)); - BST_REQUIRE(nmos::is_nc_class_manager(nmos::make_nc_class_id(nmos::nc_class_manager_class_id, { 1 }))); + BST_REQUIRE_EQUAL(false, nmos::nc::is_block({ })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_block({ 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_block({ 1, 2 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_block({ 1, 2, 0 })); + BST_REQUIRE(nmos::nc::is_block(nmos::nc_block_class_id)); + BST_REQUIRE(nmos::nc::is_block(nmos::nc::make_class_id(nmos::nc_block_class_id, { 1 }))); + + BST_REQUIRE_EQUAL(false, nmos::nc::is_worker({ })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_worker({ 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_worker({ 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_worker({ 1, 1, 1 })); + BST_REQUIRE(nmos::nc::is_worker(nmos::nc_worker_class_id)); + BST_REQUIRE(nmos::nc::is_worker(nmos::nc::make_class_id(nmos::nc_worker_class_id, { 1 }))); + + BST_REQUIRE_EQUAL(false, nmos::nc::is_manager({ })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_manager({ 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_manager({ 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_manager({ 1, 1, 1 })); + BST_REQUIRE(nmos::nc::is_manager(nmos::nc_manager_class_id)); + BST_REQUIRE(nmos::nc::is_manager(nmos::nc::make_class_id(nmos::nc_manager_class_id, { 1 }))); + + BST_REQUIRE_EQUAL(false, nmos::nc::is_device_manager({ })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_device_manager({ 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_device_manager({ 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_device_manager({ 1, 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_device_manager({ 1, 3, 2 })); + BST_REQUIRE(nmos::nc::is_device_manager(nmos::nc_device_manager_class_id)); + BST_REQUIRE(nmos::nc::is_device_manager(nmos::nc::make_class_id(nmos::nc_device_manager_class_id, { 1 }))); + + BST_REQUIRE_EQUAL(false, nmos::nc::is_class_manager({ })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_class_manager({ 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_class_manager({ 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_class_manager({ 1, 1, 1 })); + BST_REQUIRE_EQUAL(false, nmos::nc::is_class_manager({ 1, 3, 1 })); + BST_REQUIRE(nmos::nc::is_class_manager(nmos::nc_class_manager_class_id)); + BST_REQUIRE(nmos::nc::is_class_manager(nmos::nc::make_class_id(nmos::nc_class_manager_class_id, { 1 }))); } BST_TEST_CASE(testFindProperty) @@ -681,22 +681,22 @@ BST_TEST_CASE(testFindProperty) { // valid - find members property in NcBlock - auto property = nmos::find_property_descriptor(nc_block_members_property_id, nc_block_class_id, get_control_protocol_class_descriptor); + auto property = nmos::nc::find_property_descriptor(nc_block_members_property_id, nc_block_class_id, get_control_protocol_class_descriptor); BST_REQUIRE(!property.is_null()); } { // invalid - find members property in NcWorker - auto property = nmos::find_property_descriptor(nc_block_members_property_id, nc_worker_class_id, get_control_protocol_class_descriptor); + auto property = nmos::nc::find_property_descriptor(nc_block_members_property_id, nc_worker_class_id, get_control_protocol_class_descriptor); BST_REQUIRE(property.is_null()); } { // invalid - find unknown property in NcBlock - auto property = nmos::find_property_descriptor(invalid_property_id, nc_block_class_id, get_control_protocol_class_descriptor); + auto property = nmos::nc::find_property_descriptor(invalid_property_id, nc_block_class_id, get_control_protocol_class_descriptor); BST_REQUIRE(property.is_null()); } { // invalid - find unknown property in unknown class - auto property = nmos::find_property_descriptor(invalid_property_id, invalid_class_id, get_control_protocol_class_descriptor); + auto property = nmos::nc::find_property_descriptor(invalid_property_id, invalid_class_id, get_control_protocol_class_descriptor); BST_REQUIRE(property.is_null()); } } @@ -713,8 +713,8 @@ BST_TEST_CASE(testConstraints) // constraints // runtime constraints - const auto runtime_property_string_constraints = nmos::details::make_nc_property_constraints_string(property_string_id, 10, U("^[0-9]+$")); - const auto runtime_property_int32_constraints = nmos::details::make_nc_property_constraints_number(property_int32_id, 10, 1000, 1); + const auto runtime_property_string_constraints = nmos::nc::details::make_property_constraints_string(property_string_id, 10, U("^[0-9]+$")); + const auto runtime_property_int32_constraints = nmos::nc::details::make_property_constraints_number(property_int32_id, 10, 1000, 1); const auto runtime_property_constraints = value_of({ { runtime_property_string_constraints }, @@ -722,65 +722,65 @@ BST_TEST_CASE(testConstraints) }); // property constraints - const auto property_string_constraints = nmos::details::make_nc_parameter_constraints_string(5, U("^[a-z]+$")); - const auto property_int32_constraints = nmos::details::make_nc_parameter_constraints_number(50, 500, 5); + const auto property_string_constraints = nmos::nc::details::make_parameter_constraints_string(5, U("^[a-z]+$")); + const auto property_int32_constraints = nmos::nc::details::make_parameter_constraints_number(50, 500, 5); // datatype constraints - const auto datatype_string_constraints = nmos::details::make_nc_parameter_constraints_string(2, U("^[0-9a-z]+$")); - const auto datatype_int32_constraints = nmos::details::make_nc_parameter_constraints_number(100, 250, 10); + const auto datatype_string_constraints = nmos::nc::details::make_parameter_constraints_string(2, U("^[0-9a-z]+$")); + const auto datatype_int32_constraints = nmos::nc::details::make_parameter_constraints_number(100, 250, 10); // datatypes - const auto no_constraints_bool_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints boolean datatype"), U("NoConstraintsBoolean"), false, U("NcBoolean"), value::null()); - const auto no_constraints_int16_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints int16 datatype"), U("NoConstraintsInt16"), false, U("NcInt16"), value::null()); - const auto no_constraints_int32_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints int32 datatype"), U("NoConstraintsInt32"), false, U("NcInt32"), value::null()); - const auto no_constraints_int64_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints int64 datatype"), U("NoConstraintsInt64"), false, U("NcInt64"), value::null()); - const auto no_constraints_uint16_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints uint16 datatype"), U("NoConstraintsUint16"), false, U("NcUint16"), value::null()); - const auto no_constraints_uint32_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints uint32 datatype"), U("NoConstraintsUint32"), false, U("NcUint32"), value::null()); - const auto no_constraints_uint64_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints uint64 datatype"), U("NoConstraintsUint64"), false, U("NcUint64"), value::null()); - const auto no_constraints_float32_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints float32 datatype"), U("NoConstraintsFloat32"), false, U("NcFloat32"), value::null()); - const auto no_constraints_float64_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints float64 datatype"), U("NoConstraintsFloat64"), false, U("NcFloat64"), value::null()); - const auto no_constraints_string_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints string datatype"), U("NoConstraintsString"), false, U("NcString"), value::null()); - const auto with_constraints_string_datatype = nmos::details::make_nc_datatype_typedef(U("With constraints string datatype"), U("WithConstraintsString"), false, U("NcString"), datatype_string_constraints); - const auto with_constraints_int32_datatype = nmos::details::make_nc_datatype_typedef(U("With constraints int32 datatype"), U("WithConstraintsInt32"), false, U("NcInt32"), datatype_int32_constraints); - const auto no_constraints_int32_seq_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints int64 datatype"), U("NoConstraintsInt64"), true, U("NcInt32"), value::null()); - const auto no_constraints_string_seq_datatype = nmos::details::make_nc_datatype_typedef(U("No constraints string datatype"), U("NoConstraintsString"), true, U("NcString"), value::null()); + const auto no_constraints_bool_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints boolean datatype"), U("NoConstraintsBoolean"), false, U("NcBoolean"), value::null()); + const auto no_constraints_int16_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints int16 datatype"), U("NoConstraintsInt16"), false, U("NcInt16"), value::null()); + const auto no_constraints_int32_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints int32 datatype"), U("NoConstraintsInt32"), false, U("NcInt32"), value::null()); + const auto no_constraints_int64_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints int64 datatype"), U("NoConstraintsInt64"), false, U("NcInt64"), value::null()); + const auto no_constraints_uint16_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints uint16 datatype"), U("NoConstraintsUint16"), false, U("NcUint16"), value::null()); + const auto no_constraints_uint32_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints uint32 datatype"), U("NoConstraintsUint32"), false, U("NcUint32"), value::null()); + const auto no_constraints_uint64_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints uint64 datatype"), U("NoConstraintsUint64"), false, U("NcUint64"), value::null()); + const auto no_constraints_float32_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints float32 datatype"), U("NoConstraintsFloat32"), false, U("NcFloat32"), value::null()); + const auto no_constraints_float64_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints float64 datatype"), U("NoConstraintsFloat64"), false, U("NcFloat64"), value::null()); + const auto no_constraints_string_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints string datatype"), U("NoConstraintsString"), false, U("NcString"), value::null()); + const auto with_constraints_string_datatype = nmos::nc::details::make_datatype_typedef(U("With constraints string datatype"), U("WithConstraintsString"), false, U("NcString"), datatype_string_constraints); + const auto with_constraints_int32_datatype = nmos::nc::details::make_datatype_typedef(U("With constraints int32 datatype"), U("WithConstraintsInt32"), false, U("NcInt32"), datatype_int32_constraints); + const auto no_constraints_int32_seq_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints int64 datatype"), U("NoConstraintsInt64"), true, U("NcInt32"), value::null()); + const auto no_constraints_string_seq_datatype = nmos::nc::details::make_datatype_typedef(U("No constraints string datatype"), U("NoConstraintsString"), true, U("NcString"), value::null()); enum enum_value { foo, bar, baz }; auto items = value::array(); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("foo"), U("foo"), enum_value::foo)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("bar"), U("bar"), enum_value::bar)); - web::json::push_back(items, nmos::details::make_nc_enum_item_descriptor(U("baz"), U("baz"), enum_value::baz)); - const auto enum_datatype = nmos::details::make_nc_datatype_descriptor_enum(U("enum datatype"), U("enumDatatype"), items, value::null()); // no datatype constraints for enum datatype + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("foo"), U("foo"), enum_value::foo)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("bar"), U("bar"), enum_value::bar)); + web::json::push_back(items, nmos::nc::details::make_enum_item_descriptor(U("baz"), U("baz"), enum_value::baz)); + const auto enum_datatype = nmos::nc::details::make_datatype_descriptor_enum(U("enum datatype"), U("enumDatatype"), items, value::null()); // no datatype constraints for enum datatype auto simple_struct_fields = value::array(); - web::json::push_back(simple_struct_fields, nmos::details::make_nc_field_descriptor(U("simple enum property example"), U("simpleEnumProperty"), U("enumDatatype"), false, false, value::null())); // no field constraints for enum field, as it is already described by its type - web::json::push_back(simple_struct_fields, nmos::details::make_nc_field_descriptor(U("simple string property example"), U("simpleStringProperty"), U("NcString"), false, false, datatype_string_constraints)); - web::json::push_back(simple_struct_fields, nmos::details::make_nc_field_descriptor(U("simple number property example"), U("simpleNumberProperty"), U("NcInt32"), false, false, datatype_int32_constraints)); - web::json::push_back(simple_struct_fields, nmos::details::make_nc_field_descriptor(U("simle boolean property example"), U("simpleBooleanProperty"), U("NcBoolean"), false, false, value::null())); // no field constraints for boolean field, as it is already described by its type - const auto simple_struct_datatype = nmos::details::make_nc_datatype_descriptor_struct(U("simple struct datatype"), U("simpleStructDatatype"), simple_struct_fields, value::null()); // no datatype constraints for struct datatype + web::json::push_back(simple_struct_fields, nmos::nc::details::make_field_descriptor(U("simple enum property example"), U("simpleEnumProperty"), U("enumDatatype"), false, false, value::null())); // no field constraints for enum field, as it is already described by its type + web::json::push_back(simple_struct_fields, nmos::nc::details::make_field_descriptor(U("simple string property example"), U("simpleStringProperty"), U("NcString"), false, false, datatype_string_constraints)); + web::json::push_back(simple_struct_fields, nmos::nc::details::make_field_descriptor(U("simple number property example"), U("simpleNumberProperty"), U("NcInt32"), false, false, datatype_int32_constraints)); + web::json::push_back(simple_struct_fields, nmos::nc::details::make_field_descriptor(U("simle boolean property example"), U("simpleBooleanProperty"), U("NcBoolean"), false, false, value::null())); // no field constraints for boolean field, as it is already described by its type + const auto simple_struct_datatype = nmos::nc::details::make_datatype_descriptor_struct(U("simple struct datatype"), U("simpleStructDatatype"), simple_struct_fields, value::null()); // no datatype constraints for struct datatype auto fields = value::array(); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Enum property example"), U("enumProperty"), U("enumDatatype"), false, false, value::null())); // no field constraints for enum field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("String property example"), U("stringProperty"), U("NcString"), false, false, datatype_string_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Number property example"), U("numberProperty"), U("NcInt32"), false, false, datatype_int32_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Boolean property example"), U("booleanProperty"), U("NcBoolean"), false, false, value::null())); // no field constraints for boolean field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Struct property example"), U("structProperty"), U("simpleStructDatatype"), false, false, value::null())); // no datatype constraints for struct datatype - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Sequence enum property example"), U("sequenceEnumProperty"), U("enumDatatype"), false, true, value::null())); // no field constraints for enum field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Sequence string property example"), U("sequenceStringProperty"), U("NcString"), false, true, datatype_string_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Sequence number property example"), U("sequenceNumberProperty"), U("NcInt32"), false, true, datatype_int32_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Sequence boolean property example"), U("sequenceBooleanProperty"), U("NcBoolean"), false, true, value::null())); // no field constraints for boolean field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Sequence struct property example"), U("sequenceStructProperty"), U("simpleStructDatatype"), false, true, value::null())); // no field constraints for struct field - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Enum property example"), U("enumPropertyNullable"), U("enumDatatype"), true, false, value::null())); // no field constraints for enum field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable String property example"), U("stringPropertyNullable"), U("NcString"), true, false, datatype_string_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Number property example"), U("numberPropertyNullable"), U("NcInt32"), true, false, datatype_int32_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Boolean property example"), U("booleanPropertyNullable"), U("NcBoolean"), true, false, value::null())); // no field constraints for boolean field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Struct property example"), U("structPropertyNullable"), U("simpleStructDatatype"), true, false, value::null())); // no datatype constraints for struct datatype - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Sequence enum property example"), U("sequenceEnumPropertyNullable"), U("enumDatatype"), true, true, value::null())); // no field constraints for enum field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Sequence string property example"), U("sequenceStringPropertyNullable"), U("NcString"), true, true, datatype_string_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Sequence number property example"), U("sequenceNumberPropertyNullable"), U("NcInt32"), true, true, datatype_int32_constraints)); - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Sequence boolean property example"), U("sequenceBooleanPropertyNullable"), U("NcBoolean"), true, true, value::null())); // no field constraints for boolean field, as it is already described by its type - web::json::push_back(fields, nmos::details::make_nc_field_descriptor(U("Nullable Sequence struct property example"), U("sequenceStructPropertyNullable"), U("simpleStructDatatype"), true, true, value::null())); // no field constraints for struct field - const auto struct_datatype = nmos::details::make_nc_datatype_descriptor_struct(U("struct datatype"), U("structDatatype"), fields, value::null()); // no datatype constraints for struct datatype + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Enum property example"), U("enumProperty"), U("enumDatatype"), false, false, value::null())); // no field constraints for enum field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("String property example"), U("stringProperty"), U("NcString"), false, false, datatype_string_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Number property example"), U("numberProperty"), U("NcInt32"), false, false, datatype_int32_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Boolean property example"), U("booleanProperty"), U("NcBoolean"), false, false, value::null())); // no field constraints for boolean field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Struct property example"), U("structProperty"), U("simpleStructDatatype"), false, false, value::null())); // no datatype constraints for struct datatype + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Sequence enum property example"), U("sequenceEnumProperty"), U("enumDatatype"), false, true, value::null())); // no field constraints for enum field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Sequence string property example"), U("sequenceStringProperty"), U("NcString"), false, true, datatype_string_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Sequence number property example"), U("sequenceNumberProperty"), U("NcInt32"), false, true, datatype_int32_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Sequence boolean property example"), U("sequenceBooleanProperty"), U("NcBoolean"), false, true, value::null())); // no field constraints for boolean field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Sequence struct property example"), U("sequenceStructProperty"), U("simpleStructDatatype"), false, true, value::null())); // no field constraints for struct field + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Enum property example"), U("enumPropertyNullable"), U("enumDatatype"), true, false, value::null())); // no field constraints for enum field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable String property example"), U("stringPropertyNullable"), U("NcString"), true, false, datatype_string_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Number property example"), U("numberPropertyNullable"), U("NcInt32"), true, false, datatype_int32_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Boolean property example"), U("booleanPropertyNullable"), U("NcBoolean"), true, false, value::null())); // no field constraints for boolean field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Struct property example"), U("structPropertyNullable"), U("simpleStructDatatype"), true, false, value::null())); // no datatype constraints for struct datatype + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Sequence enum property example"), U("sequenceEnumPropertyNullable"), U("enumDatatype"), true, true, value::null())); // no field constraints for enum field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Sequence string property example"), U("sequenceStringPropertyNullable"), U("NcString"), true, true, datatype_string_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Sequence number property example"), U("sequenceNumberPropertyNullable"), U("NcInt32"), true, true, datatype_int32_constraints)); + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Sequence boolean property example"), U("sequenceBooleanPropertyNullable"), U("NcBoolean"), true, true, value::null())); // no field constraints for boolean field, as it is already described by its type + web::json::push_back(fields, nmos::nc::details::make_field_descriptor(U("Nullable Sequence struct property example"), U("sequenceStructPropertyNullable"), U("simpleStructDatatype"), true, true, value::null())); // no field constraints for struct field + const auto struct_datatype = nmos::nc::details::make_datatype_descriptor_struct(U("struct datatype"), U("structDatatype"), fields, value::null()); // no datatype constraints for struct datatype // setup datatypes in control_protocol_state nmos::experimental::control_protocol_state control_protocol_state; @@ -799,130 +799,130 @@ BST_TEST_CASE(testConstraints) control_protocol_state.insert(nmos::experimental::datatype_descriptor{ no_constraints_string_seq_datatype }); // test get_runtime_property_constraints - BST_REQUIRE_EQUAL(nmos::details::get_runtime_property_constraints(property_string_id, runtime_property_constraints), runtime_property_string_constraints); - BST_REQUIRE_EQUAL(nmos::details::get_runtime_property_constraints(property_int32_id, runtime_property_constraints), runtime_property_int32_constraints); - BST_REQUIRE_EQUAL(nmos::details::get_runtime_property_constraints(unknown_property_id, runtime_property_constraints), value::null()); + BST_REQUIRE_EQUAL(nmos::nc::details::get_runtime_property_constraints(property_string_id, runtime_property_constraints), runtime_property_string_constraints); + BST_REQUIRE_EQUAL(nmos::nc::details::get_runtime_property_constraints(property_int32_id, runtime_property_constraints), runtime_property_int32_constraints); + BST_REQUIRE_EQUAL(nmos::nc::details::get_runtime_property_constraints(unknown_property_id, runtime_property_constraints), value::null()); // string property constraints validation // runtime property constraints validation - const nmos::details::datatype_constraints_validation_parameters with_constraints_string_constraints_validation_params{ with_constraints_string_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value::string(U("1234567890")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("12345678901")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("123456789A")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890")), value::string(U("1234567890")) }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890")), value::string(U("12345678901")) }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890")), 1 }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters with_constraints_string_constraints_validation_params{ with_constraints_string_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value::string(U("1234567890")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("12345678901")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("123456789A")), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890")), value::string(U("1234567890")) }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890")), value::string(U("12345678901")) }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890")), 1 }), runtime_property_string_constraints, property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); // property constraints validation - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value::string(U("abcde")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("abcdef")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("abcd1")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ value::string(U("abcde")), value::string(U("abcde")) }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("abcde")), value::string(U("abcdef")) }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("abcde")), 1 }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value::string(U("abcde")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("abcdef")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("abcd1")), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("abcde")), value::string(U("abcde")) }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("abcde")), value::string(U("abcdef")) }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("abcde")), 1 }), value::null(), property_string_constraints, with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); // datatype constraints validation - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value::string(U("1a")), value::null(), value::null(), with_constraints_string_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("1a2")), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("1*")), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); - const nmos::details::datatype_constraints_validation_parameters no_constraints_string_constraints_validation_params{ no_constraints_string_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::null(), value::null(), no_constraints_string_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value::string(U("1a")), value::null(), value::null(), with_constraints_string_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("1a2")), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("1*")), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_string_constraints_validation_params{ no_constraints_string_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::null(), value::null(), no_constraints_string_constraints_validation_params)); // number property constraints validation // runtime property constraints validation - const nmos::details::datatype_constraints_validation_parameters with_constraints_int32_constraints_validation_params{ with_constraints_int32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(10, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(1000, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(9, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(1001, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ 10, 1000 }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 10, 1001 }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 10, value::string(U("a")) }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters with_constraints_int32_constraints_validation_params{ with_constraints_int32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(10, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(1000, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(9, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(1001, runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ 10, 1000 }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 10, 1001 }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 10, value::string(U("a")) }), runtime_property_int32_constraints, property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); // property constraints validation - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(50, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(500, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(45, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(505, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(499, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ 50, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 49, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 50, 501 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 45, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 50, value::string(U("a")) }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(50, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(500, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(45, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(505, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(499, value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ 50, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 49, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 50, 501 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 45, 500 }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 50, value::string(U("a")) }), value::null(), property_int32_constraints, with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); // datatype constraints validation - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(100, value::null(), value::null(), with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(250, value::null(), value::null(), with_constraints_int32_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(90, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(260, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(99, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(100, value::null(), value::null(), with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(250, value::null(), value::null(), with_constraints_int32_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(90, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(260, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(99, value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); // int16 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_int16_constraints_validation_params{ no_constraints_int16_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(int64_t(std::numeric_limits::min()) - 1, value::null(), value::null(), no_constraints_int16_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(int64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_int16_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int16_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int16_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_int16_constraints_validation_params{ no_constraints_int16_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(int64_t(std::numeric_limits::min()) - 1, value::null(), value::null(), no_constraints_int16_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(int64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_int16_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int16_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int16_constraints_validation_params)); // int32 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_int32_constraints_validation_params{ no_constraints_int32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(int64_t(std::numeric_limits::min()) - 1, value::null(), value::null(), no_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(int64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int32_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_int32_constraints_validation_params{ no_constraints_int32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(int64_t(std::numeric_limits::min()) - 1, value::null(), value::null(), no_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(int64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int32_constraints_validation_params)); // int64 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_int64_constraints_validation_params{ no_constraints_int64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int64_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_int64_constraints_validation_params{ no_constraints_int64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_int64_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params)); // uint16 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_uint16_constraints_validation_params{ no_constraints_uint16_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint16_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(uint64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_uint16_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint16_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint16_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_uint16_constraints_validation_params{ no_constraints_uint16_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint16_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(uint64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_uint16_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint16_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint16_constraints_validation_params)); // uint32 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_uint32_constraints_validation_params{ no_constraints_uint32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(uint64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_uint32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint32_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_uint32_constraints_validation_params{ no_constraints_uint32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(uint64_t(std::numeric_limits::max()) + 1, value::null(), value::null(), no_constraints_uint32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint32_constraints_validation_params)); // uint64 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_uint64_constraints_validation_params{ no_constraints_uint64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint64_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint64_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint64_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_uint64_constraints_validation_params{ no_constraints_uint64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(-1, value::null(), value::null(), no_constraints_uint64_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_int64_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_uint64_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_uint64_constraints_validation_params)); // float32 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_float32_constraints_validation_params{ no_constraints_float32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(std::numeric_limits::lowest(), value::null(), value::null(), no_constraints_float32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::lowest(), value::null(), value::null(), no_constraints_float32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(0.0, value::null(), value::null(), no_constraints_float32_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(-1000.0, value::null(), value::null(), no_constraints_float32_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_float32_constraints_validation_params{ no_constraints_float32_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::lowest(), value::null(), value::null(), no_constraints_float32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::lowest(), value::null(), value::null(), no_constraints_float32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(0.0, value::null(), value::null(), no_constraints_float32_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(-1000.0, value::null(), value::null(), no_constraints_float32_constraints_validation_params)); // float64 datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters no_constraints_float64_constraints_validation_params{ no_constraints_float64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(1000, value::null(), value::null(), no_constraints_float64_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(1000.0, value::null(), value::null(), no_constraints_float64_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_float64_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float64_constraints_validation_params)); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_float64_constraints_validation_params{ no_constraints_float64_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(1000, value::null(), value::null(), no_constraints_float64_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(1000.0, value::null(), value::null(), no_constraints_float64_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::min(), value::null(), value::null(), no_constraints_float64_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(std::numeric_limits::max(), value::null(), value::null(), no_constraints_float64_constraints_validation_params)); // enum property datatype constraints validation - const nmos::details::datatype_constraints_validation_parameters enum_constraints_validation_params{ enum_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(enum_value::foo, value::null(), value::null(), enum_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(4, value::null(), value::null(), enum_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters enum_constraints_validation_params{ enum_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(enum_value::foo, value::null(), value::null(), enum_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(4, value::null(), value::null(), enum_constraints_validation_params), nmos::control_protocol_exception); // invalid data vs primitive datatype constraints - const nmos::details::datatype_constraints_validation_parameters no_constraints_string_seq_constraints_validation_params{ no_constraints_string_seq_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 1 }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(1, value::null(), value::null(), no_constraints_string_seq_constraints_validation_params), nmos::control_protocol_exception); - const nmos::details::datatype_constraints_validation_parameters no_constraints_int32_seq_constraints_validation_params{ no_constraints_int32_seq_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ 1 }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_string_seq_constraints_validation_params{ no_constraints_string_seq_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 1 }), value::null(), value::null(), no_constraints_string_seq_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(1, value::null(), value::null(), no_constraints_string_seq_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters no_constraints_int32_seq_constraints_validation_params{ no_constraints_int32_seq_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ 1 }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ value::string(U("1234567890-abcde-!\"$%^&*()_+=")) }), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value::string(U("1234567890-abcde-!\"$%^&*()_+=")), value::null(), value::null(), no_constraints_int32_seq_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), with_constraints_int32_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(value_of({ 1, 2 }), value::null(), value::null(), with_constraints_string_constraints_validation_params), nmos::control_protocol_exception); // struct property datatype constraints validation const auto good_struct1 = value_of({ @@ -1833,29 +1833,29 @@ BST_TEST_CASE(testConstraints) { U("sequenceStructPropertyNullable"), value::null() } }); - const nmos::details::datatype_constraints_validation_parameters struct_constraints_validation_params{ struct_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(good_struct1, value::null(), value::null(), struct_constraints_validation_params)); - BST_REQUIRE_NO_THROW(nmos::details::constraints_validation(good_struct2, value::null(), value::null(), struct_constraints_validation_params)); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_4, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_5, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_5_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_5_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_5_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_6, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_6_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_6_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_6_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_7, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_7_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_7_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct2_7_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct3_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct3_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); - BST_REQUIRE_THROW(nmos::details::constraints_validation(bad_struct3_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + const nmos::nc::details::datatype_constraints_validation_parameters struct_constraints_validation_params{ struct_datatype, nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state) }; + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(good_struct1, value::null(), value::null(), struct_constraints_validation_params)); + BST_REQUIRE_NO_THROW(nmos::nc::details::constraints_validation(good_struct2, value::null(), value::null(), struct_constraints_validation_params)); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_4, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_5, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_5_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_5_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_5_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_6, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_6_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_6_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_6_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_7, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_7_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_7_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct2_7_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct3_1, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct3_2, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); + BST_REQUIRE_THROW(nmos::nc::details::constraints_validation(bad_struct3_3, value::null(), value::null(), struct_constraints_validation_params), nmos::control_protocol_exception); } diff --git a/Development/nmos/test/control_protocol_utils_test.cpp b/Development/nmos/test/control_protocol_utils_test.cpp index d8d92189c..ffdf7694b 100644 --- a/Development/nmos/test/control_protocol_utils_test.cpp +++ b/Development/nmos/test/control_protocol_utils_test.cpp @@ -32,25 +32,25 @@ BST_TEST_CASE(testGetSetControlProtocolProperty) // root, ClassManager auto class_manager_oid = ++root_block_oid; auto class_manager = nmos::make_class_manager(class_manager_oid, control_protocol_state); - nmos::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, class_manager); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); - auto oid = nmos::get_control_protocol_property(resources, class_manager_oid, nmos::nc_object_oid_property_id, get_control_protocol_class_descriptor, gate); + auto oid = nmos::nc::get_property(resources, class_manager_oid, nmos::nc_object_oid_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(class_manager_oid, static_cast(oid.as_integer())); - auto role = get_control_protocol_property(resources, class_manager_oid, nmos::nc_object_role_property_id, get_control_protocol_class_descriptor, gate); + auto role = nmos::nc::get_property(resources, class_manager_oid, nmos::nc_object_role_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(U("ClassManager"), role.as_string()); auto test_label = U("ThisIsATest"); - bool result = set_control_protocol_property_and_notify(resources, class_manager_oid, nmos::nc_object_user_label_property_id, web::json::value::string(test_label), get_control_protocol_class_descriptor, gate); + bool result = nmos::nc::set_property_and_notify(resources, class_manager_oid, nmos::nc_object_user_label_property_id, web::json::value::string(test_label), get_control_protocol_class_descriptor, gate); BST_REQUIRE(result); - auto label = get_control_protocol_property(resources, class_manager_oid, nmos::nc_object_user_label_property_id, get_control_protocol_class_descriptor, gate); + auto label = nmos::nc::get_property(resources, class_manager_oid, nmos::nc_object_user_label_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(test_label, label.as_string()); } @@ -78,8 +78,8 @@ BST_TEST_CASE(testSetReceiverMonitorStatuses) auto monitor = nmos::make_receiver_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); @@ -98,37 +98,37 @@ BST_TEST_CASE(testSetReceiverMonitorStatuses) auto stream_status_message = U("Stream status healthy"); auto expected_stream_status_transition_counter = 0; - BST_REQUIRE(set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status, actual_connection_status.as_integer()); - auto actual_connection_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status_message, actual_connection_status_message.as_string()); - auto actual_connection_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_connection_status_transition_counter, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_stream_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status, actual_stream_status.as_integer()); - auto actual_stream_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status_message, actual_stream_status_message.as_string()); - auto actual_stream_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_stream_status_transition_counter, actual_stream_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, overall_status.as_integer()); } { @@ -145,37 +145,37 @@ BST_TEST_CASE(testSetReceiverMonitorStatuses) auto stream_status_message = U("Stream status healthy"); auto expected_stream_status_transition_counter = 0; - BST_REQUIRE(set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status, actual_connection_status.as_integer()); - auto actual_connection_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status_message, actual_connection_status_message.as_string()); - auto actual_connection_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_connection_status_transition_counter, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_stream_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status, actual_stream_status.as_integer()); - auto actual_stream_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status_message, actual_stream_status_message.as_string()); - auto actual_stream_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_stream_status_transition_counter, actual_stream_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, overall_status.as_integer()); } { @@ -192,37 +192,37 @@ BST_TEST_CASE(testSetReceiverMonitorStatuses) auto stream_status_message = U("Stream status healthy"); auto expected_stream_status_transition_counter = 1; - BST_REQUIRE(set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status, actual_connection_status.as_integer()); - auto actual_connection_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status_message, actual_connection_status_message.as_string()); - auto actual_connection_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_connection_status_transition_counter, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_stream_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status, actual_stream_status.as_integer()); - auto actual_stream_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status_message, actual_stream_status_message.as_string()); - auto actual_stream_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_stream_status_transition_counter, actual_stream_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::partially_healthy, overall_status.as_integer()); } { @@ -239,37 +239,37 @@ BST_TEST_CASE(testSetReceiverMonitorStatuses) auto stream_status_message = U("Stream status healthy"); auto expected_stream_status_transition_counter = 1; - BST_REQUIRE(set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_connection_status(resources, monitor_oid, connection_status, connection_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_receiver_monitor_stream_status(resources, monitor_oid, stream_status, stream_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status, actual_connection_status.as_integer()); - auto actual_connection_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(connection_status_message, actual_connection_status_message.as_string()); - auto actual_connection_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_connection_status_transition_counter, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_stream_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status, actual_stream_status.as_integer()); - auto actual_stream_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(stream_status_message, actual_stream_status_message.as_string()); - auto actual_stream_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_stream_status_transition_counter, actual_stream_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::unhealthy, overall_status.as_integer()); } } @@ -297,21 +297,21 @@ BST_TEST_CASE(testSetSynchronizationSourceId) auto monitor = nmos::make_receiver_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); { utility::string_t sync_source_id = U("SYNCID"); - nmos::set_monitor_synchronization_source_id(resources, monitor_oid, sync_source_id, get_control_protocol_class_descriptor, gate); - auto actual_sync_source_id = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_synchronization_source_id_property_id, get_control_protocol_class_descriptor, gate); + nmos::nc::set_monitor_synchronization_source_id(resources, monitor_oid, sync_source_id, get_control_protocol_class_descriptor, gate); + auto actual_sync_source_id = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_synchronization_source_id_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(sync_source_id, actual_sync_source_id.as_string()); } { - nmos::set_monitor_synchronization_source_id(resources, monitor_oid, {}, get_control_protocol_class_descriptor, gate); - auto actual_sync_source_id = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_synchronization_source_id_property_id, get_control_protocol_class_descriptor, gate); + nmos::nc::set_monitor_synchronization_source_id(resources, monitor_oid, {}, get_control_protocol_class_descriptor, gate); + auto actual_sync_source_id = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_synchronization_source_id_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK(actual_sync_source_id.is_null()); } } @@ -328,10 +328,10 @@ BST_TEST_CASE(testActivateDeactivateReceiverMonitor) // check that the property changed handler gets called reset_monitor_called = true; - return nmos::details::make_nc_method_result({ nmos::nc_method_status::ok }); + return nmos::nc::details::make_method_result({ nmos::nc_method_status::ok }); }; - nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, reset_monitor, nullptr); + nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, reset_monitor); nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor = nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor = nmos::make_get_control_protocol_method_descriptor_handler(control_protocol_state); @@ -351,42 +351,42 @@ BST_TEST_CASE(testActivateDeactivateReceiverMonitor) auto monitor = nmos::make_receiver_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); { // autoResetCounterAndMessages will reset all counters and messages on activate, including calling back into application code - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_auto_reset_monitor_property_id, web::json::value::boolean(true), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_auto_reset_monitor_property_id, web::json::value::boolean(true), get_control_protocol_class_descriptor, gate); uint32_t transition_count = 10; // set transition counters - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); // Do activatation - nmos::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); + nmos::nc::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); // Check statuses - auto actual_stream_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::healthy, actual_stream_status.as_integer()); - auto actual_connection_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::healthy, actual_connection_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, actual_overall_status.as_integer()); // Check transition counters - auto actual_stream_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_stream_status_transition_counter.as_integer()); - auto actual_link_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_external_synchronization_status_transition_counter.as_integer()); // Check that reset_monitor handler was invoked @@ -394,48 +394,48 @@ BST_TEST_CASE(testActivateDeactivateReceiverMonitor) } { // Do deactivation - nmos::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); + nmos::nc::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); // Check statuses - auto actual_stream_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::inactive, actual_stream_status.as_integer()); - auto actual_connection_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::inactive, actual_connection_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, actual_overall_status.as_integer()); } { reset_monitor_called = false; // disable autoResetCounterAndMessages - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_auto_reset_monitor_property_id, web::json::value::boolean(false), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_auto_reset_monitor_property_id, web::json::value::boolean(false), get_control_protocol_class_descriptor, gate); int32_t transition_count = 10; // set transition counters - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); // Do activatation - nmos::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); + nmos::nc::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); // Check statuses - auto actual_stream_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::healthy, actual_stream_status.as_integer()); - auto actual_connection_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::healthy, actual_connection_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, actual_overall_status.as_integer()); // Check transition counters - auto actual_stream_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_stream_status_transition_counter.as_integer()); - auto actual_link_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_link_status_transition_counter.as_integer()); - auto actual_connection_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_connection_status_transition_counter.as_integer()); - auto actual_external_synchronization_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_external_synchronization_status_transition_counter.as_integer()); // Check that reset_monitor handler was NOT invoked @@ -443,14 +443,14 @@ BST_TEST_CASE(testActivateDeactivateReceiverMonitor) } { // Do deactivation - nmos::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); + nmos::nc::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); // Check statuses - auto actual_stream_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_stream_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_stream_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::inactive, actual_stream_status.as_integer()); - auto actual_connection_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_connection_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_receiver_monitor_connection_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_stream_status::status::inactive, actual_connection_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, actual_overall_status.as_integer()); } } @@ -482,8 +482,8 @@ BST_TEST_CASE(testSetSenderMonitorStatuses) auto monitor = nmos::make_sender_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); @@ -502,37 +502,37 @@ BST_TEST_CASE(testSetSenderMonitorStatuses) auto essence_status_message = U("essence status healthy"); auto expected_essence_status_transition_counter = 0; - BST_REQUIRE(set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status, actual_transmission_status.as_integer()); - auto actual_transmission_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status_message, actual_transmission_status_message.as_string()); - auto actual_transmission_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_transmission_status_transition_counter, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_essence_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status, actual_essence_status.as_integer()); - auto actual_essence_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status_message, actual_essence_status_message.as_string()); - auto actual_essence_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_essence_status_transition_counter, actual_essence_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, overall_status.as_integer()); } { @@ -549,37 +549,37 @@ BST_TEST_CASE(testSetSenderMonitorStatuses) auto essence_status_message = U("essence status healthy"); auto expected_essence_status_transition_counter = 0; - BST_REQUIRE(set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status, actual_transmission_status.as_integer()); - auto actual_transmission_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status_message, actual_transmission_status_message.as_string()); - auto actual_transmission_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_transmission_status_transition_counter, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_essence_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status, actual_essence_status.as_integer()); - auto actual_essence_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status_message, actual_essence_status_message.as_string()); - auto actual_essence_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_essence_status_transition_counter, actual_essence_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, overall_status.as_integer()); } { @@ -596,37 +596,37 @@ BST_TEST_CASE(testSetSenderMonitorStatuses) auto essence_status_message = U("essence status healthy"); auto expected_essence_status_transition_counter = 1; - BST_REQUIRE(set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status, actual_transmission_status.as_integer()); - auto actual_transmission_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status_message, actual_transmission_status_message.as_string()); - auto actual_transmission_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_transmission_status_transition_counter, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_essence_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status, actual_essence_status.as_integer()); - auto actual_essence_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status_message, actual_essence_status_message.as_string()); - auto actual_essence_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_essence_status_transition_counter, actual_essence_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::partially_healthy, overall_status.as_integer()); } { @@ -643,37 +643,37 @@ BST_TEST_CASE(testSetSenderMonitorStatuses) auto essence_status_message = U("essence status healthy"); auto expected_essence_status_transition_counter = 1; - BST_REQUIRE(set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); - BST_REQUIRE(set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_link_status(resources, monitor_oid, link_status, link_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_transmission_status(resources, monitor_oid, transmission_status, transmission_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_external_synchronization_status(resources, monitor_oid, external_synchronization_status, external_synchronization_status_message, get_control_protocol_class_descriptor, gate)); + BST_REQUIRE(nmos::nc::set_sender_monitor_essence_status(resources, monitor_oid, essence_status, essence_status_message, get_control_protocol_class_descriptor, gate)); - auto actual_link_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status, actual_link_status.as_integer()); - auto actual_link_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(link_status_message, actual_link_status_message.as_string()); - auto actual_link_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_link_status_transition_counter, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status, actual_transmission_status.as_integer()); - auto actual_transmission_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transmission_status_message, actual_transmission_status_message.as_string()); - auto actual_transmission_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_transmission_status_transition_counter, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status, actual_external_synchronization_status.as_integer()); - auto actual_external_synchronization_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(external_synchronization_status_message, actual_external_synchronization_status_message.as_string()); - auto actual_external_synchronization_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_external_synchronization_status_transition_counter, actual_external_synchronization_status_transition_counter.as_integer()); - auto actual_essence_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status, actual_essence_status.as_integer()); - auto actual_essence_status_message = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_message_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(essence_status_message, actual_essence_status_message.as_string()); - auto actual_essence_status_transition_counter = get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(expected_essence_status_transition_counter, actual_essence_status_transition_counter.as_integer()); - auto overall_status = get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::unhealthy, overall_status.as_integer()); } } @@ -690,10 +690,10 @@ BST_TEST_CASE(testActivateDeactivateSenderMonitor) // check that the property changed handler gets called reset_monitor_called = true; - return nmos::details::make_nc_method_result({ nmos::nc_method_status::ok }); + return nmos::nc::details::make_method_result({ nmos::nc_method_status::ok }); }; - nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, reset_monitor, nullptr); + nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, reset_monitor); nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); nmos::get_control_protocol_datatype_descriptor_handler get_control_protocol_datatype_descriptor = nmos::make_get_control_protocol_datatype_descriptor_handler(control_protocol_state); nmos::get_control_protocol_method_descriptor_handler get_control_protocol_method_descriptor = nmos::make_get_control_protocol_method_descriptor_handler(control_protocol_state); @@ -713,42 +713,42 @@ BST_TEST_CASE(testActivateDeactivateSenderMonitor) auto monitor = nmos::make_sender_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); { // autoResetCounterAndMessages will reset all counters and messages on activate, including calling back into application code - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_auto_reset_monitor_property_id, web::json::value::boolean(true), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_auto_reset_monitor_property_id, web::json::value::boolean(true), get_control_protocol_class_descriptor, gate); uint32_t transition_count = 10; // set transition counters - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); // Do activatation - nmos::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); + nmos::nc::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); // Check statuses - auto actual_essence_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::healthy, actual_essence_status.as_integer()); - auto actual_transmission_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::healthy, actual_transmission_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, actual_overall_status.as_integer()); // Check transition counters - auto actual_essence_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_essence_status_transition_counter.as_integer()); - auto actual_link_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(0, actual_external_synchronization_status_transition_counter.as_integer()); // Check that reset_monitor handler was invoked @@ -756,48 +756,48 @@ BST_TEST_CASE(testActivateDeactivateSenderMonitor) } { // Do deactivation - nmos::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); + nmos::nc::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); // Check statuses - auto actual_essence_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::inactive, actual_essence_status.as_integer()); - auto actual_transmission_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::inactive, actual_transmission_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, actual_overall_status.as_integer()); } { reset_monitor_called = false; // disable autoResetCounterAndMessages - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_auto_reset_monitor_property_id, web::json::value::boolean(false), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_auto_reset_monitor_property_id, web::json::value::boolean(false), get_control_protocol_class_descriptor, gate); int32_t transition_count = 10; // set transition counters - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); - nmos::set_control_protocol_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); + nmos::nc::set_property_and_notify(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, web::json::value::number(transition_count), get_control_protocol_class_descriptor, gate); // Do activatation - nmos::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); + nmos::nc::activate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, get_control_protocol_method_descriptor, gate); // Check statuses - auto actual_essence_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::healthy, actual_essence_status.as_integer()); - auto actual_transmission_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::healthy, actual_transmission_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::healthy, actual_overall_status.as_integer()); // Check transition counters - auto actual_essence_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_essence_status_transition_counter.as_integer()); - auto actual_link_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_link_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_link_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_link_status_transition_counter.as_integer()); - auto actual_transmission_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_transmission_status_transition_counter.as_integer()); - auto actual_external_synchronization_status_transition_counter = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); + auto actual_external_synchronization_status_transition_counter = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_external_synchronization_status_transition_counter_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(transition_count, actual_external_synchronization_status_transition_counter.as_integer()); // Check that reset_monitor handler was NOT invoked @@ -805,14 +805,14 @@ BST_TEST_CASE(testActivateDeactivateSenderMonitor) } { // Do deactivation - nmos::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); + nmos::nc::deactivate_monitor(resources, monitor_oid, get_control_protocol_class_descriptor, gate); // Check statuses - auto actual_essence_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_essence_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_essence_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::inactive, actual_essence_status.as_integer()); - auto actual_transmission_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_transmission_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_sender_monitor_transmission_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_essence_status::status::inactive, actual_transmission_status.as_integer()); - auto actual_overall_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); + auto actual_overall_status = nmos::nc::get_property(resources, monitor_oid, nmos::nc_status_monitor_overall_status_property_id, get_control_protocol_class_descriptor, gate); BST_CHECK_EQUAL(nmos::nc_overall_status::status::inactive, actual_overall_status.as_integer()); } } @@ -830,7 +830,7 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // check that the property changed handler gets called reset_monitor_called = true; - return nmos::details::make_nc_method_result({nmos::nc_method_status::ok}); + return nmos::nc::details::make_method_result({nmos::nc_method_status::ok}); }; nmos::monitor_status_pending_handler monitor_status_pending = [&]() @@ -838,7 +838,7 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) monitor_status_pending_called = true; }; - nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, reset_monitor, nullptr); + nmos::experimental::control_protocol_state control_protocol_state(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, reset_monitor); nmos::get_control_protocol_class_descriptor_handler get_control_protocol_class_descriptor = nmos::make_get_control_protocol_class_descriptor_handler(control_protocol_state); boost::iostreams::stream< boost::iostreams::null_sink > null_ostream((boost::iostreams::null_sink())); @@ -856,8 +856,8 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) auto monitor = nmos::make_receiver_monitor(monitor_oid, true, root_block_oid, U("monitor"), U("monitor"), U("monitor"), web::json::value::null()); - nmos::push_back(root_block, class_manager); - nmos::push_back(root_block, monitor); + nmos::nc::push_back(root_block, class_manager); + nmos::nc::push_back(root_block, monitor); insert_resource(resources, std::move(root_block)); insert_resource(resources, std::move(class_manager)); insert_resource(resources, std::move(monitor)); @@ -865,10 +865,10 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) { // Status should change with no delay to Inactive // Initial stream status of healthy - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); // Set stream stream status to inactive at t=0 - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, 0, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, 0, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -881,7 +881,7 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to change with no delay to inactive BST_CHECK_EQUAL(0, actual_value.as_integer()); } @@ -889,12 +889,12 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // Status should change to Inactive with no delay // Initial stream status of healthy and monitor activation time to t=0 - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); long long current_time = 1; // Set stream stream status to inactive at t=1 - within initial status_reporting_delay period - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, 0, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, 0, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -908,11 +908,11 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) BST_REQUIRE(success); // Expected status to change with no delay to inactive - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); BST_CHECK_EQUAL(0, actual_value.as_integer()); // Expected status pending received time to be 0 i.e. not pending - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(0, actual_time.as_integer()); } { @@ -920,13 +920,13 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // Any unhealthy status updates should be pending // // Initial stream status of healthy and monitor activation time to t=0 - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); long long current_time = 1; int expected_status = 3; // Set stream stream status to unhealthy at t=1 - within initial status_reporting_delay period - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -939,27 +939,27 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to remain healthy BST_CHECK_EQUAL(1, actual_value.as_integer()); // Expected status pending received time to be current time i.e. pending - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(current_time, actual_time.as_integer()); // Expected status pending to be expected status i.e. pending - const auto actual_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); + const auto actual_status = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); BST_CHECK_EQUAL(expected_status, actual_status.as_integer()); } { // Status updates from healthy to unhealthy after initial reporting delay should happen with no delay // // Initial stream status of healthy and monitor activation time to t=0 - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, 1, gate); long long current_time = 5; int expected_status = 3; // Set stream status to unhealthy at t=5 - after initial status_reporting_delay period - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -972,24 +972,24 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to be unhealthy BST_CHECK_EQUAL(expected_status, actual_value.as_integer()); // Expected status pending received time to be 0 i.e. not pending - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(0, actual_time.as_integer()); } { // Status updates from partailly unhealthy to unhealthy after initial reporting delay should happen with no delay // // Initial stream status of partially unhealthy and monitor activation time to t=0 - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, 2, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, 2, gate); long long current_time = 5; int expected_status = 3; // Set stream stream status to unhealthy at t=5 - after initial status_reporting_delay period - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -1002,11 +1002,11 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to go to unhealthy without delay BST_CHECK_EQUAL(expected_status, actual_value.as_integer()); // Expected status pending received time to be 0 i.e. not pending - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(0, actual_time.as_integer()); } { @@ -1014,13 +1014,13 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // // Initial stream status of partially unhealthy and monitor activation time to t=0 int initial_status = 2; - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); long long current_time = 5; int expected_status = 1; // Set stream stream status to healthy at t=5 - after initial status_reporting_delay period - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -1033,14 +1033,14 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to stay partially unhealthy BST_CHECK_EQUAL(initial_status, actual_value.as_integer()); // Expected status pending received time to be current time i.e. pending - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(current_time, actual_time.as_integer()); // Expected status pending to be expected status i.e. healthy - const auto actual_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); + const auto actual_status = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); BST_CHECK_EQUAL(expected_status, actual_status.as_integer()); } { @@ -1048,18 +1048,18 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // // Initial stream status of partially unhealthy and monitor activation time to t=0 int initial_status = 2; - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); long long current_time = 9; int expected_status = 1; long long received_time = 8; // Status already pending with healthy state at t=8 - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, expected_status, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, received_time, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, expected_status, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, received_time, gate); // Set stream stream status to healthy at t=9 - healthy status already pending - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, expected_status, U(""), nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -1072,14 +1072,14 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to stay unhealthy BST_CHECK_EQUAL(initial_status, actual_value.as_integer()); // Expected status pending received time to be the original pending time - const auto actual_time = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); + const auto actual_time = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending_received_time, gate); BST_CHECK_EQUAL(received_time, actual_time.as_integer()); // Expected status pending to be expected status i.e. healthy - const auto actual_status = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); + const auto actual_status = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_pending, gate); BST_CHECK_EQUAL(expected_status, actual_status.as_integer()); } { @@ -1088,15 +1088,15 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) // Initial stream status of healthy and monitor activation time to t=0 int initial_status = 1; utility::string_t initial_status_message = U("initial status message"); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); - nmos::set_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_message, web::json::value::string(initial_status_message), gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::monitor_activation_time, 0, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status, initial_status, gate); + nmos::nc::set_property(resources, monitor_oid, nmos::fields::nc::stream_status_message, web::json::value::string(initial_status_message), gate); long long current_time = 9; utility::string_t updated_status_message = U("updated status message"); // Maintain healthy status but change the status message - bool success = nmos::details::set_monitor_status_with_delay(resources, monitor_oid, initial_status, updated_status_message, + bool success = nmos::nc::details::set_monitor_status_with_delay(resources, monitor_oid, initial_status, updated_status_message, nmos::nc_receiver_monitor_stream_status_property_id, nmos::nc_receiver_monitor_stream_status_message_property_id, nmos::nc_receiver_monitor_stream_status_transition_counter_property_id, @@ -1109,11 +1109,71 @@ BST_TEST_CASE(testSetMonitorStatusWithDelay) gate); BST_REQUIRE(success); - const auto actual_value = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); + const auto actual_value = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status, gate); // Expected status to stay healthy BST_CHECK_EQUAL(initial_status, actual_value.as_integer()); - const auto actual_status_message = nmos::get_control_protocol_property(resources, monitor_oid, nmos::fields::nc::stream_status_message, gate); + const auto actual_status_message = nmos::nc::get_property(resources, monitor_oid, nmos::fields::nc::stream_status_message, gate); // Expected message to have been updated BST_CHECK_EQUAL(updated_status_message, actual_status_message.as_string()); } -} \ No newline at end of file +} + +//////////////////////////////////////////////////////////////////////////////////////////// +BST_TEST_CASE(testFindTouchpointResources) +{ + using web::json::value_of; + using web::json::value; + + const auto touchpoint1_id = U("1000"); + auto touchpoint1_data = value_of({ + { nmos::fields::id, touchpoint1_id }, + { nmos::fields::version, nmos::make_version() }, + { nmos::fields::label, U("touchpoint1") }, + { nmos::fields::description, U("touchpoint1") }, + { nmos::fields::tags, value::null() } + }); + nmos::resource touchpoint1 = { nmos::is04_versions::v1_3, nmos::types::node, std::move(touchpoint1_data), false }; + + const auto touchpoint2_id = U("1001"); + auto touchpoint2_data = value_of({ + { nmos::fields::id, touchpoint2_id }, + { nmos::fields::version, nmos::make_version() }, + { nmos::fields::label, U("touchpoint2") }, + { nmos::fields::description, U("touchpoint2") }, + { nmos::fields::tags, value::null() } + }); + nmos::resource touchpoint2 = { nmos::is04_versions::v1_3, nmos::types::node, std::move(touchpoint2_data), false }; + + const auto non_existant_id = U("1002"); + + // Create Device Model + auto oid = nmos::root_block_oid; + auto monitor1 = nmos::make_receiver_monitor(++oid, true, nmos::root_block_oid, U("mon1"), U("monitor 1"), U("monitor 1"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, touchpoint1_id})} })); + auto monitor2 = nmos::make_receiver_monitor(++oid, true, nmos::root_block_oid, U("mon2"), U("monitor 2"), U("monitor 2"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, touchpoint2_id})} })); + auto monitor3 = nmos::make_receiver_monitor(++oid, true, nmos::root_block_oid, U("mon3"), U("monitor 3"), U("monitor 3"), value_of({ {nmos::nc::details::make_touchpoint_nmos({nmos::ncp_touchpoint_resource_types::receiver, non_existant_id})} })); + + nmos::resources resources; + // Insert dummy NMOS resources + insert_resource(resources, std::move(touchpoint1)); + insert_resource(resources, std::move(touchpoint2)); + + { + const auto& touchpoint = nmos::nc::find_touchpoint_resource(resources, monitor1); + + BST_CHECK_EQUAL(touchpoint1_id, nmos::fields::id(touchpoint->data)); + BST_CHECK_EQUAL(U("touchpoint1"), nmos::fields::label(touchpoint->data)); + BST_CHECK_EQUAL(U("touchpoint1"), nmos::fields::description(touchpoint->data)); + } + { + const auto& touchpoint = nmos::nc::find_touchpoint_resource(resources, monitor2); + + BST_CHECK_EQUAL(touchpoint2_id, nmos::fields::id(touchpoint->data)); + BST_CHECK_EQUAL(U("touchpoint2"), nmos::fields::label(touchpoint->data)); + BST_CHECK_EQUAL(U("touchpoint2"), nmos::fields::description(touchpoint->data)); + } + { + const auto& touchpoint = nmos::nc::find_touchpoint_resource(resources, monitor3); + + BST_CHECK_EQUAL(touchpoint, resources.end()); + } +} diff --git a/Development/nmos/type.h b/Development/nmos/type.h index 69a334eef..98a69252f 100644 --- a/Development/nmos/type.h +++ b/Development/nmos/type.h @@ -50,10 +50,10 @@ namespace nmos const type nc_receiver_monitor{ U("nc_receiver_monitor") }; const type nc_sender_monitor{ U("nc_sender_monitor") }; const type nc_ident_beacon{ U("nc_ident_beacon") }; + const type nc_bulk_properties_manager{ U("nc_bulk_properties_manager") }; // all Control Protocol resource types const std::vector all_nc{ nmos::types::nc_block, nmos::types::nc_worker, nmos::types::nc_manager, nmos::types::nc_device_manager, nmos::types::nc_class_manager, nmos::types::nc_status_monitor, nmos::types::nc_ident_beacon }; - } } diff --git a/Development/third_party/is-14/README.md b/Development/third_party/is-14/README.md new file mode 100644 index 000000000..a6d9c931f --- /dev/null +++ b/Development/third_party/is-14/README.md @@ -0,0 +1,9 @@ +# AMWA IS-14 NMOS Device Configuration Specification + +This directory contains files from the [AMWA NMOS Device Configuration Specification](https://github.com/AMWA-TV/is-14), in particular tagged versions of the JSON schemas used by the API specifications. + +Original source code: + +- (c) AMWA 2024 +- Licensed under the Apache License, Version 2.0; http://www.apache.org/licenses/LICENSE-2.0 + diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/base.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/base.json new file mode 100644 index 000000000..d8c791bec --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/base.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API base resource", + "title": "Configuration API base resource", + "items": { + "type": "string", + "enum": [ + "rolePaths/" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-get-response.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-get-response.json new file mode 100644 index 000000000..698a1b358 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-get-response.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "Returns a NcMethodResultBulkPropertiesHolder from a bulkProperties GET", + "title": "NcMethodResultBulkPropertiesHolder" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-request.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-request.json new file mode 100644 index 000000000..bf711c5b3 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-request.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "PATCH request body for invoking ValidateSetPropertiesByPath method on NcBulkPropertiesManager", + "title": "Bulk properties Validate request", + "required": [ + "arguments" + ], + "properties": { + "arguments": { + "type": "object", + "description": "Method arguments. The rolePath is offered in the URL and is not part of these arguments", + "properties": { + "dataSet": { + "type": "object", + "description": "NcBulkPropertiesHolder datatype" + }, + "recurse": { + "type": "boolean" + }, + "restoreMode": { + "type": "integer", + "description": "numeric representation of NcRestoreMode enum options" + } + } + } + } +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-response.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-response.json new file mode 100644 index 000000000..1642eb0d5 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-patch-response.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "Returns a NcMethodResultObjectPropertiesSetValidation from a bulkProperties PATCH", + "title": "NcMethodResultObjectPropertiesSetValidation" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-request.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-request.json new file mode 100644 index 000000000..75a1694e3 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-request.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "PUT request body for invoking SetPropertiesByPath method on NcBulkPropertiesManager", + "title": "Bulk properties Set request", + "required": [ + "arguments" + ], + "properties": { + "arguments": { + "type": "object", + "description": "Method arguments. The rolePath is offered in the URL and is not part of these arguments", + "properties": { + "dataSet": { + "type": "object", + "description": "NcBulkPropertiesHolder datatype" + }, + "recurse": { + "type": "boolean" + }, + "restoreMode": { + "type": "integer", + "description": "numeric representation of NcRestoreMode enum options" + } + } + } + } +} \ No newline at end of file diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-response.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-response.json new file mode 100644 index 000000000..6b5885c01 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/bulkProperties-put-response.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "Returns a NcMethodResultObjectPropertiesSetValidation from a bulkProperties PUT", + "title": "NcMethodResultObjectPropertiesSetValidation" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/descriptor-get.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/descriptor-get.json new file mode 100644 index 000000000..28f76a40e --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/descriptor-get.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "NcMethodResultClassDescriptor", + "title": "NcMethodResultClassDescriptor" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-request.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-request.json new file mode 100644 index 000000000..ecf42c21b --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-request.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "PATCH request body for invoking a method", + "title": "Invoke method body", + "required": [ + "arguments" + ], + "properties": { + "arguments": { + "type": "object", + "description": "Method arguments. Arguments are specified as nested properties inside this object and their types are dictated by the specific MS-05-02 model for the method targeted. For methods which do not have arguments defined the object is an empty object." + } + } +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-response.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-response.json new file mode 100644 index 000000000..c74183f9a --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/method-patch-response.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "NcMethodResult", + "title": "NcMethodResult" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/methods-base.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/methods-base.json new file mode 100644 index 000000000..6b9222b57 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/methods-base.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API /rolePaths/{rolePath}/methods base", + "title": "Configuration API /rolePaths/{rolePath}/methods base", + "items": { + "type": "string", + "pattern": "^[0-9]+m[0-9]+" + }, + "uniqueItems": true +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/ms05-error.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/ms05-error.json new file mode 100644 index 000000000..a7996e064 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/ms05-error.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "Object of type NcMethodResultError or a type derived from NcMethodResultError", + "title": "Request error" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/properties-base.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/properties-base.json new file mode 100644 index 000000000..72c3f5488 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/properties-base.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API /rolePaths/{rolePath}/properties base", + "title": "Configuration API /rolePaths/{rolePath}/properties base", + "items": { + "type": "string", + "pattern": "^[0-9]+p[0-9]+" + }, + "uniqueItems": true +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/property-descriptor.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-descriptor.json new file mode 100644 index 000000000..e564e0fd0 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-descriptor.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "NcMethodResultDatatypeDescriptor", + "title": "NcMethodResultDatatypeDescriptor" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-get.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-get.json new file mode 100644 index 000000000..0f018830a --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-get.json @@ -0,0 +1,5 @@ +{ + "type": "object", + "description": "NcMethodResultPropertyValue with the contents of the property", + "title": "NcMethodResultPropertyValue" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-request.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-request.json new file mode 100644 index 000000000..fdbd07d40 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-request.json @@ -0,0 +1,37 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "PUT request body for modyfing a property", + "title": "Modify property body", + "required": [ + "value" + ], + "properties": { + "value": { + "description": "New property value. The actual type is determined by the property's MS-05-02 datatype.", + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "integer" + }, + { + "type": "object" + }, + { + "type": "array" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + } +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-response.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-response.json new file mode 100644 index 000000000..c74183f9a --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/property-value-put-response.json @@ -0,0 +1,6 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "description": "NcMethodResult", + "title": "NcMethodResult" +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/property.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/property.json new file mode 100644 index 000000000..0a53e5103 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/property.json @@ -0,0 +1,16 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API /rolePaths/{rolePath}/properties/{propertyId}", + "title": "Configuration API /rolePaths/{rolePath}/properties/{propertyId}", + "items": { + "type": "string", + "enum": [ + "descriptor/", + "value/" + ] + }, + "minItems": 2, + "maxItems": 2, + "uniqueItems": true +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePath.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePath.json new file mode 100644 index 000000000..03cf62b42 --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePath.json @@ -0,0 +1,18 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API /rolePaths/{rolePath}", + "title": "Configuration API /rolePaths/{rolePath}", + "items": { + "type": "string", + "enum": [ + "bulkProperties/", + "descriptor/", + "methods/", + "properties/" + ] + }, + "minItems": 4, + "maxItems": 4, + "uniqueItems": true +} diff --git a/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePaths-base.json b/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePaths-base.json new file mode 100644 index 000000000..de6d1c0bc --- /dev/null +++ b/Development/third_party/is-14/v1.0.x/APIs/schemas/rolePaths-base.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "array", + "description": "Describes the Configuration API /rolePaths base", + "title": "Configuration API /rolePaths base", + "items": { + "type": "string" + }, + "uniqueItems": true +} diff --git a/README.md b/README.md index 8a1795b2a..25967f0e8 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ This repository contains an implementation of the [AMWA Networked Media Open Spe - [AMWA IS-09 NMOS System Parameters Specification](https://specs.amwa.tv/is-09/) (originally defined in JT-NM TR-1001-1:2018 Annex A) - [AMWA IS-10 NMOS Authorization Specification](https://specs.amwa.tv/is-10/) - [AMWA IS-12 AMWA IS-12 NMOS Control Protocol](https://specs.amwa.tv/is-12/) +- [AMWA IS-14 AMWA IS-14 NMOS Device Configuration Specification](https://specs.amwa.tv/is-14/) - [AMWA BCP-002-01 NMOS Grouping Recommendations - Natural Grouping](https://specs.amwa.tv/bcp-002-01/) - [AMWA BCP-002-02 NMOS Asset Distinguishing Information](https://specs.amwa.tv/bcp-002-02/) - [AMWA BCP-003-01 Secure Communication in NMOS Systems](https://specs.amwa.tv/bcp-003-01/) @@ -95,6 +96,7 @@ The [AMWA NMOS API Testing Tool](https://github.com/AMWA-TV/nmos-testing) is aut [![IS-09-01][IS-09-01-badge]][IS-09-01-sheet] [![IS-09-02][IS-09-02-badge]][IS-09-02-sheet] [![IS-12-01][IS-12-01-badge]][IS-12-01-sheet] +[![IS-14-01][IS-14-01-badge]][IS-14-01-sheet] [BCP-003-01-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/BCP-003-01.svg [BCP-006-01-01-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/BCP-006-01-01.svg @@ -112,6 +114,7 @@ The [AMWA NMOS API Testing Tool](https://github.com/AMWA-TV/nmos-testing) is aut [IS-09-01-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/IS-09-01.svg [IS-09-02-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/IS-09-02.svg [IS-12-01-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/IS-12-01.svg +[IS-14-01-badge]: https://raw.githubusercontent.com/sony/nmos-cpp/badges/IS-14-01.svg [BCP-003-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit#gid=468090822 [BCP-006-01-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit?gid=1835994800 [BCP-008-01-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit?gid=1290589116 @@ -128,6 +131,7 @@ The [AMWA NMOS API Testing Tool](https://github.com/AMWA-TV/nmos-testing) is aut [IS-09-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit#gid=919453974 [IS-09-02-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit#gid=2135469955 [IS-12-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit?gid=1026699230 +[IS-14-01-sheet]: https://docs.google.com/spreadsheets/d/1UgZoI0lGCMDn9-zssccf2Azil3WN6jogroMT8Wh6H64/edit?gid=342707873 ### Recent Activity @@ -135,7 +139,10 @@ The implementation is designed to be extended. Development is ongoing, following Recent activity on the project (newest first): -- Added support for the IS-12 NMOS Control Protocol +- Added support for IS-14 NMOS Device Configuration +- Added support for BCP-008-01 Receiver Status Monitoring +- Added support for BCP-008-02 Sender Status Monitoring +- Added support for IS-12 NMOS Control Protocol - Update to Conan 2; Conan 1.X is no longer supported - Added support for IS-10 Authorization - Added support for HSTS and OCSP stapling diff --git a/Sandbox/run_nmos_testing.sh b/Sandbox/run_nmos_testing.sh index bebf84b3d..12fa14b62 100755 --- a/Sandbox/run_nmos_testing.sh +++ b/Sandbox/run_nmos_testing.sh @@ -37,6 +37,7 @@ expected_disabled_IS_09_02=0 expected_disabled_IS_04_02=0 expected_disabled_IS_09_01=0 expected_disabled_IS_12_01=0 +expected_disabled_IS_14_01=1 expected_disabled_BCP_006_01_01=0 expected_disabled_BCP_008_01_01=0 expected_disabled_BCP_008_02_01=0 @@ -149,6 +150,7 @@ else # test_33, test_33_1 (( expected_disabled_IS_04_02+=16 )) (( expected_disabled_IS_09_01+=7 )) + (( expected_disabled_IS_14_01+=7 )) (( expected_disabled_BCP_006_01_01+=7 )) fi @@ -220,6 +222,8 @@ do_run_test IS-09-02 $expected_disabled_IS_09_02 --host "${host}" null --port 0 do_run_test IS-12-01 $expected_disabled_IS_12_01 --host "${host}" "${host}" null null --port 1080 1082 0 0 --version v1.3 v1.0 v1.0 v1.0 --urlpath null x-nmos/ncp/v1.0 null null +do_run_test IS-14-01 $expected_disabled_IS_14_01 --host "${host}" "${host}" null null --port 1080 1080 0 0 --version v1.3 v1.0 v1.0 v1.0 --selector null null null null --ignore test_ms05_05 + do_run_test BCP-006-01-01 $expected_disabled_BCP_006_01_01 --host "${host}" --port 1080 --version v1.3 do_run_test BCP-008-01-01 $expected_disabled_BCP_008_01_01 --host "${host}" "${host}" "${host}" null --port 1080 1080 1082 0 --version v1.3 v1.1 v1.0 v1.0 --urlpath null null x-nmos/ncp/v1.0 null