ESP32原生开发——小智AI解析3(thing.cc)

头文件

#ifndef THING_H
#define THING_H

#include <string>
#include <map>
#include <functional>
#include <vector>
#include <stdexcept>
#include <cJSON.h>

命名空间

namespace iot {

命名空间内的enum枚举类型

enum ValueType {
    kValueTypeBoolean,
    kValueTypeNumber,
    kValueTypeString
};

内涵的几个类

class Property {

私有成员变量

private:
    std::string name_;
    std::string description_;
    ValueType type_;
    std::function<bool()> boolean_getter_;
    std::function<int()> number_getter_;
    std::function<std::string()> string_getter_;

重载过的构造函数

public:
    Property(const std::string& name, const std::string& description, std::function<bool()> getter) :
        name_(name), description_(description), type_(kValueTypeBoolean), boolean_getter_(getter) {}
    Property(const std::string& name, const std::string& description, std::function<int()> getter) :
        name_(name), description_(description), type_(kValueTypeNumber), number_getter_(getter) {}
    Property(const std::string& name, const std::string& description, std::function<std::string()> getter) :
        name_(name), description_(description), type_(kValueTypeString), string_getter_(getter) {}

name description type 名称描述类型

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ValueType type() const { return type_; }

    bool boolean() const { return boolean_getter_(); }
    int number() const { return number_getter_(); }
    std::string string() const { return string_getter_(); }

获取描述json字符串

    //布尔类型属性:{"description":"这是一个布尔属性","type":"boolean"}
    //数值类型属性:{"description":"这是一个数值属性","type":"number"}
    //字符串类型属性:{"description":"这是一个字符串属性","type":"string"}
    std::string GetDescriptorJson() {
        //创建一个 std::string 类型的变量 json_str,并将其初始化为 {,这是 JSON 对象的起始符号。
        std::string json_str = "{";
        //向 json_str 中添加 description 字段,格式为 "description":"属性描述信息"。
        //description_ 是 Property 类的私有成员变量,存储着属性的描述信息。
        json_str += "\"description\":\"" + description_ + "\",";
        //依据 type_(Property 类的私有成员变量,代表属性的类型)的值,向 json_str 中添加 type 字段:

        //若 type_ 为 kValueTypeBoolean,添加 "type":"boolean"。
        //若 type_ 为 kValueTypeNumber,添加 "type":"number"。
        //若 type_ 为 kValueTypeString,添加 "type":"string"。
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        //向 json_str 中添加 },这是 JSON 对象的结束符号。
        json_str += "}";
        //返回生成好的包含属性描述信息和类型信息的 JSON 字符串。
        return json_str;
    }

获取状态JSON字符串

    //GetStateJson 函数根据属性的类型,调用对应的取值函数获取属性当前值,并将其转换为符合 JSON 格式的字符串返回。若属性类型无效,则返回 "null"。示例输出如下:
    //布尔类型属性:true 或 false
    //数值类型属性:123
    //字符串类型属性:"hello"
    //无效类型属性:null
    std::string GetStateJson() {
        // 检查属性类型是否为布尔类型
        if (type_ == kValueTypeBoolean) {
            // 调用布尔值获取函数,根据返回结果返回 "true" 或 "false"
            return boolean_getter_() ? "true" : "false";
        } 
        // 检查属性类型是否为数值类型
        else if (type_ == kValueTypeNumber) {
            // 调用数值获取函数,将返回的整数值转换为字符串返回
            return std::to_string(number_getter_());
        } 
        // 检查属性类型是否为字符串类型
        else if (type_ == kValueTypeString) {
            // 调用字符串获取函数,将返回的字符串用双引号包裹后返回,以符合 JSON 字符串格式
            return "\"" + string_getter_() + "\"";
        }
        // 若属性类型不匹配上述任何一种有效类型,则返回表示空值的 "null" 字符串
        return "null";
    }

 

PropertyList类

这个类需要前面的类

但是不需要前向声明

class PropertyList {

私有变量就一个property容器

private:
    std::vector<Property> properties_;

构造函数很有趣,C++11特性 default构造

public:
    PropertyList() = default;
    PropertyList(const std::vector<Property>& properties) : properties_(properties) {}

选中的代码是 PropertyList 类中的两个成员函数,用于向 PropertyList 对象添加不同类型的属性。下面详细解释:

    //该函数的作用是向 PropertyList 对象中添加一个布尔类型的属性。
    void AddBooleanProperty(const std::string& name, const std::string& description, std::function<bool()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    void AddNumberProperty(const std::string& name, const std::string& description, std::function<int()> getter) {
        properties_.push_back(Property(name, description, getter));
    }
    void AddStringProperty(const std::string& name, const std::string& description, std::function<std::string()> getter) {
        properties_.push_back(Property(name, description, getter));
    }

选中的代码是 PropertyList 类中的 operator[] 重载函数,其主要功能是通过属性名称来获取 Property 对象的常量引用。

  • const Property&:函数返回一个 Property 对象的常量引用。使用常量引用意味着调用者不能修改返回的 Property 对象,同时避免了对象的复制,提高性能。
  • operator[]:这是对 [] 运算符的重载,使得 PropertyList 对象可以像数组或 std::map 一样,通过 [] 运算符来访问其中的元素。
  • const std::string& name:传入的参数是一个常量引用类型的字符串,代表要查找的属性名称。使用常量引用可以避免不必要的字符串复制,提高性能。
  • const:函数末尾的 const 关键字表明这是一个常量成员函数,意味着该函数不会修改调用对象的任何成员变量。
    const Property& operator[](const std::string& name) const {
        for (auto& property : properties_) {
            if (property.name() == name) {
                return property;
            }
        }
        throw std::runtime_error("Property not found: " + name);
    }
    //选中的代码是 PropertyList 类中的 GetDescriptorJson 成员函数,其功能是生成一个包含所有属性描述信息的 JSON 对象字符串。下面逐行解释:
    //假设 PropertyList 中有两个属性,一个布尔类型属性 power 和一个数值类型属性 temperature,生成的 JSON 字符串可能如下:
    //{
    //    "power": {"description":"Whether the device is on","type":"boolean"},
    //    "temperature": {"description":"Current temperature","type":"number"}
    //}
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            //对于每个 Property 对象,将其名称用双引号包裹,后面加上 :,接着调用 property.GetDescriptorJson() 方法获取该属性的描述信息 JSON 字符串,最后添加逗号 ,,并将这些内容追加到 json_str 中。
            json_str += "\"" + property.name() + "\":" + property.GetDescriptorJson() + ",";
        }
        //检查 json_str 的最后一个字符是否为逗号 ,,如果是,则使用 pop_back() 方法移除该逗号,以保证生成的 JSON 字符串格式正确。
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }

假设 PropertyList 中有两个属性,一个布尔类型属性 power 和一个数值类型属性 temperature,生成的 JSON 字符串可能如下:

{
"power": true,
"temperature": 25
}

    //选中的代码是 PropertyList 类里的 GetStateJson 成员函数,其功能是生成一个包含所有属性当前状态信息的 JSON 对象字符串。
    std::string GetStateJson() {
        std::string json_str = "{";
        for (auto& property : properties_) {
            json_str += "\"" + property.name() + "\":" + property.GetStateJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

parameter类

class Parameter {
private:
    std::string name_;
    std::string description_;
    ValueType type_;
    bool required_;
    bool boolean_;
    int number_;
    std::string string_;
class Parameter {
private:
    std::string name_;
    std::string description_;
    ValueType type_;
    bool required_;
    bool boolean_;
    int number_;
    std::string string_;

public:
    //选中的代码是 Parameter 类的构造函数,其作用是创建 Parameter 对象并初始化其成员变量。下面详细解释:
    Parameter(const std::string& name, const std::string& description, ValueType type, bool required = true) :
        name_(name), description_(description), type_(type), required_(required) {}

    //选中的代码是 Parameter 类中的两个成员函数,它们均为常量成员函数,作用是获取 Parameter 对象的名称和描述信息。
    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ValueType type() const { return type_; }
    bool required() const { return required_; }

    bool boolean() const { return boolean_; }
    int number() const { return number_; }
    const std::string& string() const { return string_; }

    void set_boolean(bool value) { boolean_ = value; }
    void set_number(int value) { number_ = value; }
    void set_string(const std::string& value) { string_ = value; }

    //选中的代码是 Parameter 类的 GetDescriptorJson 成员函数,其功能是生成一个描述当前 Parameter 对象信息的 JSON 字符串。
    //{"description":"Enable the device","type":"boolean"} 假设 Parameter 对象的名称为 enable,描述信息为 "Enable the device",类型为布尔类型,生成的 JSON 字符串如下:
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        if (type_ == kValueTypeBoolean) {
            json_str += "\"type\":\"boolean\"";
        } else if (type_ == kValueTypeNumber) {
            json_str += "\"type\":\"number\"";
        } else if (type_ == kValueTypeString) {
            json_str += "\"type\":\"string\"";
        }
        json_str += "}";
        return json_str;
    }
};

选中的代码是 ParameterList 类中的 operator[] 运算符重载函数,其主要功能是通过参数名称来获取 Parameter 对象的常量引用。

该函数为 ParameterList 类提供了一种便捷的参数访问方式,允许用户通过参数名称来获取对应的 Parameter 对象。若参数存在,返回其常量引用;若不存在,则抛出异常。示例使用如下:

选中的代码是 ParameterList 类中的 operator[] 运算符重载函数,其主要功能是通过参数名称来获取 Parameter 对象的常量引用。

  • 调用 parameter 对象的 name() 成员函数获取其名称,并与传入的 name 参数进行比较。
  • 如果名称匹配,则返回该 Parameter 对象的常量引用。
class ParameterList {
private:
    std::vector<Parameter> parameters_;

public:
    ParameterList() = default;
    ParameterList(const std::vector<Parameter>& parameters) : parameters_(parameters) {}
    void AddParameter(const Parameter& parameter) {
        parameters_.push_back(parameter);
    }

    const Parameter& operator[](const std::string& name) const {
        for (auto& parameter : parameters_) {
            if (parameter.name() == name) {
                return parameter;
            }
        }
        throw std::runtime_error("Parameter not found: " + name);
    }

    // iterator
    auto begin() { return parameters_.begin(); }
    auto end() { return parameters_.end(); }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& parameter : parameters_) {
            json_str += "\"" + parameter.name() + "\":" + parameter.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

Method类

class Method {
private:
    std::string name_;
    std::string description_;
    ParameterList parameters_;
    std::function<void(const ParameterList&)> callback_;

还带一个回调参数

description和parameter两个层次了

class Method {
private:
    std::string name_;
    std::string description_;
    ParameterList parameters_;
    std::function<void(const ParameterList&)> callback_;

public:
    //选中的代码是 Method 类的构造函数,作用是创建 Method 类的对象并初始化其成员变量。
    Method(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) :
        name_(name), description_(description), parameters_(parameters), callback_(callback) {}

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }
    ParameterList& parameters() { return parameters_; }

    //选中的代码是 Method 类里的 GetDescriptorJson 成员函数,其作用是生成一个描述当前 Method 对象信息的 JSON 字符串。
    //
    std::string GetDescriptorJson() {
        std::string json_str = "{";
        json_str += "\"description\":\"" + description_ + "\",";
        json_str += "\"parameters\":" + parameters_.GetDescriptorJson();
        json_str += "}";
        return json_str;
    }

    void Invoke() {
        callback_(parameters_);
    }
};

假设 Method 对象的描述信息为 "This is an example method",其参数列表包含一个名为 enable 的布尔类型参数,生成的 JSON 字符串如下

{
    "description":"This is an example method",
    "parameters":{
        "enable":{
            "description":"Enable the device",
            "type":"boolean"
        }
    }
}

方法列表

选中的代码是 MethodList 类里的 AddMethod 成员函数,其功能是向 MethodList 对象添加一个新的 Method 对象。

class MethodList {
private:
    std::vector<Method> methods_;

public:
    MethodList() = default;
    MethodList(const std::vector<Method>& methods) : methods_(methods) {}

    void AddMethod(const std::string& name, const std::string& description, const ParameterList& parameters, std::function<void(const ParameterList&)> callback) {
        methods_.push_back(Method(name, description, parameters, callback));
    }

    Method& operator[](const std::string& name) {
        for (auto& method : methods_) {
            if (method.name() == name) {
                return method;
            }
        }
        throw std::runtime_error("Method not found: " + name);
    }

    std::string GetDescriptorJson() {
        std::string json_str = "{";
        for (auto& method : methods_) {
            json_str += "\"" + method.name() + "\":" + method.GetDescriptorJson() + ",";
        }
        if (json_str.back() == ',') {
            json_str.pop_back();
        }
        json_str += "}";
        return json_str;
    }
};

Thing类型

虽然是核心类,但是没什么好注释的

class Thing {
public:
    Thing(const std::string& name, const std::string& description) :
        name_(name), description_(description) {}
    virtual ~Thing() = default;

    virtual std::string GetDescriptorJson();
    virtual std::string GetStateJson();
    virtual void Invoke(const cJSON* command);

    const std::string& name() const { return name_; }
    const std::string& description() const { return description_; }

protected:
    PropertyList properties_;
    MethodList methods_;

private:
    std::string name_;
    std::string description_;
};

这段代码定义了两个函数声明和一个宏,用于实现 Thing 类及其派生类的动态注册与创建功能。

void RegisterThing(const std::string& type, std::function<Thing*()> creator);
Thing* CreateThing(const std::string& type);

#define DECLARE_THING(TypeName) \
    static iot::Thing* Create##TypeName() { \
        return new iot::TypeName(); \
    } \
    static bool Register##TypeNameHelper = []() { \
        RegisterThing(#TypeName, Create##TypeName); \
        return true; \
    }();

} // namespace iot

#endif // THING_H
  • 功能:将 Thing 类或其派生类的类型名和对应的创建函数注册到系统中,方便后续根据类型名动态创建对象。
  • 参数:
    • const std::string& type:表示 Thing 类或其派生类的类型名,使用常量引用避免字符串复制。
    • std::function<Thing*()> creator:一个函数对象,该对象不接受参数,返回一个 Thing* 指针,用于创建对应类型的对象。

 

posted @ 2025-06-15 19:17  mcwhirr  阅读(178)  评论(0)    收藏  举报