Information
We are currently investigating an issue with the editor of some pages. Please save your work and avoid to create new pages until this banner is gone.
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
#define CPPHTTPLIB_OPENSSL_SUPPORT #include <TuyaBulbBaciImpl.h> #include <stdexcept> // Extras #define SHA256_HASH_SIZE 32 using json = nlohmann::json; TuyaBulbBaciImpl::TuyaBulbBaciImpl(const ACE_CString& name, maci::ContainerServices* containerServices) : CharacteristicComponentImpl(name, containerServices), api_region("us"), client_id("..."), api_secret("..."), device_id("..."), base_url("https://openapi.tuyaus.com"), m_status_p(0) { std::cout << "Constructing TuyaBulbBaciImpl object." << std::endl; token = getToken(); m_status_p = new baci::ROboolean(name + ":status", getComponent()); CHARACTERISTIC_COMPONENT_PROPERTY(status, m_status_p); // std::cout << "API Region: " << this->api_region << std::endl; // std::cout << "Client ID: " << this->client_id << std::endl; // std::cout << "API Secret: " << this->api_secret << std::endl; // std::cout << "Device ID: " << this->device_id << std::endl; // std::cout << "API Token: " << this->token << std::endl; } TuyaBulbBaciImpl::~TuyaBulbBaciImpl() { if (m_status_p != 0) { m_status_p->destroy(); m_status_p=0; } } void TuyaBulbBaciImpl::turnOn() { std::cout << "Turning smart bulb ON..." << std::endl; // Set request parameters const std::string uri = "/iot-03/devices/" + this->device_id + "/commands"; const std::string action = "POST"; const std::string headers_str = ""; const std::string body = "{\"commands\":[{\"code\":\"switch_led\",\"value\":true}]}"; const std::string body_sha256 = "8479c9c60cd5d531054c49333c7b361a9ce41b9b313ab8eb6bc9df4141f658ef"; std::map<std::string, std::string> headers_map; headers_map = { {"Content-type", "application/json"}, {"access_token", this->token} }; // Send request and print response httplib::Result response = this->sendRequest(uri, action, headers_map, headers_str, body, body_sha256); std::cout << "Response status:\n"; std::cout << response->status << std::endl; std::cout << "Response body:\n"; std::cout << response->body << std::endl; // Check API response if (response->status == 200) { json body = json::parse(response->body); if (body["success"].dump() == "true") { m_status_p = new baci::ROboolean(true); } else { throw std::runtime_error("Error while turning smart bulb ON.\n"); } } } void TuyaBulbBaciImpl::turnOff() { std::cout << "Turning smart bulb OFF..." << std::endl; // Set request parameters const std::string uri = "/iot-03/devices/" + this->device_id + "/commands"; const std::string action = "POST"; const std::string headers_str = ""; const std::string body = "{\"commands\":[{\"code\":\"switch_led\",\"value\":false}]}"; const std::string body_sha256 = "c9df53ad98d9c9be68680613d9ece634a27f102c5e40c7b5f60c11f6b944b6a9"; std::map<std::string, std::string> headers_map; headers_map = { {"Content-type", "application/json"}, {"access_token", this->token} }; // Send request and print response httplib::Result response = this->sendRequest(uri, action, headers_map, headers_str, body, body_sha256); std::cout << "Response status:\n"; std::cout << response->status << std::endl; std::cout << "Response body:\n"; std::cout << response->body << std::endl; // Check API response if (response->status == 200) { json body = json::parse(response->body); if (body["success"].dump() == "true") { m_status_p = new baci::ROboolean(false); } else { throw std::runtime_error("Error while turning smart bulb OFF.\n"); } } } httplib::Result TuyaBulbBaciImpl::sendRequest( const std::string uri, const std::string action, const std::map<std::string, std::string> headers_map, const std::string headers_str, const std::string body, const std::string body_sha256, const std::string version ) { // https://developer.tuya.com/en/docs/iot/api-request?id=Ka4a8uuo1j4t4 // https://developer.tuya.com/en/docs/iot/singnature?id=Ka43a5mtx1gsc std::cout << "Sending request to Tuya API " << uri << std::endl; // String stringToSign = // HTTPMethod + "\n" + // Content-SHA256 + "\n" + // Headers + "\n" + // Url const std::string url = "/" + version + uri; const std::string string_to_sign = action + "\n" + body_sha256 + "\n" + headers_str + "\n" + url; // Get time in milliseconds since epoch, with 13 digits std::time_t t = std::time(nullptr) * 1000; // str = client_id + access_token + t + nonce + stringToSign // sign = HMAC-SHA256(str, secret).toUpperCase() std::string str_data; if (this->token.empty()) { str_data = this->client_id + std::to_string(t) + string_to_sign; } else { str_data = this->client_id + this->token + std::to_string(t) + string_to_sign; } // Allocate memory for the HMAC std::vector<uint8_t> out(SHA256_HASH_SIZE); // Call hmac-sha256 function and parse result to string stream hmac_sha256(this->api_secret.data(), this->api_secret.size(), str_data.data(), str_data.size(), out.data(), out.size()); std::stringstream ss_result; for (uint8_t i : out) { ss_result << std::hex << std::setfill('0') << std::setw(2) << (int)i; } // to uppercase std::string sign = ss_result.str(); transform(sign.begin(), sign.end(), sign.begin(), ::toupper); // Create base headers httplib::Headers request_headers = { { "client_id", this->client_id }, { "sign_method", "HMAC-SHA256" }, { "sign", sign }, { "t", std::to_string(t) } }; // Add extra headers std::map<std::string, std::string>::const_iterator it; for (it = headers_map.begin(); it != headers_map.end(); it++) { request_headers.insert({ it->first, it->second }); } // Create HTTPS client httplib::Client cli(this->base_url); // Send request if (action.compare("GET") == 0) { return cli.Get(url.c_str(), request_headers); } else { return cli.Post(url.c_str(), request_headers, body.c_str(), "application/json"); } } std::string TuyaBulbBaciImpl::getToken() { // https://openapi.tuyaus.com/v1.0/token?grant_type=1 const std::string uri = "/token?grant_type=1"; httplib::Result response = this->sendRequest(uri); // Check API response if (response->status == 200) { json body = json::parse(response->body); if (body["success"].dump() == "true") { const std::string token = body["result"]["access_token"]; return token; } } throw std::runtime_error("Error while getting API token.\n"); } ACS::ROboolean_ptr TuyaBulbBaciImpl::status () { if(m_status_p == 0) { return ACS::ROboolean::_nil(); } ACS::ROboolean_var prop = ACS::ROboolean::_narrow(m_status_p->getCORBAReference()); return prop._retn(); } /* --------------- [ MACI DLL support functions ] -----------------*/ #include <maciACSComponentDefines.h> MACI_DLL_SUPPORT_FUNCTIONS(TuyaBulbBaciImpl) /* ----------------------------------------------------------------*/ |
...