Webthing-CPP: a modern CPP implementation of the WebThings API


LCOV - code coverage report
Current view: top level - webthing - webthing.hpp (source / functions) Coverage Total Hit
Test: filtered_coverage.info Lines: 97.3 % 75 73
Test Date: 2025-03-15 12:45:00 Functions: 98.3 % 59 58

            Line data    Source code
       1              : // Webthing-CPP
       2              : // SPDX-FileCopyrightText: 2023-present Benno Waldhauer
       3              : // SPDX-License-Identifier: MIT
       4              : 
       5              : #pragma once
       6              : 
       7              : #include <bw/webthing/action.hpp>
       8              : #include <bw/webthing/errors.hpp>
       9              : #include <bw/webthing/event.hpp>
      10              : #include <bw/webthing/json.hpp>
      11              : #include <bw/webthing/json_validator.hpp>
      12              : #include <bw/webthing/mdns.hpp>
      13              : #include <bw/webthing/property.hpp>
      14              : #include <bw/webthing/server.hpp>
      15              : #include <bw/webthing/thing.hpp>
      16              : #include <bw/webthing/utils.hpp>
      17              : #include <bw/webthing/value.hpp>
      18              : #include <bw/webthing/version.hpp>
      19              : 
      20              : namespace bw::webthing
      21              : {
      22              : 
      23           22 : inline std::shared_ptr<Thing> make_thing(std::string id, std::string title, std::vector<std::string> type, std::string description)
      24              : {
      25           22 :     if(id == "")
      26            7 :         id = "uuid:" + generate_uuid();
      27           22 :     if(title == "")
      28           10 :         title = id;
      29           22 :     return std::make_shared<Thing>(id, title, type, description);
      30              : }
      31              : 
      32           22 : inline std::shared_ptr<Thing> make_thing(std::string id = "", std::string title = "", std::string type = "", std::string description = "")
      33              : {
      34           22 :     std::vector<std::string> types;
      35           22 :     if(type != "")
      36            1 :         types.push_back(type);
      37           44 :     return make_thing(id, title, types, description);
      38           22 : }
      39              : 
      40           18 : template<class T> std::shared_ptr<Value<T>> make_value(T initial_value,  typename Value<T>::ValueForwarder value_forwarder = nullptr)
      41              : {
      42           18 :     return std::make_shared<Value<T>>(initial_value, std::move(value_forwarder));
      43              : }
      44              : 
      45            3 : template<class T> std::shared_ptr<Value<T>> make_unknown_value(typename Value<T>::ValueForwarder value_forwarder = nullptr)
      46              : {
      47            3 :     return std::make_shared<Value<T>>(std::nullopt, std::move(value_forwarder));
      48              : }
      49              : 
      50           17 : template<class T> std::shared_ptr<Property<T>> link_property(Thing* thing, std::string name, std::shared_ptr<Value<T>> value, json metadata = json::object())
      51              : {
      52           51 :     PropertyChangedCallback property_changed_callback = [thing](json property_status){
      53           17 :         thing->property_notify(property_status);
      54              :     };
      55           17 :     auto property = std::make_shared<Property<T>>(std::move(property_changed_callback), name, value, metadata);
      56           17 :     thing->add_property(property);
      57           34 :     return property;
      58           17 : }
      59              : 
      60            1 : template<class T> std::shared_ptr<Property<T>> link_property(Thing* thing, std::string name, T intial_value, json metadata = json::object())
      61              : {
      62            1 :     return link_property(thing, name, make_value(intial_value), metadata);
      63              : }
      64              : 
      65           16 : template<class T> std::shared_ptr<Property<T>> link_property(std::shared_ptr<Thing> thing, std::string name, std::shared_ptr<Value<T>> value, json metadata = json::object())
      66              : {
      67           16 :    return link_property(thing.get(), name, value, metadata);   
      68              : }
      69              : 
      70           15 : template<class T> std::shared_ptr<Property<T>> link_property(std::shared_ptr<Thing> thing, std::string name, T intial_value, json metadata = json::object())
      71              : {
      72           15 :     return link_property(thing, name, make_value(intial_value), metadata);
      73              : }
      74              : 
      75            6 : inline void link_event(Thing* thing, std::string name, json metadata = json::object())
      76              : {
      77            6 :     thing->add_available_event(name, metadata);
      78            6 : }
      79              : 
      80            6 : inline void link_event(std::shared_ptr<Thing> thing, std::string name, json metadata = json::object())
      81              : {
      82            6 :     link_event(thing.get(), name, metadata);
      83            6 : }
      84              : 
      85            8 : inline std::shared_ptr<Event> emit_event(Thing* thing, std::string name, std::optional<json> data = std::nullopt)
      86              : {
      87            8 :     auto event = std::make_shared<Event>(thing, name, data);
      88            8 :     thing->add_event(event);
      89            8 :     return event;
      90            0 : }
      91              : 
      92            8 : inline std::shared_ptr<Event> emit_event(std::shared_ptr<Thing> thing, std::string name, std::optional<json> data = std::nullopt)
      93              : {
      94            8 :     return emit_event(thing.get(), name, data);
      95              : }
      96              : 
      97              : inline std::shared_ptr<Event> emit_event(Thing* thing, Event&& event)
      98              : {
      99              :     auto event_ptr = std::make_shared<Event>(event);
     100              :     thing->add_event(event_ptr);
     101              :     return event_ptr;
     102              : }
     103              : 
     104            1 : inline std::shared_ptr<Event> emit_event(std::shared_ptr<Thing> thing, Event&& event)
     105              : {
     106            1 :     auto event_ptr = std::make_shared<Event>(event);
     107            1 :     thing->add_event(event_ptr);
     108            1 :     return event_ptr;
     109            0 : }
     110              : 
     111            5 : inline void link_action(Thing* thing, std::string action_name, json metadata,
     112              :     std::function<void()> perform_action = nullptr, std::function<void()> cancel_action = nullptr)
     113              : {
     114           10 :     Thing::ActionSupplier action_supplier = [thing, action_name, perform_action, cancel_action](auto input){
     115              :         return std::make_shared<Action>(generate_uuid(), 
     116           10 :             make_action_behavior(thing, perform_action, cancel_action),
     117            5 :             action_name, input);
     118            5 :     };
     119              : 
     120            5 :     thing->add_available_action(action_name, metadata, std::move(action_supplier));
     121            5 : }
     122              : 
     123            3 : inline void link_action(std::shared_ptr<Thing> thing, std::string action_name, json metadata,
     124              :     std::function<void()> perform_action = nullptr, std::function<void()> cancel_action = nullptr)
     125              : {
     126            3 :     link_action(thing.get(), action_name, metadata, perform_action, cancel_action);
     127            3 : }
     128              : 
     129            1 : inline void link_action(Thing* thing, std::string action_name, 
     130              :     std::function<void()> perform_action = nullptr, std::function<void()> cancel_action = nullptr)
     131              : {
     132            1 :     link_action(thing, action_name, json::object(), perform_action, cancel_action);
     133            1 : }
     134              : 
     135              : inline void link_action(std::shared_ptr<Thing> thing, std::string action_name, 
     136              :     std::function<void()> perform_action = nullptr, std::function<void()> cancel_action = nullptr)
     137              : {
     138              :     link_action(thing.get(), action_name, perform_action, cancel_action);
     139              : }
     140              : 
     141            5 : template<class ActionImpl> void link_action(Thing* thing, std::string action_name, json metadata = json::object())
     142              : {
     143              :     static_assert(has_perform_action<ActionImpl>::value, "ActionImpl does not have a perform_action method");
     144              : 
     145            5 :     Thing::ActionSupplier action_supplier;
     146              :     if constexpr(std::is_constructible_v<ActionImpl, Thing*, std::optional<json>>)
     147              :     {
     148            6 :         action_supplier = [thing](auto input){
     149            3 :             return std::make_shared<ActionImpl>(thing, input);
     150              :         };
     151              :     }
     152              :     else if constexpr(std::is_constructible_v<ActionImpl, Thing*, json>)
     153              :     {
     154            4 :         action_supplier = [thing](auto input){
     155            3 :             if(!input)
     156            3 :                 throw ActionError("Input must not be empty for this Action type");
     157            4 :             return std::make_shared<ActionImpl>(thing, input.value_or(json()));
     158              :         };
     159              :     }
     160              :     else if constexpr(std::is_constructible_v<ActionImpl, Thing*>)
     161              :     {
     162            2 :         action_supplier = [thing](auto input){
     163            1 :             return std::make_shared<ActionImpl>(thing);
     164              :         };
     165              :     }
     166              :     else
     167              :     {
     168              :         throw std::runtime_error("ActionImpl does not provide a suitable constructor");
     169              :     }
     170              : 
     171            5 :     thing->add_available_action(action_name, metadata, std::move(action_supplier));
     172            5 : }
     173              : 
     174            4 : template<class ActionImpl> void link_action(std::shared_ptr<Thing> thing, std::string action_name, json metadata = json::object())
     175              : {
     176            4 :     link_action<ActionImpl>(thing.get(), action_name, metadata);
     177            4 : }
     178              : 
     179              : } // bw::webthing
        

Generated by: LCOV version 2.0-1