diff --git a/.vscode/settings.json b/.vscode/settings.json index 5b08dc6..01f02a7 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,18 +1,19 @@ -{ - "files.associations": { - "array": "cpp", - "deque": "cpp", - "list": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "string_view": "cpp", - "initializer_list": "cpp", - "ranges": "cpp", - "memory": "cpp", - "random": "cpp", - "optional": "cpp", - "memory_resource": "cpp", - "system_error": "cpp" - } +{ + "files.associations": { + "array": "cpp", + "deque": "cpp", + "list": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "string_view": "cpp", + "initializer_list": "cpp", + "ranges": "cpp", + "memory": "cpp", + "random": "cpp", + "optional": "cpp", + "memory_resource": "cpp", + "system_error": "cpp", + "*.tcc": "cpp" + } } \ No newline at end of file diff --git a/src/IRbaby.cpp b/src/IRbaby.cpp index 18656db..de3abb0 100644 --- a/src/IRbaby.cpp +++ b/src/IRbaby.cpp @@ -176,8 +176,8 @@ void setup() { saveSettings(); delay(SYSTEM_DELAY); - connectToAliyunIoT(); loadIRPin(ConfigData["pin"]["ir_send"], ConfigData["pin"]["ir_receive"]); + connectToAliyunIoT(); alinkCheckTask.attach_scheduled(MQTT_CHECK_INTERVALS, checkAlinkMQTT); disableIRTask.attach_scheduled(DISABLE_SIGNAL_INTERVALS, disableIR); @@ -185,6 +185,7 @@ void setup() { void loop() { recvIR(); + // downloadBin(); yield(); aliotKeepAlive(); } diff --git a/src/IRbabyIR.cpp b/src/IRbabyIR.cpp index ec68beb..81b101a 100644 --- a/src/IRbabyIR.cpp +++ b/src/IRbabyIR.cpp @@ -30,20 +30,22 @@ #include "IRbabyUserSettings.h" #include "IRbabyIRIS.h" #include "IRbabyHttp.h" +#include "IRbabyUtils.h" #include "IRbabyIR.h" -#define SAVE_PATH "/ir/" +#define IR_SERIES_MAX (1024) +#define IR_END_CODE (10000) -decode_results results; // Somewhere to store the results -const uint8_t kTimeout = 50; -// As this program is a special purpose capture/decoder, let us use a larger -// than normal buffer so we can handle Air Conditioner remote codes. -const uint16_t kCaptureBufferSize = 1024; -static IRsend * ir_send = nullptr; -static IRrecv * ir_recv = nullptr; bool saveSignal(); +decode_results results; // Somewhere to store the results +const uint8_t k_timeout = 50; +// As this program is a special purpose capture/decoder, let us use a larger +// than normal buffer so we can handle Air Conditioner remote codes. +const uint16_t k_capture_buffer_size = IR_SERIES_MAX; +static IRsend * ir_send = nullptr; +static IRrecv * ir_recv = nullptr; bool sendIR(String file_name) { String save_path = SAVE_PATH + file_name; @@ -54,9 +56,9 @@ bool sendIR(String file_name) { return false; } Serial.println(); - uint16_t *data_buffer = (uint16_t *)malloc(sizeof(uint16_t) * 512); + uint16_t *data_buffer = (uint16_t *)malloc(sizeof(uint16_t) * IR_SERIES_MAX); uint16_t length = cache.size() / 2; - memset(data_buffer, 0x0, 512); + memset(data_buffer, 0x0, IR_SERIES_MAX); INFOF("file size = %d\n", cache.size()); INFOLN(); cache.readBytes((char *)data_buffer, cache.size()); @@ -70,6 +72,63 @@ bool sendIR(String file_name) { return false; } +bool emitIR(String timing) { + char* parts[IR_SERIES_MAX]; + uint16_t series[IR_SERIES_MAX + 1] = { 0 }; + int parts_num = 0; + int i = 0; + + parts_num = split_string(timing, parts, ","); + if (parts_num > 0) { + for (i = 0; i < parts_num; i++) { + series[i] = (uint16_t) atoi(parts[i]); + // INFOF("%d ", series[i]); + } + series[i] = (uint16_t) IR_END_CODE; + ir_recv->disableIRIn(); + ir_send->sendRaw(series, parts_num + 1, 38); + ir_recv->enableIRIn(); + } + return true; +} + +bool sendCommand(String file_name, int key) { + String save_path = SAVE_PATH; + save_path += file_name; + if (LittleFS.exists(save_path)) { + File cache = LittleFS.open(save_path, "r"); + if (cache) { + UINT16 content_size = cache.size(); + DEBUGF("content size = %d\n", content_size); + + if (content_size != 0) { + UINT8 *content = (UINT8 *)malloc(content_size * sizeof(UINT8)); + cache.seek(0L, fs::SeekSet); + cache.readBytes((char *)content, content_size); + ir_binary_open(2, 1, content, content_size); + UINT16 *user_data = (UINT16 *)malloc(IR_SERIES_MAX * sizeof(UINT16)); + UINT16 data_length = ir_decode(0, user_data, NULL, FALSE); + + DEBUGF("data_length = %d\n", data_length); + if (LOG_DEBUG) { + for (int i = 0; i < data_length; i++) + Serial.printf("%d ", *(user_data + i)); + Serial.println(); + } + ir_recv->disableIRIn(); + ir_send->sendRaw(user_data, data_length, 38); + ir_recv->enableIRIn(); + ir_close(); + free(user_data); + free(content); + } else + ERRORF("Open %s is empty\n", save_path.c_str()); + } + cache.close(); + } + return true; +} + void sendStatus(String file, t_remote_ac_status status) { String save_path = SAVE_PATH + file; String url = String(DOWNLOAD_PREFIX) + file + String(DOWNLOAD_SUFFIX); @@ -89,7 +148,7 @@ void sendStatus(String file, t_remote_ac_status status) { cache.seek(0L, fs::SeekSet); cache.readBytes((char *)content, content_size); ir_binary_open(REMOTE_CATEGORY_AC, 1, content, content_size); - UINT16 *user_data = (UINT16 *)malloc(1024 * sizeof(UINT16)); + UINT16 *user_data = (UINT16 *)malloc(IR_SERIES_MAX * sizeof(UINT16)); UINT16 data_length = ir_decode(0, user_data, &status, FALSE); DEBUGF("data_length = %d\n", data_length); @@ -156,43 +215,6 @@ void initAC(String file) { ACStatus[file]["speed"] = 0; } -bool sendKey(String file_name, int key) { - String save_path = SAVE_PATH; - save_path += file_name; - if (LittleFS.exists(save_path)) { - File cache = LittleFS.open(save_path, "r"); - if (cache) { - UINT16 content_size = cache.size(); - DEBUGF("content size = %d\n", content_size); - - if (content_size != 0) { - UINT8 *content = (UINT8 *)malloc(content_size * sizeof(UINT8)); - cache.seek(0L, fs::SeekSet); - cache.readBytes((char *)content, content_size); - ir_binary_open(2, 1, content, content_size); - UINT16 *user_data = (UINT16 *)malloc(1024 * sizeof(UINT16)); - UINT16 data_length = ir_decode(0, user_data, NULL, FALSE); - - DEBUGF("data_length = %d\n", data_length); - if (LOG_DEBUG) { - for (int i = 0; i < data_length; i++) - Serial.printf("%d ", *(user_data + i)); - Serial.println(); - } - ir_recv->disableIRIn(); - ir_send->sendRaw(user_data, data_length, 38); - ir_recv->enableIRIn(); - ir_close(); - free(user_data); - free(content); - } else - ERRORF("Open %s is empty\n", save_path.c_str()); - } - cache.close(); - } - return true; -} - void loadIRPin(uint8_t send_pin, uint8_t recv_pin) { if (ir_send != nullptr) { delete ir_send; @@ -203,7 +225,7 @@ void loadIRPin(uint8_t send_pin, uint8_t recv_pin) { ir_send = new IRsend(send_pin); DEBUGF("Load IR send pin at %d\n", send_pin); ir_send->begin(); - ir_recv = new IRrecv(recv_pin, kCaptureBufferSize, kTimeout, true); + ir_recv = new IRrecv(recv_pin, k_capture_buffer_size, k_timeout, true); disableIR(); } diff --git a/src/IRbabyIR.h b/src/IRbabyIR.h index c4af6fa..05557d2 100644 --- a/src/IRbabyIR.h +++ b/src/IRbabyIR.h @@ -1,42 +1,54 @@ -/** - * - * Copyright (c) 2020-2022 IRbaby-IRext - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef IRBABY_IR_H -#define IRBABY_IR_H - -#include -#include -#include -#include "ir_decode.h" - -void loadIRPin(uint8_t send_pin, uint8_t recv_pin); -void enableIR(); -void disableIR(); -void sendStatus(String file_name, t_remote_ac_status status); -bool sendKey(String file_name, int key); -bool sendIR(String file_name); -void recvIR(); -bool saveIR(String file_name); -void initAC(String); - +/** + * + * Copyright (c) 2020-2022 IRbaby-IRext + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef IRBABY_IR_H +#define IRBABY_IR_H + +#include +#include +#include +#include "ir_decode.h" + +void loadIRPin(uint8_t send_pin, uint8_t recv_pin); + +void enableIR(); + +void disableIR(); + +bool downloadBin(int remote_id); + +bool sendIR(String file_name); + +bool emitIR(String timing); + +bool sendCommand(String file_name, int key); + +void sendStatus(String file_name, t_remote_ac_status status); + +void recvIR(); + +bool saveIR(String file_name); + +void initAC(String); + #endif // IRBABY_IR_H \ No newline at end of file diff --git a/src/IRbabyIRIS.cpp b/src/IRbabyIRIS.cpp index 9f78e93..1daaf0c 100644 --- a/src/IRbabyIRIS.cpp +++ b/src/IRbabyIRIS.cpp @@ -27,12 +27,14 @@ #include #include +#include #include "defines.h" #include "IRbabyGlobal.h" #include "IRbabySerial.h" #include "IRbabyAlink.h" #include "IRbabyHttp.h" +#include "IRbabyIR.h" #include "IRbabyIRIS.h" @@ -48,10 +50,10 @@ extern String g_device_name; extern String g_upstream_topic; extern int g_app_id; + char iris_credential_token[CREDENTIAL_MAX] = { 0 }; char iris_server_address[URL_SHORT_MAX] = { 0 }; - // private function declarations static int processEvent(String event_name, String product_key, String device_name, String content); static String buildConnect(); @@ -156,6 +158,37 @@ int fetchIrisCredential(String credential_token, return ret; } +bool downloadBin(int remote_id) { + bool ret = false; + bool protocol_prefix = false; + String save_file = ""; + String download_bin_url; + http_error_t http_ret = HTTP_ERROR_GENERIC; + + if (NULL != strstr(iris_server_address, "http://")) { + protocol_prefix = true; + } + if (protocol_prefix) { + download_bin_url = String(iris_server_address); + } else { + download_bin_url = String("http://"); + download_bin_url.concat(iris_server_address); + } + download_bin_url.concat(String(DOWNLOAD_BIN_SUFFIX)); + + if (-1 != remote_id) { + INFOF("notified to download bin: %d", remote_id); + save_file = String("ir_") + String(remote_id); + + String temp = String(SAVE_PATH) + String("/") + save_file; + if (!LittleFS.exists(temp)) { + downLoadFile(download_bin_url, save_file, SAVE_PATH); + ret = true; + } + } + return ret; +} + void sendIrisKitConnect() { String connectMessage = buildConnect(); sendRawData(g_upstream_topic.c_str(), (uint8_t*) connectMessage.c_str(), connectMessage.length()); @@ -237,8 +270,12 @@ static int handleEmit(String product_key, String device_name, String content) { emit_code_doc.clear(); if (OK == deserializeJson(emit_code_doc, content)) { int remote_id = emit_code_doc["remoteId"]; - int key_number = emit_code_doc["keyNumber"]; - INFOF("will emit key : %d for remote %d\n", key_number, remote_id); + String key_name = emit_code_doc["keyName"]; + String key_value = emit_code_doc["keyValue"]; + INFOF("will emit key : %s for remote %d = %s\n", key_name.c_str(), remote_id, key_value.c_str()); + emitIR(key_value); + } else { + INFOF("deserialize failed\n"); } return 0; } \ No newline at end of file diff --git a/src/IRbabyIRIS.h b/src/IRbabyIRIS.h index 6a47e85..69692a9 100644 --- a/src/IRbabyIRIS.h +++ b/src/IRbabyIRIS.h @@ -33,6 +33,8 @@ #define DOWNLOAD_PREFIX "http://irext-debug.oss-cn-hangzhou.aliyuncs.com/irda_" #define DOWNLOAD_SUFFIX ".bin" +// IRext bin code storage +#define SAVE_PATH "/ir/" // IRIS communication #define EVENT_NAME_CONNECT "__connect" diff --git a/src/IRbabyUtils.cpp b/src/IRbabyUtils.cpp new file mode 100644 index 0000000..70d37e7 --- /dev/null +++ b/src/IRbabyUtils.cpp @@ -0,0 +1,71 @@ +/** + * + * Copyright (c) 2020-2022 IRbaby-IRext + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include "IRbabyUtils.h" + +int split_string(const String source, char* parts[], const char* delimiter) { + char* pch = NULL; + char* copy = NULL; + char* tmp = NULL; + int i = 0; + + copy = strdup(source.c_str()); + if (NULL == copy) { + goto exit; + } + + pch = strtok(copy, delimiter); + + tmp = strdup(pch); + if (NULL == tmp) { + goto exit; + } + + parts[i++] = tmp; + + while (pch) { + pch = strtok(NULL, delimiter); + if (NULL == pch) break; + + tmp = strdup(pch); + if (NULL == tmp) { + goto exit; + } + + parts[i++] = tmp; + } + + free(copy); + return i; + +exit: + free(copy); + for (int j = 0; j < i; j++) { + free(parts[j]); + } + return -1; +} \ No newline at end of file diff --git a/src/IRbabyUtils.h b/src/IRbabyUtils.h new file mode 100644 index 0000000..f0636da --- /dev/null +++ b/src/IRbabyUtils.h @@ -0,0 +1,32 @@ +/** + * + * Copyright (c) 2020-2022 IRbaby-IRext + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "WString.h" + +#ifndef IRBABY_IRIS_UTILS_H +#define IRBABY_IRIS_UTILS_H + +int split_string(const String source, char* parts[], const char* delimiter); + +#endif //IRBABY_IRIS_UTILS_H +