|
2 | 2 | #include <memory> |
3 | 3 | #include <sstream> |
4 | 4 |
|
5 | | -#include <boost/log/trivial.hpp> |
6 | | - |
7 | 5 | #include <viam/sdk/common/exception.hpp> |
8 | 6 | #include <viam/sdk/common/proto_value.hpp> |
| 7 | +#include <viam/sdk/components/sensor.hpp> |
9 | 8 | #include <viam/sdk/config/resource.hpp> |
10 | | -#include <viam/sdk/module/module.hpp> |
11 | 9 | #include <viam/sdk/module/service.hpp> |
12 | 10 | #include <viam/sdk/registry/registry.hpp> |
13 | 11 | #include <viam/sdk/resource/reconfigurable.hpp> |
14 | | -#include <viam/sdk/resource/resource.hpp> |
15 | | -#include <viam/sdk/rpc/dial.hpp> |
16 | | -#include <viam/sdk/rpc/server.hpp> |
17 | | -#include <viam/sdk/services/generic.hpp> |
18 | | -#include <viam/sdk/services/service.hpp> |
19 | 12 |
|
20 | 13 | using namespace viam::sdk; |
21 | 14 |
|
22 | | -// Printer is a modular resource that can print a to_print value to STDOUT when |
23 | | -// a DoCommand request is received or when reconfiguring. The to_print value |
24 | | -// must be provided as an attribute in the config. |
25 | | -class Printer : public GenericService, public Reconfigurable { |
| 15 | +// Implements a trivial sensor component, constructed with a ResourceConfig that specifies a |
| 16 | +// "multiplier" value which is then returned as the only sensor reading. |
| 17 | +class MySensor : public Sensor, public Reconfigurable { |
26 | 18 | public: |
27 | | - void reconfigure(const Dependencies& deps, const ResourceConfig& cfg) { |
28 | | - std::cout << "Printer " << Resource::name() << " is reconfiguring" << std::endl; |
29 | | - for (auto& dep : deps) { |
30 | | - std::cout << "dependency: " << dep.first.to_string() << std::endl; |
31 | | - } |
32 | | - to_print_ = find_to_print(cfg); |
33 | | - std::cout << "Printer " << Resource::name() << " will now print " << to_print_ << std::endl; |
| 19 | + MySensor(const ResourceConfig& cfg) : Sensor(cfg.name()) { |
| 20 | + this->reconfigure({}, cfg); |
34 | 21 | } |
35 | 22 |
|
36 | | - Printer(Dependencies deps, ResourceConfig cfg) : GenericService(cfg.name()) { |
37 | | - std::cout << "Creating Printer " + Resource::name() << std::endl; |
38 | | - to_print_ = find_to_print(cfg); |
39 | | - std::cout << "Printer " << Resource::name() << " will print " << to_print_ << std::endl; |
40 | | - } |
| 23 | + static std::vector<std::string> validate(const ResourceConfig&); |
41 | 24 |
|
42 | | - ProtoStruct do_command(const ProtoStruct& command) { |
43 | | - std::cout << "Received DoCommand request for Printer " << Resource::name() << std::endl; |
44 | | - std::cout << "Printer " << Resource::name() << " has printed " << to_print_ << std::endl; |
45 | | - return command; |
| 25 | + void reconfigure(const Dependencies&, const ResourceConfig&) override; |
| 26 | + |
| 27 | + ProtoStruct do_command(const ProtoStruct&) override; |
| 28 | + |
| 29 | + std::vector<GeometryConfig> get_geometries(const ProtoStruct&) override { |
| 30 | + throw Exception("method not supported"); |
46 | 31 | } |
47 | 32 |
|
48 | | - static std::string find_to_print(ResourceConfig cfg) { |
49 | | - auto& printer_name = cfg.name(); |
50 | | - auto to_print = cfg.attributes().find("to_print"); |
51 | | - if (to_print == cfg.attributes().end()) { |
52 | | - std::ostringstream buffer; |
53 | | - buffer << printer_name << ": Required parameter `to_print` not found in configuration"; |
54 | | - throw std::invalid_argument(buffer.str()); |
| 33 | + ProtoStruct get_readings(const ProtoStruct&) override; |
| 34 | + |
| 35 | + private: |
| 36 | + double multiplier_{1.0}; |
| 37 | +}; |
| 38 | + |
| 39 | +std::vector<std::string> MySensor::validate(const ResourceConfig& cfg) { |
| 40 | + auto itr = cfg.attributes().find("multiplier"); |
| 41 | + if (itr != cfg.attributes().end()) { |
| 42 | + const double* multiplier = itr->second.get<double>(); |
| 43 | + if (!multiplier) { |
| 44 | + throw Exception("multiplier must be a number value"); |
55 | 45 | } |
56 | | - const auto* const to_print_string = to_print->second.get<std::string>(); |
57 | | - if (!to_print_string || to_print_string->empty()) { |
58 | | - std::ostringstream buffer; |
59 | | - buffer << printer_name |
60 | | - << ": Required non-empty string parameter `to_print` is either not a string " |
61 | | - "or is an empty string"; |
62 | | - throw std::invalid_argument(buffer.str()); |
| 46 | + |
| 47 | + if (*multiplier == 0.0) { |
| 48 | + throw Exception("multiplier cannot be zero"); |
63 | 49 | } |
64 | | - return *to_print_string; |
65 | 50 | } |
66 | 51 |
|
67 | | - private: |
68 | | - std::string to_print_; |
69 | | -}; |
| 52 | + return {}; |
| 53 | +} |
| 54 | + |
| 55 | +void MySensor::reconfigure(const Dependencies&, const ResourceConfig& cfg) { |
| 56 | + auto itr = cfg.attributes().find("multiplier"); |
| 57 | + if (itr != cfg.attributes().end()) { |
| 58 | + const double* multiplier = itr->second.get<double>(); |
| 59 | + if (multiplier) { |
| 60 | + multiplier_ = *multiplier; |
| 61 | + } |
| 62 | + } |
| 63 | +} |
| 64 | + |
| 65 | +ProtoStruct MySensor::do_command(const ProtoStruct& command) { |
| 66 | + for (const auto& entry : command) { |
| 67 | + std::cout << "Command entry " << entry.first; |
| 68 | + } |
| 69 | + |
| 70 | + return command; |
| 71 | +} |
| 72 | + |
| 73 | +ProtoStruct MySensor::get_readings(const ProtoStruct&) { |
| 74 | + return {{"signal", multiplier_}}; |
| 75 | +} |
70 | 76 |
|
71 | 77 | int main(int argc, char** argv) try { |
72 | | - API generic = API::get<GenericService>(); |
73 | | - Model m("viam", "generic", "printer"); |
| 78 | + Model mysensor_model("viam", "sensor", "mysensor"); |
74 | 79 |
|
75 | 80 | std::shared_ptr<ModelRegistration> mr = std::make_shared<ModelRegistration>( |
76 | | - generic, |
77 | | - m, |
78 | | - [](Dependencies deps, ResourceConfig cfg) { return std::make_unique<Printer>(deps, cfg); }, |
79 | | - // Custom validation can be done by specifying a validate function like |
80 | | - // this one. Validate functions can `throw` exceptions that will be |
81 | | - // returned to the parent through gRPC. Validate functions can also return |
82 | | - // a vector of strings representing the implicit dependencies of the resource. |
83 | | - [](ResourceConfig cfg) -> std::vector<std::string> { |
84 | | - // find_to_print will throw an error if the `to_print` attribute |
85 | | - // is missing, is not a string or is an empty string. |
86 | | - Printer::find_to_print(cfg); |
87 | | - return {}; |
88 | | - }); |
| 81 | + API::get<Sensor>(), |
| 82 | + mysensor_model, |
| 83 | + [](Dependencies, ResourceConfig cfg) { return std::make_unique<MySensor>(cfg); }, |
| 84 | + &MySensor::validate); |
89 | 85 |
|
90 | 86 | std::vector<std::shared_ptr<ModelRegistration>> mrs = {mr}; |
91 | 87 | auto my_mod = std::make_shared<ModuleService>(argc, argv, mrs); |
|
0 commit comments