completed android-example and arduino example co-working

This commit is contained in:
strawmanbobi
2026-01-27 20:22:00 +08:00
parent 12fa4d886b
commit 93685d90f0
32 changed files with 989 additions and 489 deletions

View File

@@ -27,10 +27,12 @@
#include <cstdint>
// Wi-Fi Configs
// #define SECRET_SSID "Maomao的小房子"
// #define SECRET_PASS "Maomao121207"
#define SECRET_SSID "maomao"
#define SECRET_PASS "20121207"
#define SECRET_SSID "Maomao的小房子"
#define SECRET_PASS "Maomao121207"
// #define SECRET_SSID "maomao"
// #define SECRET_PASS "20121207"
// #define TEST_BIN_RECEIVE (1)
// LED Matrix Definitions
constexpr uint32_t chip[] = {

View File

@@ -0,0 +1,66 @@
/**
*
* Copyright (c) 2020-2025 IRext Opensource Organization
*
* 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 <ArduinoJson.h>
#include "serial_log.h"
#include "control_command.h"
// public function definitions
int parseControlCommand(int category, const char *commandJson,
t_remote_ac_status *ac_status, int* keyCode) {
JsonDocument doc;
DeserializationError error = deserializeJson(doc, commandJson);
if (error) {
serialPrint(LOG_ERROR, "Parsing command JSON failed: %s", error.c_str());
return -1;
}
// Parse AC status fields from JSON according to ACStatus structure
ac_status->ac_power = doc["acStatus"]["acPower"];
ac_status->ac_temp = doc["acStatus"]["acTemp"];
ac_status->ac_mode = doc["acStatus"]["acMode"];
ac_status->ac_wind_dir = doc["acStatus"]["acWindDir"];
ac_status->ac_wind_speed = doc["acStatus"]["acWindSpeed"];
ac_status->ac_display = doc["acStatus"]["acDisplay"];
ac_status->ac_sleep = doc["acStatus"]["acSleep"];
ac_status->ac_timer = doc["acStatus"]["acTimer"];
ac_status->change_wind_direction = doc["acStatus"]["changeWindDir"];
*keyCode = doc["keyCode"];
serialPrint(LOG_VERBOSE, "--- AC Status ---");
serialPrint(LOG_VERBOSE, "Power: %d", ac_status->ac_power);
serialPrint(LOG_VERBOSE, "Temperature: %d", ac_status->ac_temp);
serialPrint(LOG_VERBOSE, "Mode: %d", ac_status->ac_mode);
serialPrint(LOG_VERBOSE, "Wind Direction: %d", ac_status->ac_wind_dir);
serialPrint(LOG_VERBOSE, "Wind Speed: %d", ac_status->ac_wind_speed);
serialPrint(LOG_VERBOSE, "Display: %d", ac_status->ac_display);
serialPrint(LOG_VERBOSE, "Sleep: %d", ac_status->ac_sleep);
serialPrint(LOG_VERBOSE, "Timer: %d", ac_status->ac_timer);
serialPrint(LOG_VERBOSE, "Change Wind Direction: %d", ac_status->change_wind_direction);
serialPrint(LOG_VERBOSE, "Key Code: %d", *keyCode);
return 0;
}

View File

@@ -0,0 +1,40 @@
/**
*
* Copyright (c) 2020-2025 IRext Opensource Organization
*
* 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 ARDUINO_EXAMPLE_CONTROL_COMMAND_H
#define ARDUINO_EXAMPLE_CONTROL_COMMAND_H
#include "ir_decode.h"
#ifdef __cplusplus
extern "C" {
#endif
int parseControlCommand(int category, const char *commandJson,
t_remote_ac_status *ac_status, int* keyCode);
#ifdef __cplusplus
}
#endif
#endif // ARDUINO_EXAMPLE_CONTROL_COMMAND_H

View File

@@ -26,15 +26,15 @@ extern "C"
#define MIN_TAG_LENGTH_TYPE_1 4
#define MIN_TAG_LENGTH_TYPE_2 6
INT8 apply_power(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_power(t_remote_ac_status *ac_status, UINT8 function_code);
INT8 apply_mode(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_mode(t_remote_ac_status *ac_status, UINT8 function_code);
INT8 apply_wind_speed(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_wind_speed(t_remote_ac_status *ac_status, UINT8 function_code);
INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_swing(t_remote_ac_status *ac_status, UINT8 function_code);
INT8 apply_temperature(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_temperature(t_remote_ac_status *ac_status, UINT8 function_code);
INT8 apply_function(struct ac_protocol *protocol, UINT8 function);

View File

@@ -342,7 +342,7 @@ typedef struct ac_protocol
UINT8 swing_status;
BOOL change_wind_direction;
UINT8 change_wind_direction;
UINT16 dc_cnt;
t_ac_bit_num bit_num[MAX_BITNUM];
@@ -382,10 +382,11 @@ typedef struct REMOTE_AC_STATUS
UINT8 ac_display;
UINT8 ac_sleep;
UINT8 ac_timer;
UINT8 change_wind_direction;
} t_remote_ac_status;
// function polymorphism
typedef INT8 (*lp_apply_ac_parameter)(t_remote_ac_status ac_status, UINT8 function_code);
typedef INT8 (*lp_apply_ac_parameter)(t_remote_ac_status *ac_status, UINT8 function_code);
#define TAG_AC_BOOT_CODE 1
#define TAG_AC_ZERO 2

View File

@@ -276,11 +276,10 @@ extern INT8 ir_binary_open(const UINT8 category, const UINT8 sub_category, UINT8
* parameters: key_code (in) - the code of pressed key
* user_data (out) - output decoded data in INT16 array format
* ac_status(in) - pointer to AC status (optional)
* change_wind_direction (in) - if control changes wind direction for AC (for AC only)
*
* returns: length of decoded data (0 indicates decode failure)
*/
extern UINT16 ir_decode(UINT8 key_code, UINT16* user_data, t_remote_ac_status* ac_status, BOOL change_wind_direction);
extern UINT16 ir_decode(UINT8 key_code, UINT16* user_data, t_remote_ac_status* ac_status);
/**
* function ir_close
@@ -362,7 +361,7 @@ extern void ir_lib_free_inner_buffer();
UINT16 ir_decode_combo(const UINT8 category, const UINT8 sub_category,
UINT8* binary, UINT16 bin_length,
UINT8 key_code, UINT16* user_data,
t_remote_ac_status* ac_status, BOOL change_wind_direction);
t_remote_ac_status* ac_status);
#ifdef __cplusplus
}

View File

@@ -12,7 +12,7 @@ Revision log:
#ifndef _IR_DEFS_H
#define _IR_DEFS_H
#define IR_DECODE_LIB_VER "1.5.0"
#define IR_DECODE_LIB_VER "1.5.2"
#if defined (BOARD_PC)
#pragma ide diagnostic ignored "OCUnusedGlobalDeclarationInspection"
@@ -29,6 +29,10 @@ extern "C"
#define LOG_TAG "ir_decode"
#endif
#if defined BOARD_ARDUINO
#include "serial_log.h"
#endif
#define TRUE 1
#define FALSE 0
@@ -59,10 +63,10 @@ void noprint(const char *fmt, ...);
#define ir_strlen(A) strlen(A)
#if ((defined BOARD_PC) || (defined BOARD_PC_JNI)) && (defined DEBUG)
#define ir_printf(...) do { printf(__VA_ARGS__); fflush(stdout); } while(0)
#else
#define ir_printf noprint
#elif (defined BOARD_ARDUINO)
#define ir_printf(...) do { serialPrint(LOG_DEBUG, __VA_ARGS__); } while(0)
#endif
#define USER_DATA_SIZE 1636
#define USER_DATA_SIZE 2048
// #define USER_DATA_SIZE 4096
#ifdef __cplusplus

View File

@@ -13,8 +13,8 @@ Revision log:
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
#endif
#include "include/ir_utils.h"
#include "include/ir_ac_apply.h"
#include "ir_utils.h"
#include "ir_ac_apply.h"
static INT8 apply_ac_power(struct ac_protocol *protocol, UINT8 power_status);
@@ -616,17 +616,17 @@ INT8 apply_checksum(struct ac_protocol *protocol)
return IR_DECODE_SUCCEEDED;
}
INT8 apply_power(t_remote_ac_status ac_status, UINT8 function_code)
INT8 apply_power(t_remote_ac_status *ac_status, UINT8 function_code)
{
(void) function_code;
apply_ac_power(context, ac_status.ac_power);
apply_ac_power(context, ac_status->ac_power);
return IR_DECODE_SUCCEEDED;
}
INT8 apply_mode(t_remote_ac_status ac_status, UINT8 function_code)
INT8 apply_mode(t_remote_ac_status *ac_status, UINT8 function_code)
{
(void) function_code;
if (IR_DECODE_FAILED == apply_ac_mode(context, ac_status.ac_mode))
if (IR_DECODE_FAILED == apply_ac_mode(context, ac_status->ac_mode))
{
// do not implement this mechanism since mode, temperature, wind
// speed would have unspecified function
@@ -639,16 +639,16 @@ INT8 apply_mode(t_remote_ac_status ac_status, UINT8 function_code)
return IR_DECODE_SUCCEEDED;
}
INT8 apply_wind_speed(t_remote_ac_status ac_status, UINT8 function_code)
INT8 apply_wind_speed(t_remote_ac_status *ac_status, UINT8 function_code)
{
if (FALSE == context->n_mode[ac_status.ac_mode].all_speed)
if (FALSE == context->n_mode[ac_status->ac_mode].all_speed)
{
// if this level is not in black list
if (!is_in(context->n_mode[ac_status.ac_mode].speed,
ac_status.ac_wind_speed,
context->n_mode[ac_status.ac_mode].speed_cnt))
if (!is_in(context->n_mode[ac_status->ac_mode].speed,
ac_status->ac_wind_speed,
context->n_mode[ac_status->ac_mode].speed_cnt))
{
if (IR_DECODE_FAILED == apply_ac_wind_speed(context, ac_status.ac_wind_speed) &&
if (IR_DECODE_FAILED == apply_ac_wind_speed(context, ac_status->ac_wind_speed) &&
function_code == AC_FUNCTION_WIND_SPEED)
{
// do not implement this mechanism since mode, temperature, wind
@@ -689,7 +689,7 @@ INT8 apply_wind_speed(t_remote_ac_status ac_status, UINT8 function_code)
return IR_DECODE_SUCCEEDED;
}
INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code)
INT8 apply_swing(t_remote_ac_status *ac_status, UINT8 function_code)
{
(void) ac_status;
if (function_code == AC_FUNCTION_WIND_FIX)
@@ -697,7 +697,7 @@ INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code)
// adjust fixed wind direction according to current status
if (context->si.type == SWING_TYPE_NORMAL && context->si.mode_count > 1)
{
if (TRUE == context->change_wind_direction)
if (1 == context->change_wind_direction)
{
context->si.dir_index++;
}
@@ -735,15 +735,15 @@ INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code)
return IR_DECODE_SUCCEEDED;
}
INT8 apply_temperature(t_remote_ac_status ac_status, UINT8 function_code)
INT8 apply_temperature(t_remote_ac_status *ac_status, UINT8 function_code)
{
if (FALSE == context->n_mode[ac_status.ac_mode].all_temp)
if (FALSE == context->n_mode[ac_status->ac_mode].all_temp)
{
if (!is_in(context->n_mode[ac_status.ac_mode].temp,
ac_status.ac_temp,
context->n_mode[ac_status.ac_mode].temp_cnt))
if (!is_in(context->n_mode[ac_status->ac_mode].temp,
ac_status->ac_temp,
context->n_mode[ac_status->ac_mode].temp_cnt))
{
if (IR_DECODE_FAILED == apply_ac_temperature(context, ac_status.ac_temp))
if (IR_DECODE_FAILED == apply_ac_temperature(context, ac_status->ac_temp))
{
if (function_code == AC_FUNCTION_TEMPERATURE_UP
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_UP)*/)

View File

@@ -9,8 +9,8 @@ Revision log:
* 2017-01-03: created by strawmanbobi
**************************************************************************************/
#include "include/ir_ac_binary_parse.h"
#include "include/ir_decode.h"
#include "ir_ac_binary_parse.h"
#include "ir_decode.h"
UINT16 tag_head_offset = 0;

View File

@@ -14,8 +14,8 @@ Revision log:
#pragma ide diagnostic ignored "readability-redundant-declaration"
#endif
#include "include/ir_ac_build_frame.h"
#include "include/ir_decode.h"
#include "ir_ac_build_frame.h"
#include "ir_decode.h"
extern t_ac_protocol* context;

View File

@@ -13,13 +13,13 @@ Revision log:
#include <stdio.h>
#include <string.h>
#include "include/ir_ac_control.h"
#include "include/ir_ac_binary_parse.h"
#include "include/ir_decode.h"
#include "include/ir_ac_parse_parameter.h"
#include "include/ir_ac_parse_forbidden_info.h"
#include "include/ir_ac_parse_frame_info.h"
#include "include/ir_utils.h"
#include "ir_ac_control.h"
#include "ir_ac_binary_parse.h"
#include "ir_decode.h"
#include "ir_ac_parse_parameter.h"
#include "ir_ac_parse_forbidden_info.h"
#include "ir_ac_parse_frame_info.h"
#include "ir_utils.h"
#if defined USE_DYNAMIC_TAG

View File

@@ -17,8 +17,8 @@ Revision log:
#include <stdlib.h>
#include <string.h>
#include "include/ir_decode.h"
#include "include/ir_ac_parse_forbidden_info.h"
#include "ir_decode.h"
#include "ir_ac_parse_forbidden_info.h"
extern t_ac_protocol *context;

View File

@@ -10,11 +10,10 @@ Revision log:
**************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "include/ir_utils.h"
#include "include/ir_ac_parse_frame_info.h"
#include "ir_utils.h"
#include "ir_ac_parse_frame_info.h"
INT8 parse_boot_code(struct tag_head *tag)
@@ -341,5 +340,13 @@ INT8 parse_bit_num(struct tag_head *tag)
if (context->bit_num[i].pos == -1)
context->bit_num[i].pos = (UINT16) (context->default_code.len - 1); //convert -1 to last data pos
}
// Ensure bit_num_cnt does not exceed MAX_BITNUM to prevent buffer overflow
if (context->bit_num_cnt > MAX_BITNUM)
{
ir_printf("Warning: bit_num_cnt (%d) exceeds MAX_BITNUM (%d), limiting to MAX_BITNUM\n",
context->bit_num_cnt, MAX_BITNUM);
context->bit_num_cnt = MAX_BITNUM;
}
return IR_DECODE_SUCCEEDED;
}

View File

@@ -13,8 +13,8 @@ Revision log:
#include <stdio.h>
#include <string.h>
#include "include/ir_utils.h"
#include "include/ir_ac_parse_parameter.h"
#include "ir_utils.h"
#include "ir_ac_parse_parameter.h"
static INT8 parse_checksum_byte_typed(const UINT8 *csdata, t_tag_checksum_data *checksum, UINT16 len);
@@ -236,6 +236,13 @@ INT8 parse_temp_1(struct tag_head *tag, t_temp_1 *temp1)
temp1->len = (UINT8) hex_len;
UINT8 seg_len = hex_data[0];
// Initialize all segments to NULL to ensure proper cleanup in case of error
for (seg_index = AC_TEMP_16; seg_index < (UINT16) AC_TEMP_MAX; seg_index++)
{
temp1->comp_data[seg_index].seg_len = 0;
temp1->comp_data[seg_index].segment = NULL;
}
for (seg_index = AC_TEMP_16; seg_index < (UINT16) AC_TEMP_MAX; seg_index++)
{
// 020210 indicates set the 02nd byte to [default] +10, +11, +12, +...
@@ -243,6 +250,17 @@ INT8 parse_temp_1(struct tag_head *tag, t_temp_1 *temp1)
temp1->comp_data[seg_index].segment = (UINT8 *) ir_malloc(seg_len);
if (NULL == temp1->comp_data[seg_index].segment)
{
// Clean up previously allocated memory
UINT16 cleanup_idx;
for (cleanup_idx = AC_TEMP_16; cleanup_idx < seg_index; cleanup_idx++)
{
if (temp1->comp_data[cleanup_idx].segment != NULL)
{
ir_free(temp1->comp_data[cleanup_idx].segment);
temp1->comp_data[cleanup_idx].segment = NULL;
temp1->comp_data[cleanup_idx].seg_len = 0;
}
}
ir_free(hex_data);
return IR_DECODE_FAILED;
}
@@ -400,10 +418,30 @@ INT8 parse_swing_1(struct tag_head *tag, t_swing_1 *swing1, UINT16 swing_count)
return IR_DECODE_FAILED;
}
// Initialize the comp_data to ensure proper cleanup in case of error
for (seg_index = 0; seg_index < swing_count; seg_index++)
{
swing1->comp_data[seg_index].seg_len = 0;
swing1->comp_data[seg_index].segment = NULL;
}
for (seg_index = 0; seg_index < swing_count; seg_index++)
{
if (IR_DECODE_FAILED == parse_comp_data_type_1(hex_data, &trav_offset, &swing1->comp_data[seg_index]))
{
// Clean up any allocated memory in previous iterations
UINT16 i;
for (i = 0; i < seg_index; i++)
{
if (swing1->comp_data[i].segment != NULL)
{
ir_free(swing1->comp_data[i].segment);
swing1->comp_data[i].segment = NULL;
swing1->comp_data[i].seg_len = 0;
}
}
ir_free(swing1->comp_data);
swing1->comp_data = NULL;
ir_free(hex_data);
return IR_DECODE_FAILED;
}
@@ -518,6 +556,16 @@ INT8 parse_checksum(struct tag_head *tag, t_checksum *checksum)
checksum->checksum_data + num,
(UINT8) (i - preindex) >> (UINT8) 1))
{
// Clean up allocated memory on error
UINT16 j;
for (j = 0; j < num; j++) {
if (checksum->checksum_data[j].spec_pos != NULL) {
ir_free(checksum->checksum_data[j].spec_pos);
checksum->checksum_data[j].spec_pos = NULL;
}
}
ir_free(checksum->checksum_data);
checksum->checksum_data = NULL;
return IR_DECODE_FAILED;
}
preindex = (UINT16) (i + 1);
@@ -529,6 +577,16 @@ INT8 parse_checksum(struct tag_head *tag, t_checksum *checksum)
checksum->checksum_data + num,
(UINT8) (i - preindex) >> (UINT8) 1))
{
// Clean up allocated memory on error
UINT16 j;
for (j = 0; j <= num; j++) {
if (checksum->checksum_data[j].spec_pos != NULL) {
ir_free(checksum->checksum_data[j].spec_pos);
checksum->checksum_data[j].spec_pos = NULL;
}
}
ir_free(checksum->checksum_data);
checksum->checksum_data = NULL;
return IR_DECODE_FAILED;
}
@@ -635,18 +693,12 @@ INT8 parse_function_1_tag29(struct tag_head *tag, t_function_1 *function1)
// seg_index in TAG only refers to functional count
for (seg_index = AC_FUNCTION_POWER; seg_index < (UINT16) AC_FUNCTION_MAX; seg_index++)
{
/** WARNING: for strict mode only **/
/**
INT8 fid = parse_function_1(hex_data, &trav_offset, &function1->comp_data[0]);
if (fid > AC_FUNCTION_MAX - 1)
INT8 result = parse_function_1(hex_data, &trav_offset, &function1->comp_data[0]);
if (result == IR_DECODE_FAILED)
{
irda_free(hex_data);
hex_data = NULL;
ir_free(hex_data);
return IR_DECODE_FAILED;
}
**/
parse_function_1(hex_data, &trav_offset, &function1->comp_data[0]);
if (trav_offset >= hex_len)
{
break;
@@ -694,6 +746,13 @@ INT8 parse_temp_2(struct tag_head *tag, t_temp_2 *temp2)
temp2->len = (UINT8) hex_len;
UINT8 seg_len = hex_data[0];
// Initialize all segments to NULL to ensure proper cleanup in case of error
for (seg_index = AC_TEMP_16; seg_index < (UINT16) AC_TEMP_MAX; seg_index++)
{
temp2->comp_data[seg_index].seg_len = 0;
temp2->comp_data[seg_index].segment = NULL;
}
for (seg_index = AC_TEMP_16; seg_index < (UINT16) AC_TEMP_MAX; seg_index++)
{
// 020210 indicates set the 02nd byte to [default] +10, +11, +12, +...
@@ -701,6 +760,17 @@ INT8 parse_temp_2(struct tag_head *tag, t_temp_2 *temp2)
temp2->comp_data[seg_index].segment = (UINT8 *) ir_malloc(seg_len);
if (NULL == temp2->comp_data[seg_index].segment)
{
// Clean up previously allocated memory
UINT16 cleanup_idx;
for (cleanup_idx = AC_TEMP_16; cleanup_idx < seg_index; cleanup_idx++)
{
if (temp2->comp_data[cleanup_idx].segment != NULL)
{
ir_free(temp2->comp_data[cleanup_idx].segment);
temp2->comp_data[cleanup_idx].segment = NULL;
temp2->comp_data[cleanup_idx].seg_len = 0;
}
}
ir_free(hex_data);
return IR_DECODE_FAILED;
}
@@ -873,10 +943,30 @@ INT8 parse_swing_2(struct tag_head *tag, t_swing_2 *swing2, UINT16 swing_count)
return IR_DECODE_FAILED;
}
// Initialize the comp_data to ensure proper cleanup in case of error
for (seg_index = 0; seg_index < swing_count; seg_index++)
{
swing2->comp_data[seg_index].seg_len = 0;
swing2->comp_data[seg_index].segment = NULL;
}
for (seg_index = 0; seg_index < swing_count; seg_index++)
{
if (IR_DECODE_FAILED == parse_comp_data_type_2(hex_data, &trav_offset, &swing2->comp_data[seg_index]))
{
// Clean up any allocated memory in previous iterations
UINT16 i;
for (i = 0; i < seg_index; i++)
{
if (swing2->comp_data[i].segment != NULL)
{
ir_free(swing2->comp_data[i].segment);
swing2->comp_data[i].segment = NULL;
swing2->comp_data[i].seg_len = 0;
}
}
ir_free(swing2->comp_data);
swing2->comp_data = NULL;
ir_free(hex_data);
return IR_DECODE_FAILED;
}
@@ -993,18 +1083,12 @@ INT8 parse_function_2_tag34(struct tag_head *tag, t_function_2 *function2)
// seg_index in TAG only refers to functional count
for (seg_index = AC_FUNCTION_POWER; seg_index < (UINT16) AC_FUNCTION_MAX; seg_index++)
{
/** WARNING: for strict mode only **/
/**
INT8 fid = parse_function_2(hex_data, &trav_offset, &function2->comp_data[0]);
if (fid > AC_FUNCTION_MAX - 1)
INT8 result = parse_function_2(hex_data, &trav_offset, &function2->comp_data[0]);
if (result == IR_DECODE_FAILED)
{
irda_free(hex_data);
hex_data = NULL;
ir_free(hex_data);
return IR_DECODE_FAILED;
}
**/
parse_function_2(hex_data, &trav_offset, &function2->comp_data[0]);
if (trav_offset >= hex_len)
{
break;

View File

@@ -14,10 +14,10 @@ Revision log:
#include <string.h>
#include "include/ir_decode.h"
#include "include/ir_utils.h"
#include "include/ir_ac_build_frame.h"
#include "include/ir_ac_apply.h"
#include "ir_decode.h"
#include "ir_utils.h"
#include "ir_ac_build_frame.h"
#include "ir_ac_apply.h"
struct ir_bin_buffer binary_file;
struct ir_bin_buffer *p_ir_buffer = &binary_file;
@@ -79,18 +79,23 @@ static INT8 ir_ac_file_open(const char *file_name);
#endif
static INT8 ir_ac_binary_open(UINT8 *binary, UINT16 bin_length);
static UINT16 ir_ac_control(t_remote_ac_status ac_status, UINT16* user_data, UINT8 key_code,
BOOL change_wind_direction);
static UINT16 ir_ac_control(t_remote_ac_status *ac_status, UINT16* user_data, UINT8 key_code);
static INT8 ir_ac_binary_close();
static BOOL validate_ac_status(t_remote_ac_status* ac_status, BOOL change_wind_dir);
static BOOL validate_ac_status(t_remote_ac_status* ac_status);
#if !defined NO_FS
static INT8 ir_tv_file_open(const char *file_name);
#endif
static INT8 ir_tv_binary_open(UINT8 *binary, UINT16 bin_length);
static INT8 ir_tv_binary_parse(UINT8 ir_hex_encode);
static UINT16 ir_tv_control(UINT8 key, UINT16 *l_user_data);
static INT8 ir_tv_binary_close();
@@ -244,8 +249,7 @@ INT8 ir_binary_open(const UINT8 category, const UINT8 sub_category, UINT8* binar
}
/** the main entry of decode algorithm **/
UINT16 ir_decode(UINT8 key_code, UINT16* user_data,
t_remote_ac_status* ac_status, BOOL change_wind_direction)
UINT16 ir_decode(UINT8 key_code, UINT16* user_data, t_remote_ac_status* ac_status)
{
ir_printf("remote_category = %d, KEY_CODE_MAX = %d\n", remote_category, KEY_CODE_MAX[remote_category]);
@@ -266,21 +270,21 @@ UINT16 ir_decode(UINT8 key_code, UINT16* user_data,
return 0;
}
ir_printf("ac status is not null in decode core : power = %d, mode = %d, "
"temp = %d, wind_dir = %d, wind_speed = %d, "
"key_code = %d, change_wind_direction = %d\n",
"temp = %d, wind_dir = %d, wind_speed = %d, change_wind_direction = %d, "
"key_code = %d\n",
ac_status->ac_power, ac_status->ac_mode,
ac_status->ac_temp, ac_status->ac_wind_dir,
ac_status->ac_wind_speed,
key_code, change_wind_direction);
ac_status->change_wind_direction,
key_code);
// ac status validation
if (FALSE == validate_ac_status(ac_status, change_wind_direction)) {
if (FALSE == validate_ac_status(ac_status)) {
return 0;
}
return ir_ac_control(*ac_status, user_data, key_code, change_wind_direction);
return ir_ac_control(ac_status, user_data, key_code);
}
}
INT8 ir_close()
{
if (IR_TYPE_COMMANDS == ir_binary_type)
@@ -359,8 +363,7 @@ static INT8 ir_ac_binary_open(UINT8 *binary, UINT16 bin_length)
return IR_DECODE_SUCCEEDED;
}
static UINT16 ir_ac_control(t_remote_ac_status ac_status, UINT16* user_data, UINT8 key_code,
BOOL change_wind_direction)
static UINT16 ir_ac_control(t_remote_ac_status *ac_status, UINT16* user_data, UINT8 key_code)
{
UINT16 time_length = 0;
UINT8 function_code = 0;
@@ -402,7 +405,7 @@ static UINT16 ir_ac_control(t_remote_ac_status ac_status, UINT16* user_data, UIN
}
// pre-set change wind direction flag here
context->change_wind_direction = change_wind_direction;
context->change_wind_direction = ac_status->change_wind_direction;
context->time = user_data;
@@ -410,15 +413,16 @@ static UINT16 ir_ac_control(t_remote_ac_status ac_status, UINT16* user_data, UIN
ir_memcpy(ir_hex_code, context->default_code.data, context->default_code.len);
#if defined USE_APPLY_TABLE
if(ac_status.ac_power != AC_POWER_OFF)
if(ac_status->ac_power != AC_POWER_OFF)
{
UINT8 i;
for (i = AC_APPLY_POWER; i < AC_APPLY_MAX; i++)
{
apply_table[i](context, parameter_array[i]);
apply_table[i](ac_status, function_code);
}
}
#else
if (ac_status.ac_power == AC_POWER_OFF)
if (ac_status->ac_power == AC_POWER_OFF)
{
// otherwise, power should always be applied
apply_power(ac_status, function_code);
@@ -426,7 +430,7 @@ static UINT16 ir_ac_control(t_remote_ac_status ac_status, UINT16* user_data, UIN
else
{
// check the mode as the first priority, despite any other status
if (TRUE == context->n_mode[ac_status.ac_mode].enable)
if (TRUE == context->n_mode[ac_status->ac_mode].enable)
{
if (is_solo_function(function_code))
{
@@ -506,7 +510,7 @@ static INT8 ir_ac_binary_close()
return IR_DECODE_SUCCEEDED;
}
static BOOL validate_ac_status(t_remote_ac_status* ac_status, BOOL change_wind_dir)
static BOOL validate_ac_status(t_remote_ac_status* ac_status)
{
if (AC_POWER_OFF != ac_status->ac_power && AC_POWER_ON != ac_status->ac_power)
{
@@ -528,7 +532,7 @@ static BOOL validate_ac_status(t_remote_ac_status* ac_status, BOOL change_wind_d
{
return FALSE;
}
if (0 != change_wind_dir && 1 != change_wind_dir)
if (0 != ac_status->change_wind_direction && 1 != ac_status->change_wind_direction)
{
return FALSE;
}
@@ -776,7 +780,7 @@ static INT8 ir_tv_binary_close()
UINT16 ir_decode_combo(const UINT8 category, const UINT8 sub_category,
UINT8* binary, UINT16 bin_length,
UINT8 key_code, UINT16* user_data,
t_remote_ac_status* ac_status, BOOL change_wind_direction)
t_remote_ac_status* ac_status)
{
UINT16 decoded_length = 0;
@@ -787,6 +791,13 @@ UINT16 ir_decode_combo(const UINT8 category, const UINT8 sub_category,
return IR_DECODE_FAILED;
}
if (sub_category < SUB_CATEGORY_QUATERNARY ||
sub_category >= SUB_CATEGORY_NEXT)
{
ir_printf("wrong remote sub category : %d\n", sub_category);
return IR_DECODE_FAILED;
}
remote_category = (t_remote_category) category;
if (key_code < 0 || key_code >= KEY_CODE_MAX[remote_category])
@@ -798,7 +809,7 @@ UINT16 ir_decode_combo(const UINT8 category, const UINT8 sub_category,
if (IR_DECODE_SUCCEEDED ==
ir_binary_open(category, sub_category, binary, bin_length))
{
decoded_length = ir_decode(key_code, user_data, ac_status, change_wind_direction);
decoded_length = ir_decode(key_code, user_data, ac_status);
ir_close();
return decoded_length;
}

View File

@@ -15,9 +15,9 @@ Revision log:
#include <string.h>
#include "include/ir_defs.h"
#include "include/ir_decode.h"
#include "include/ir_tv_control.h"
#include "ir_defs.h"
#include "ir_decode.h"
#include "ir_tv_control.h"
struct buffer
@@ -249,8 +249,16 @@ static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time)
}
else if (ir_level == IRDA_LEVEL_LOW)
{
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->mask;
}
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->space;
ir_level = IRDA_LEVEL_LOW;
}
@@ -263,8 +271,16 @@ static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time)
}
else if (ir_level == IRDA_LEVEL_HIGH)
{
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->space;
}
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->mask;
ir_level = IRDA_LEVEL_HIGH;
}
@@ -278,6 +294,10 @@ static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time)
}
else if (ir_level == IRDA_LEVEL_HIGH)
{
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->space;
}
ir_level = IRDA_LEVEL_LOW;
@@ -291,6 +311,10 @@ static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time)
}
else if (ir_level == IRDA_LEVEL_LOW)
{
if (time_index + 1 > USER_DATA_SIZE) {
ir_printf("time index exceeded\n");
return;
}
ir_time[time_index++] = pcycles->mask;
}
ir_level = IRDA_LEVEL_HIGH;

View File

@@ -9,7 +9,7 @@ Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#include "include/ir_utils.h"
#include "ir_utils.h"
UINT8 char_to_hex(char chr)
{

View File

@@ -28,6 +28,7 @@
#include "configure.h"
#include "remote.h"
#include "serial_log.h"
#define WIFI_SERVER_PORT (8000)
@@ -74,21 +75,18 @@ void printWiFiStatus() {
unsigned long currentMillis = millis();
if (currentMillis - lastStatusCheck >= ALIVE_DEBUG_INTERVAL) {
IPAddress ip = WiFi.localIP();
const IPAddress ip = WiFi.localIP();
if (0 == strcmp(ip.toString().c_str(), "0.0.0.0")) {
lastStatusCheck = currentMillis;
return;
}
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
serialPrint(LOG_INFO, "Wi-Fi SSID: %s", WiFi.SSID());
Serial.print("IP address: ");
Serial.println(ip);
serialPrint(LOG_INFO, "Wi-Fi IP address: %s", ip.toString().c_str());
const long rssi = WiFi.RSSI();
Serial.print("Signal strength (RSSI): ");
Serial.print(rssi);
Serial.println(" dBm");
serialPrint(LOG_INFO, "Wi-Fi signal strength (RSSI): %ld dBm", rssi);
lastStatusCheck = currentMillis;
if (0 == wifiStatusPrinted) {
@@ -98,12 +96,20 @@ void printWiFiStatus() {
}
}
static void sendToClient(WiFiClient *client, const char* content) {
client->println(content);
client->flush();
}
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
remoteInit();
matrix.begin();
matrix.beginDraw();
@@ -117,33 +123,31 @@ void setup() {
matrix.endText(SCROLL_LEFT);
matrix.endDraw();
Serial.println("IRext Arduino example started in station mode");
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
serialPrint(LOG_INFO, "IRext Arduino example started in station mode");
serialPrint(LOG_INFO, "Attempting to connect to SSID: %s", ssid);
status = WiFi.begin(ssid, pass);
if (status == WL_CONNECTED) {
Serial.println("\nConnected to Wi-Fi");
serialPrint(LOG_INFO, "Connected to Wi-Fi");
server.begin();
}
else {
Serial.print("\nFailed to connect Wi-Fi, status: ");
Serial.println(status);
serialPrint(LOG_ERROR, "Failed to connect Wi-Fi, status: %d", status);
}
}
void onConnected(WiFiClient *client) {
client->flush();
Serial.println("Client connected");
client->println(eHello);
serialPrint(LOG_DEBUG, "Client connected");
sendToClient(client, eHello);
}
void onDisconnected(WiFiClient *client) {
remoteClose();
client->flush();
client->stop();
Serial.println("Client disconnected");
serialPrint(LOG_DEBUG, "Client disconnected");
}
void onError(WiFiClient *client) {
@@ -151,54 +155,61 @@ void onError(WiFiClient *client) {
client->stop();
}
void onCommand(const String *command, WiFiClient *client) {
void onCommand(WiFiClient *client, const String *command) {
if (command->startsWith(aHello)) {
Serial.println("Received hello command");
client->println(eBin);
client->flush();
serialPrint(LOG_DEBUG, "Received hello command");
sendToClient(client, eBin);
} else if (command->startsWith(aBin)) {
Serial.println("Received bin command");
serialPrint(LOG_DEBUG, "Received bin command");
#if !defined TEST_BIN_RECEIVE
if (remoteOpen(command->c_str()) > 0) {
client->println(eControl);
sendToClient(client, eControl);
} else {
Serial.println("Failed to parse bin command");
client->println(eError);
serialPrint(LOG_ERROR, "Failed to parse bin command");
sendToClient(client, eError);
}
#else
sendToClient(client, eControl);
#endif
} else if (command->startsWith(aControl)) {
Serial.println("Received control command");
serialPrint(LOG_DEBUG, "Received control command");
remoteControl(command->c_str());
} else if (command->startsWith(aError)) {
Serial.println("Received error command");
serialPrint(LOG_DEBUG, "Received error command");
onError(client);
}
}
void loop() {
if (WiFi.status() != WL_CONNECTED) {
Serial.print("Connection lost. Reconnecting...");
serialPrint(LOG_INFO, "Connection lost, reconnecting");
status = WiFi.begin(ssid, pass);
if (status == WL_CONNECTED) {
Serial.println("Reconnected!");
serialPrint(LOG_INFO, "Reconnected");
}
} else {
printWiFiStatus();
client = server.available();
if (client.connected()) {
if (false == clientConnected) {
if (!client || !client.connected()) {
client = server.available();
if (client) {
clientConnected = true;
onConnected(&client);
}
clientConnected = true;
}
if (client && client.connected()) {
if (client.available()) {
const String received = client.readStringUntil('\n');
Serial.println(received);
onCommand(&received, &client);
}
} else {
if (clientConnected) {
onDisconnected(&client);
String received = client.readStringUntil('\n');
received.trim();
if (received.length() > 0) {
serialPrint(LOG_VERBOSE, "Data received: %d", received.length());
onCommand(&client, &received);
}
}
} else if (clientConnected) {
onDisconnected(&client);
clientConnected = false;
client.stop();
}
}
delay(10);
}

View File

@@ -23,89 +23,229 @@
#include <Arduino.h>
#include <Base64.h>
#include <IRremote.hpp>
#include "control_command.h"
#include "utils.h"
#include "serial_log.h"
#include "ir_decode.h"
#include "remote.h"
#define REMOTE_BIN_MAX (1024)
#define REMOTE_BIN_MAX (1024)
#define ABIN_COMMAND_SEG (5)
#define SEG_ABIN_HEADER (0)
#define SEG_ABIN_CATE (1)
#define SEG_ABIN_SUBCATE (2)
#define SEG_ABIN_LENGTH (3)
#define SEG_ABIN_BIN (4)
#define ABIN_COMMAND_SEG (5)
#define ACTRL_COMMAND_SEG (3)
// global variable definitions
unsigned char *remoteBin = nullptr;
int remoteBinLen = 0;
#define SEG_ABIN_HEADER (0)
#define SEG_ABIN_CATE (1)
#define SEG_ABIN_SUBCATE (2)
#define SEG_ABIN_LENGTH (3)
#define SEG_ABIN_BIN (4)
#define SEG_ACTRL_HEADER (0)
#define SEG_ACTRL_LENGTH (1)
#define SEG_ACTRL_COMMAND (2)
#define IR_SEND_PIN 3
// external variable declarations
extern char *eError;
// private variable definitions
static uint8_t categoryId = -1;
static uint8_t subCategoryId = -1;
static unsigned char *remoteBin = nullptr;
static int remoteBinLen = 0;
static uint16_t remoteUserData[USER_DATA_SIZE] = { 0 };
static uint16_t userDataLen = 0;
// public function definitions
void remoteInit() {
IrSender.begin(IR_SEND_PIN);
}
int remoteOpen(const char *binStr) {
char *aBinCommand[ABIN_COMMAND_SEG];
char *remoteBinStr = nullptr;
int categoryId = 0;
int subCateId = 0;
int aBinCommandSeg = 0;
int remoteBinBase64Len = 0;
int retVal = 0;
aBinCommandSeg = splitString(binStr, aBinCommand, ABIN_COMMAND_SEG, ",");
if (ABIN_COMMAND_SEG != aBinCommandSeg) {
Serial.print("Invalid aBin command: ");
Serial.println(binStr);
return -1;
serialPrint(LOG_ERROR, "Invalid aBin command: %s", binStr);
retVal = -1;
goto _exit;
}
categoryId = strtol(aBinCommand[SEG_ABIN_CATE], nullptr, 10);
subCateId = strtol(aBinCommand[SEG_ABIN_SUBCATE], nullptr, 10);
subCategoryId = strtol(aBinCommand[SEG_ABIN_SUBCATE], nullptr, 10);
remoteBinBase64Len = strtol(aBinCommand[SEG_ABIN_LENGTH], nullptr, 10);
remoteBinStr = aBinCommand[SEG_ABIN_BIN];
if (remoteBinBase64Len != strlen(remoteBinStr)) {
Serial.println("Remote bin length not correct");
return -1;
serialPrint(LOG_ERROR, "Remote bin length not correct, expected : %d, decoded : %d",
remoteBinBase64Len, remoteBinLen);
retVal = -1;
goto _exit;
}
remoteBinLen = base64_dec_len(remoteBinStr, remoteBinBase64Len);
// free the previously used buffer
if (nullptr != remoteBin) {
free(remoteBin);
remoteBin = nullptr;
}
remoteBin = static_cast<unsigned char*>(malloc(remoteBinLen));
char debugStr[129];
if (nullptr == remoteBin) {
Serial.println("Not enough memory for remote bin");
return -1;
serialPrint(LOG_ERROR, "Not enough memory for remote bin");
retVal = -1;
goto _exit;
}
memset(remoteBin, 0, remoteBinLen);
if (remoteBinLen != base64_decode(reinterpret_cast<char*>(remoteBin), remoteBinStr, remoteBinBase64Len)) {
Serial.println("Failed to decode remote bin");
return -1;
serialPrint(LOG_ERROR, "Failed to decode remote bin");
retVal = -1;
goto _exit;
}
#if defined REMOTE_BIN_DEBUG
Serial.print("Remote bin length = ");
Serial.println(remoteBinLen);
snprintf(debugStr, 128, "%02x %02x %02x %02x %02x %02x %02x %02x",
remoteBin[0], remoteBin[1], remoteBin[2], remoteBin[3],
remoteBin[4], remoteBin[5], remoteBin[6], remoteBin[7]);
Serial.println(debugStr);
snprintf(debugStr, 128, "%02x %02x %02x %02x %02x %02x %02x %02x",
remoteBin[remoteBinLen - 8], remoteBin[remoteBinLen - 7], remoteBin[remoteBinLen - 6], remoteBin[remoteBinLen - 5],
remoteBin[remoteBinLen - 4], remoteBin[remoteBinLen - 3], remoteBin[remoteBinLen - 2], remoteBin[remoteBinLen - 1]);
Serial.println(debugStr);
#endif
if (IR_DECODE_FAILED == ir_binary_open(categoryId, subCateId, remoteBin, remoteBinLen)) {
Serial.println("Failed to load remote bin");
return -1;
if (getLogLevel() == LOG_VERBOSE) {
char debugStr[129] = { 0 };
serialPrint(LOG_VERBOSE, "Remote bin(%d): ", remoteBinLen);
snprintf(debugStr, 128, "%02x %02x %02x %02x %02x %02x %02x %02x",
remoteBin[0], remoteBin[1], remoteBin[2], remoteBin[3],
remoteBin[4], remoteBin[5], remoteBin[6], remoteBin[7]);
serialPrint(LOG_VERBOSE, debugStr);
snprintf(debugStr, 128, "%02x %02x %02x %02x %02x %02x %02x %02x",
remoteBin[remoteBinLen - 8], remoteBin[remoteBinLen - 7], remoteBin[remoteBinLen - 6], remoteBin[remoteBinLen - 5],
remoteBin[remoteBinLen - 4], remoteBin[remoteBinLen - 3], remoteBin[remoteBinLen - 2], remoteBin[remoteBinLen - 1]);
serialPrint(LOG_VERBOSE, debugStr);
}
Serial.println("Remote bin loaded successfully");
return remoteBinLen;
if (IR_DECODE_FAILED == ir_binary_open(categoryId, subCategoryId, remoteBin, remoteBinLen)) {
serialPrint(LOG_ERROR, "Failed to load remote bin");
retVal = -1;
goto _exit;
}
retVal = remoteBinLen;
serialPrint(LOG_INFO, "Remote bin loaded successfully");
_exit:
return retVal;
}
int remoteControl(const char *controlStr) {
return 0;
char *aCtrlCommand[ACTRL_COMMAND_SEG];
char *commandStrBase64 = nullptr;
char *commandStr = nullptr;
int aCtrlCommandSeg = 0;
int commandBase64Len = 0;
int commandLen = 0;
t_remote_ac_status acStatus;
int keyCode = 0;
int retVal = 0;
aCtrlCommandSeg = splitString(controlStr, aCtrlCommand, ACTRL_COMMAND_SEG, ",");
if (ACTRL_COMMAND_SEG != aCtrlCommandSeg) {
serialPrint(LOG_ERROR, "Invalid aCtrl command: ");
retVal = -1;
goto _exit;
}
commandBase64Len = strtol(aCtrlCommand[SEG_ACTRL_LENGTH], nullptr, 10);
commandStrBase64 = aCtrlCommand[SEG_ACTRL_COMMAND];
if (commandBase64Len != strlen(commandStrBase64)) {
serialPrint(LOG_ERROR, "Remote command length not correct, expected : %d, decoded : %d",
commandBase64Len, commandStrBase64);
retVal = -1;
goto _exit;
}
commandLen = base64_dec_len(commandStrBase64, commandBase64Len);
commandStr = static_cast<char*>(malloc(commandLen));
if (nullptr == commandStr) {
serialPrint(LOG_ERROR, "Not enough memory for remote command");
retVal = -1;
goto _exit;
}
memset(commandStr, 0, commandLen);
if (commandLen != base64_decode(commandStr, commandStrBase64, commandBase64Len)) {
serialPrint(LOG_ERROR, "Failed to decode remote command");
retVal = -1;
goto _exit;
}
serialPrint(LOG_DEBUG, "Received remote command: %s", commandStr);
if (-1 != categoryId) {
if (0 != parseControlCommand(categoryId, commandStr, &acStatus, &keyCode)) {
serialPrint(LOG_ERROR, "Failed to parse command JSON");
retVal = -1;
goto _exit;
}
} else {
serialPrint(LOG_ERROR, "No remote bin loaded");
retVal = - 1;
goto _exit;
}
userDataLen = ir_decode(keyCode, remoteUserData, &acStatus);
if (userDataLen > 0) {
serialPrint(LOG_INFO, "IR decoded successfully: %d", userDataLen);
}
if (getLogLevel() == LOG_VERBOSE) {
remoteDebug(remoteUserData, userDataLen);
}
IrSender.sendRaw(remoteUserData, userDataLen, 38);
serialPrint(LOG_INFO, "IR sent successfully");
retVal = 0;
_exit:
if (nullptr != commandStr) {
free(commandStr);
}
return retVal;
}
void remoteClose() {
serialPrint(LOG_INFO, "Closing remote");
ir_close();
}
// private function definitions
void remoteDebug(const uint16_t* userData, const uint16_t userDataLen) {
if (userData == nullptr || userDataLen == 0) {
serialPrint(LOG_VERBOSE, "userData is empty or null");
return;
}
char debugStr[256] = { 0 };
int offset = 0;
for (uint16_t i = 0; i < userDataLen; i++) {
if (i % 16 == 0) {
offset = snprintf(debugStr, sizeof(debugStr), "userData[%d-%d]: ",
i, (i + 15 < userDataLen) ? i + 15 : userDataLen - 1);
}
offset += snprintf(debugStr + offset, sizeof(debugStr) - offset, "%d ", userData[i]);
if ((i + 1) % 16 == 0 || i == userDataLen - 1) {
serialPrint(LOG_VERBOSE, "%s", debugStr);
offset = 0;
}
}
}
int irControlSend() {
}

View File

@@ -24,7 +24,11 @@
#ifndef ARDUINO_EXAMPLE_REMOTE_H
#define ARDUINO_EXAMPLE_REMOTE_H
#define REMOTE_BIN_DEBUG (1)
#ifdef __cplusplus
extern "C" {
#endif
void remoteInit();
int remoteOpen(const char *binStr);
@@ -32,4 +36,9 @@ int remoteControl(const char *controlStr);
void remoteClose();
#endif //ARDUINO_EXAMPLE_REMOTE_H
void remoteDebug(const uint16_t* userData, uint16_t userDataLen);
#ifdef __cplusplus
}
#endif
#endif // ARDUINO_EXAMPLE_REMOTE_H

View File

@@ -0,0 +1,59 @@
/**
*
* Copyright (c) 2020-2025 IRext Opensource Organization
*
* 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 <Arduino.h>
#include <cstdarg>
#include <cstdio>
#include <cstring>
#include "serial_log.h"
#define LOG_BUF_SIZE (128)
// public variable definitions
int logLevel = LOG_VERBOSE;
char logBuf[LOG_BUF_SIZE] = { 0 };
// public function definitions
void serialPrint(const int logType, const char* fmt, ...) {
if (logType < logLevel) {
return;
}
memset(logBuf, 0, LOG_BUF_SIZE);
va_list ap;
va_start(ap, fmt);
vsnprintf(logBuf, LOG_BUF_SIZE, fmt, ap);
va_end(ap);
Serial.println(logBuf);
}
void setLogLevel(const int level) {
logLevel = level;
}
int getLogLevel() {
return logLevel;
}

View File

@@ -0,0 +1,45 @@
/**
*
* Copyright (c) 2020-2025 IRext Opensource Organization
*
* 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 ARDUINO_EXAMPLE_SERIAL_LOG_H
#define ARDUINO_EXAMPLE_SERIAL_LOG_H
#define LOG_VERBOSE (0)
#define LOG_DEBUG (1)
#define LOG_INFO (2)
#define LOG_ERROR (3)
#ifdef __cplusplus
extern "C" {
#endif
void serialPrint(int logType, const char* fmt, ...);
void setLogLevel(int level);
int getLogLevel();
#ifdef __cplusplus
}
#endif
#endif // ARDUINO_EXAMPLE_SERIAL_LOG_H

View File

@@ -22,9 +22,9 @@
*/
#include <Arduino.h>
#include <cstring>
#include "utils.h"
// public function definitions
int splitString(const char *str, char *parts[],

View File

@@ -24,7 +24,15 @@
#ifndef ARDUINO_EXAMPLE_UTILS_H
#define ARDUINO_EXAMPLE_UTILS_H
#ifdef __cplusplus
extern "C" {
#endif
int splitString(const char *str, char *parts[],
int parts_max, const char *delimiter);
#ifdef __cplusplus
}
#endif
#endif //ARDUINO_EXAMPLE_UTILS_H