thing.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. #ifndef THING_H
  2. #define THING_H
  3. #include <string>
  4. #include <map>
  5. #include <functional>
  6. #include <vector>
  7. #include <stdexcept>
  8. #include <cJSON.h>
  9. namespace iot {
  10. enum ValueType {
  11. kValueTypeBoolean,
  12. kValueTypeNumber,
  13. kValueTypeString
  14. };
  15. class Property {
  16. private:
  17. std::string name_;
  18. std::string description_;
  19. ValueType type_;
  20. std::function<bool()> boolean_getter_;
  21. std::function<int()> number_getter_;
  22. std::function<std::string()> string_getter_;
  23. public:
  24. Property(const std::string& name, const std::string& description, std::function<bool()> getter) :
  25. name_(name), description_(description), type_(kValueTypeBoolean), boolean_getter_(getter) {}
  26. Property(const std::string& name, const std::string& description, std::function<int()> getter) :
  27. name_(name), description_(description), type_(kValueTypeNumber), number_getter_(getter) {}
  28. Property(const std::string& name, const std::string& description, std::function<std::string()> getter) :
  29. name_(name), description_(description), type_(kValueTypeString), string_getter_(getter) {}
  30. const std::string& name() const { return name_; }
  31. const std::string& description() const { return description_; }
  32. ValueType type() const { return type_; }
  33. bool boolean() const { return boolean_getter_(); }
  34. int number() const { return number_getter_(); }
  35. std::string string() const { return string_getter_(); }
  36. std::string GetDescriptorJson() {
  37. std::string json_str = "{";
  38. json_str += "\"description\":\"" + description_ + "\",";
  39. if (type_ == kValueTypeBoolean) {
  40. json_str += "\"type\":\"boolean\"";
  41. } else if (type_ == kValueTypeNumber) {
  42. json_str += "\"type\":\"number\"";
  43. } else if (type_ == kValueTypeString) {
  44. json_str += "\"type\":\"string\"";
  45. }
  46. json_str += "}";
  47. return json_str;
  48. }
  49. std::string GetStateJson() {
  50. if (type_ == kValueTypeBoolean) {
  51. return boolean_getter_() ? "true" : "false";
  52. } else if (type_ == kValueTypeNumber) {
  53. return std::to_string(number_getter_());
  54. } else if (type_ == kValueTypeString) {
  55. return "\"" + string_getter_() + "\"";
  56. }
  57. return "null";
  58. }
  59. };
  60. class PropertyList {
  61. private:
  62. std::vector<Property> properties_;
  63. public:
  64. PropertyList() = default;
  65. PropertyList(const std::vector<Property>& properties) : properties_(properties) {}
  66. void AddBooleanProperty(const std::string& name, const std::string& description, std::function<bool()> getter) {
  67. properties_.push_back(Property(name, description, getter));
  68. }
  69. void AddNumberProperty(const std::string& name, const std::string& description, std::function<int()> getter) {
  70. properties_.push_back(Property(name, description, getter));
  71. }
  72. void AddStringProperty(const std::string& name, const std::string& description, std::function<std::string()> getter) {
  73. properties_.push_back(Property(name, description, getter));
  74. }
  75. const Property& operator[](const std::string& name) const {
  76. for (auto& property : properties_) {
  77. if (property.name() == name) {
  78. return property;
  79. }
  80. }
  81. throw std::runtime_error("Property not found: " + name);
  82. }
  83. std::string GetDescriptorJson() {
  84. std::string json_str = "{";
  85. for (auto& property : properties_) {
  86. json_str += "\"" + property.name() + "\":" + property.GetDescriptorJson() + ",";
  87. }
  88. if (json_str.back() == ',') {
  89. json_str.pop_back();
  90. }
  91. json_str += "}";
  92. return json_str;
  93. }
  94. std::string GetStateJson() {
  95. std::string json_str = "{";
  96. for (auto& property : properties_) {
  97. json_str += "\"" + property.name() + "\":" + property.GetStateJson() + ",";
  98. }
  99. if (json_str.back() == ',') {
  100. json_str.pop_back();
  101. }
  102. json_str += "}";
  103. return json_str;
  104. }
  105. };
  106. class Parameter {
  107. private:
  108. std::string name_;
  109. std::string description_;
  110. ValueType type_;
  111. bool required_;
  112. bool boolean_;
  113. int number_;
  114. std::string string_;
  115. public:
  116. Parameter(const std::string& name, const std::string& description, ValueType type, bool required = true) :
  117. name_(name), description_(description), type_(type), required_(required) {}
  118. const std::string& name() const { return name_; }
  119. const std::string& description() const { return description_; }
  120. ValueType type() const { return type_; }
  121. bool required() const { return required_; }
  122. bool boolean() const { return boolean_; }
  123. int number() const { return number_; }
  124. const std::string& string() const { return string_; }
  125. void set_boolean(bool value) { boolean_ = value; }
  126. void set_number(int value) { number_ = value; }
  127. void set_string(const std::string& value) { string_ = value; }
  128. std::string GetDescriptorJson() {
  129. std::string json_str = "{";
  130. json_str += "\"description\":\"" + description_ + "\",";
  131. if (type_ == kValueTypeBoolean) {
  132. json_str += "\"type\":\"boolean\"";
  133. } else if (type_ == kValueTypeNumber) {
  134. json_str += "\"type\":\"number\"";
  135. } else if (type_ == kValueTypeString) {
  136. json_str += "\"type\":\"string\"";
  137. }
  138. json_str += "}";
  139. return json_str;
  140. }
  141. };
  142. class ParameterList {
  143. private:
  144. std::vector<Parameter> parameters_;
  145. public:
  146. ParameterList() = default;
  147. ParameterList(const std::vector<Parameter>& parameters) : parameters_(parameters) {}
  148. void AddParameter(const Parameter& parameter) {
  149. parameters_.push_back(parameter);
  150. }
  151. const Parameter& operator[](const std::string& name) const {
  152. for (auto& parameter : parameters_) {
  153. if (parameter.name() == name) {
  154. return parameter;
  155. }
  156. }
  157. throw std::runtime_error("Parameter not found: " + name);
  158. }
  159. // iterator
  160. auto begin() { return parameters_.begin(); }
  161. auto end() { return parameters_.end(); }
  162. std::string GetDescriptorJson() {
  163. std::string json_str = "{";
  164. for (auto& parameter : parameters_) {
  165. json_str += "\"" + parameter.name() + "\":" + parameter.GetDescriptorJson() + ",";
  166. }
  167. if (json_str.back() == ',') {
  168. json_str.pop_back();
  169. }
  170. json_str += "}";
  171. return json_str;
  172. }
  173. };
  174. class Method {
  175. private:
  176. std::string name_;
  177. std::string description_;
  178. ParameterList parameters_;
  179. std::function<void(const ParameterList&)> callback_;
  180. public:
  181. Method(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) :
  182. name_(name), description_(description), parameters_(parameters), callback_(callback) {}
  183. const std::string& name() const { return name_; }
  184. const std::string& description() const { return description_; }
  185. ParameterList& parameters() { return parameters_; }
  186. std::string GetDescriptorJson() {
  187. std::string json_str = "{";
  188. json_str += "\"description\":\"" + description_ + "\",";
  189. json_str += "\"parameters\":" + parameters_.GetDescriptorJson();
  190. json_str += "}";
  191. return json_str;
  192. }
  193. void Invoke() {
  194. callback_(parameters_);
  195. }
  196. };
  197. class MethodList {
  198. private:
  199. std::vector<Method> methods_;
  200. public:
  201. MethodList() = default;
  202. MethodList(const std::vector<Method>& methods) : methods_(methods) {}
  203. void AddMethod(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) {
  204. methods_.push_back(Method(name, description, parameters, callback));
  205. }
  206. Method& operator[](const std::string& name) {
  207. for (auto& method : methods_) {
  208. if (method.name() == name) {
  209. return method;
  210. }
  211. }
  212. throw std::runtime_error("Method not found: " + name);
  213. }
  214. std::string GetDescriptorJson() {
  215. std::string json_str = "{";
  216. for (auto& method : methods_) {
  217. json_str += "\"" + method.name() + "\":" + method.GetDescriptorJson() + ",";
  218. }
  219. if (json_str.back() == ',') {
  220. json_str.pop_back();
  221. }
  222. json_str += "}";
  223. return json_str;
  224. }
  225. };
  226. class Thing {
  227. public:
  228. Thing(const std::string& name, const std::string& description) :
  229. name_(name), description_(description) {}
  230. virtual ~Thing() = default;
  231. virtual std::string GetDescriptorJson();
  232. virtual std::string GetStateJson();
  233. virtual void Invoke(const cJSON* command);
  234. const std::string& name() const { return name_; }
  235. const std::string& description() const { return description_; }
  236. protected:
  237. PropertyList properties_;
  238. MethodList methods_;
  239. private:
  240. std::string name_;
  241. std::string description_;
  242. };
  243. void RegisterThing(const std::string& type, std::function<Thing*()> creator);
  244. Thing* CreateThing(const std::string& type);
  245. #define DECLARE_THING(TypeName) \
  246. static iot::Thing* Create##TypeName() { \
  247. return new iot::TypeName(); \
  248. } \
  249. static bool Register##TypeNameHelper = []() { \
  250. RegisterThing(#TypeName, Create##TypeName); \
  251. return true; \
  252. }();
  253. } // namespace iot
  254. #endif // THING_H