Skip to content

Commit

Permalink
Merge pull request #4 from bw-hro/integer-input-for-double-properties
Browse files Browse the repository at this point in the history
Integer input for double properties
  • Loading branch information
bw-hro authored Dec 2, 2023
2 parents 977bae9 + 0ac4fa7 commit 84a0852
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 18 deletions.
29 changes: 15 additions & 14 deletions include/bw/webthing/property.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,22 @@ json property_status_message(const Property<T>& property)
});
}


template<class T>
json property_value_object(const Property<T>& property)
{

auto value_as_json = property.get_value() ? json(*property.get_value()) : json();
return json({{property.get_name(), value_as_json}});
}


class PropertyBase
{
public:

PropertyBase(std::string name, json metadata)
PropertyBase(std::string name, json metadata, bool wraps_double)
: name(name)
, metadata(metadata)
{
, wraps_double(wraps_double)
{
if(this->metadata.type() != json::value_t::object)
throw PropertyError("Only json::object is allowed as meta data.");

Expand Down Expand Up @@ -74,8 +72,8 @@ class PropertyBase

std::string get_name() const
{
return name;
}
return name;
}

json get_metadata() const
{
Expand All @@ -90,6 +88,9 @@ class PropertyBase
template<class T> void set_value(T value)
{
try{
if(wraps_double && !std::is_same_v<T, double>)
return set_value(try_static_cast<double>(value));

auto property = dynamic_cast<Property<T>&>(*this);
property.set_value(value);
}
Expand All @@ -100,10 +101,11 @@ class PropertyBase
}

protected:
std::string name;
std::string name;
std::string href_prefix;
std::string href;
json metadata;
const bool wraps_double;
};

typedef std::function<void (json)> PropertyChangedCallback;
Expand All @@ -112,16 +114,15 @@ template<class T>
class Property : public PropertyBase
{
public:

Property(PropertyChangedCallback changed_callback, std::string name, std::shared_ptr<Value<T>> value, json metadata = json::object())
: PropertyBase(name, metadata)
Property(PropertyChangedCallback changed_callback, std::string name, std::shared_ptr<Value<T>> value, json metadata = json::object())
: PropertyBase(name, metadata, std::is_same_v<T, double>)
, property_change_callback(changed_callback)
, value(value)
{
{
// Add value change observer to notify the Thing about a property change.
if(property_change_callback)
this->value->add_observer([&](auto v){property_change_callback(property_status_message(*this));});
}
}

// Validate new proptery value before setting it.
void validate_value(const T& value) const
Expand Down Expand Up @@ -164,7 +165,7 @@ class Property : public PropertyBase
}

private:
std::shared_ptr<Value<T>> value;
std::shared_ptr<Value<T>> value;
PropertyChangedCallback property_change_callback;
};

Expand Down
14 changes: 14 additions & 0 deletions include/bw/webthing/utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,5 +261,19 @@ struct fix_uuid_scoped

#define FIXED_UUID_SCOPED(uuid) auto fixed_uuid_scope_guard = fix_uuid_scoped(uuid);

// try to static_cast from a type to another, throws std::bad_cast on error
template<class To, class From>
inline To try_static_cast(const From& value)
{
try
{
if constexpr (std::is_convertible_v<From, To>)
return static_cast<To>(value);
}
catch(...)
{}

throw std::bad_cast();
}

} // bw::webthing
26 changes: 25 additions & 1 deletion test/unit-test/property_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ TEST_CASE( "Properties can wrap json values", "[property]" )

TEST_CASE( "Properties can only be changed from external when provided values are valid", "[property]" )
{
SECTION( "Number" )
SECTION( "Integer" )
{
auto val = create_value(666);
json property_description = {{"type", "integer"}, {"minimum", 555}};
Expand All @@ -128,10 +128,34 @@ TEST_CASE( "Properties can only be changed from external when provided values ar
);
REQUIRE( *property->get_value<int>() == 666 );

REQUIRE_THROWS_MATCHES(property->set_value(777.0), PropertyError,
MessageContains("value type not matching")
);
REQUIRE( *property->get_value<int>() == 666 );

property->set_value(1000);
REQUIRE( *property->get_value<int>() == 1000 );
}

SECTION( "Number" )
{
auto val = create_value(666.0);
json property_description = {{"type", "number"}, {"minimum", 555.0}};
auto property = create_proptery("writeable-number-prop", val, property_description);

REQUIRE_THROWS_MATCHES(property->set_value(123.0), PropertyError,
MessageContains("Invalid property") &&
MessageContains("below minimum of 555")
);
REQUIRE( *property->get_value<double>() == 666 );

property->set_value(1000.123);
REQUIRE( *property->get_value<double>() == 1000.123 );

property->set_value(777);
REQUIRE( *property->get_value<double>() == 777 );
}

SECTION( "String" )
{
auto val = create_value(std::string("first-string-value"));
Expand Down
2 changes: 1 addition & 1 deletion vcpkg-no-ssl.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webthing-cpp",
"version-string": "1.0",
"version-string": "1.0.2",
"dependencies": [
"catch2",
"json-schema-validator",
Expand Down
2 changes: 1 addition & 1 deletion vcpkg-with-ssl.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webthing-cpp",
"version-string": "1.0",
"version-string": "1.0.2",
"dependencies": [
"catch2",
"json-schema-validator",
Expand Down
2 changes: 1 addition & 1 deletion vcpkg.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "webthing-cpp",
"version-string": "1.0",
"version-string": "1.0.2",
"dependencies": [
"catch2",
"json-schema-validator",
Expand Down

0 comments on commit 84a0852

Please sign in to comment.