diff --git a/app/stm32fxxx_app/app/comm_manager.c b/app/stm32fxxx_app/app/comm_manager.c
index 4dee4a8..de729a4 100644
--- a/app/stm32fxxx_app/app/comm_manager.c
+++ b/app/stm32fxxx_app/app/comm_manager.c
@@ -312,8 +312,8 @@ void bms_init_comm(void)
drv_uart_set_interrupt(EXTER_UART1_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, exter_uart1_rx_it_call);
drv_uart_set_interrupt(EXTER_UART2_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, exter_uart2_rx_it_call);
- drv_uart_set_interrupt(SIM_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, sim_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2
-
+ //设置接收回调函数
+ //drv_uart_set_interrupt(SIM_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, sim_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2
drv_can_init(INTER_CAN_PORT, 250, kGpioType_Can_Ch1_Rx, kGpioType_Can_Ch1_Tx);
drv_can_set_interrupt(INTER_CAN_PORT, kcan_interrupt_e_Rx, APP_CFG_INT_PRIO_CAN1_RX, inter_can_rx_it_call);
diff --git a/app/stm32fxxx_app/app/gpio_manager.c b/app/stm32fxxx_app/app/gpio_manager.c
index 85dcfcb..9999a19 100644
--- a/app/stm32fxxx_app/app/gpio_manager.c
+++ b/app/stm32fxxx_app/app/gpio_manager.c
@@ -50,8 +50,8 @@ const GpioArray io_array[kGpioType_End] =
kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 1), kGpioPort_A, kGpioPin_1, //rs485A Rx(mcu uart4)
kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 0), kGpioPort_A, kGpioPin_0, //rs485A Tx(mcu uart4)
- kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 2), kGpioPort_A, kGpioPin_2, //SIM UART Rx(mcu uart2)
- kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 3), kGpioPort_A, kGpioPin_3, //SIM UART Tx(mcu uart2)
+ kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 2), kGpioPort_A, kGpioPin_2, //Sim卡/wifi/ble Rx(mcu uart2)
+ kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 3), kGpioPort_A, kGpioPin_3, //Sim卡/wifi/ble Tx(mcu uart2)
/*CAN枚举*/
kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 11), kGpioPort_A, kGpioPin_11, //can1 rx
diff --git a/app/stm32fxxx_app/app/gpio_manager.h b/app/stm32fxxx_app/app/gpio_manager.h
index 2b3cf66..0ad958a 100644
--- a/app/stm32fxxx_app/app/gpio_manager.h
+++ b/app/stm32fxxx_app/app/gpio_manager.h
@@ -57,8 +57,8 @@ typedef enum
kGpioType_Rs485_Ch3_Rx,
kGpioType_Rs485_Ch3_Tx,
- kGpioType_SIMUart_Rx, //Sim卡
- kGpioType_SIMUart_Tx, //Sim卡
+ kGpioType_WIRELESSUart_Rx, //Sim卡/wifi/ble
+ kGpioType_WIRELESSUart_Tx, //Sim卡/wifi/ble
/*CAN枚举*/
kGpioType_Can_Ch1_Rx,
diff --git a/app/stm32fxxx_app/app/iso_check.c b/app/stm32fxxx_app/app/iso_check.c
index a3e7720..7b55140 100644
--- a/app/stm32fxxx_app/app/iso_check.c
+++ b/app/stm32fxxx_app/app/iso_check.c
@@ -104,7 +104,7 @@ static bool is_volt_ad_stable(int32_t *buf, uint16_t len, uint16_t aim_rate)
min = buf[i];
}
}
- //KIT_DEBUG_PRINTF("iso ad %d %d %d\r\n", max, min, (max - min) * 10000 / min);
+ //KIT_PRINTF("iso ad %d %d %d\r\n", max, min, (max - min) * 10000 / min);
if((min > 0) && (((int64_t)(max - min) * 10000 / min) < aim_rate))
{
res = true;
@@ -126,13 +126,13 @@ void insu_sample_calc_insu_res(void)
{
if (iso_item.v2 <= iso_item.v1)
{
- KIT_DEBUG_PRINTF("iso err v1 %d v2 %d\r\n", iso_item.v1, iso_item.v2);
+ KIT_PRINTF("iso err v1 %d v2 %d\r\n", iso_item.v1, iso_item.v2);
iso_item.v2 = iso_item.v1 + 1;
}
if (iso_item.v3 >= iso_item.v1)
{
- KIT_DEBUG_PRINTF("iso err v1 %d v3 %d\r\n", iso_item.v1, iso_item.v3);
+ KIT_PRINTF("iso err v1 %d v3 %d\r\n", iso_item.v1, iso_item.v3);
iso_item.v3 = iso_item.v1 - 1;
}
@@ -153,7 +153,7 @@ void insu_sample_calc_insu_res(void)
}
else
{
- KIT_DEBUG_PRINTF("iso pos neg\r\n");
+ KIT_PRINTF("iso pos neg\r\n");
}
tmp = 4 * v0v3 - 2 * v0v1 - v1v3;
@@ -166,7 +166,7 @@ void insu_sample_calc_insu_res(void)
}
else
{
- KIT_DEBUG_PRINTF("iso neg neg\r\n");
+ KIT_PRINTF("iso neg neg\r\n");
}
// iso_item.data[kIsoData_Res] = (iso_item.data[kIsoData_PosRes] > iso_item.data[kIsoData_NegRes]) ? iso_item.data[kIsoData_NegRes] : iso_item.data[kIsoData_PosRes];
@@ -187,8 +187,8 @@ void insu_sample_calc_insu_res(void)
iso_item.data[kIsoData_Res] = (iso_item.data[kIsoData_PosRes] > iso_item.data[kIsoData_NegRes]) ? iso_item.data[kIsoData_NegRes] : iso_item.data[kIsoData_PosRes];
iso_item.data[kIsoData_Value] = (iso_item.data[kIsoData_PosValue] > iso_item.data[kIsoData_NegValue]) ? iso_item.data[kIsoData_NegValue] : iso_item.data[kIsoData_PosValue];
- KIT_DEBUG_PRINTF("iso %d %d %d %d\r\n", iso_item.v0, iso_item.v1, iso_item.v2, iso_item.v3);
- KIT_DEBUG_PRINTF("iso pos %d neg %d\r\n", iso_item.data[kIsoData_PosRes], iso_item.data[kIsoData_NegRes]);
+ KIT_PRINTF("iso %d %d %d %d\r\n", iso_item.v0, iso_item.v1, iso_item.v2, iso_item.v3);
+ KIT_PRINTF("iso pos %d neg %d\r\n", iso_item.data[kIsoData_PosRes], iso_item.data[kIsoData_NegRes]);
}
}
}
@@ -216,13 +216,13 @@ void bms_poll_iso(uint32_t base_time)
{
iso_item.dly = 0;
iso_item.step = kIsoStep_TotalVolt;
- KIT_DEBUG_PRINTF("iso tv \r\n");
+ KIT_PRINTF("iso tv \r\n");
}
break;
case kIsoStep_TotalVolt:
if ((is_volt_ad_stable(iso_item.ad_buf[kIsoVolt_TotalVolt], ISO_SAMPLE_CNT, ISO_STABLE_AD_RATE) == true) || (iso_item.dly >= ISO_SAMPLE_TIME_MAX))
{
- KIT_DEBUG_PRINTF("iso tv %d\r\n", iso_item.dly);
+ KIT_PRINTF("iso tv %d\r\n", iso_item.dly);
ISO_S1_ON();
iso_item.dly = 0;
iso_item.step = kIsoStep_IsoVolt;
@@ -233,7 +233,7 @@ void bms_poll_iso(uint32_t base_time)
if (((is_volt_ad_stable(iso_item.ad_buf[kIsoVolt_Other], ISO_SAMPLE_CNT, ISO_STABLE_AD_RATE) == true) || (iso_item.dly >= ISO_SAMPLE_TIME_MAX))
&& (iso_item.dly >= ISO_SAMPLE_TIME_MIN))
{
- KIT_DEBUG_PRINTF("iso iv %d\r\n", iso_item.dly);
+ KIT_PRINTF("iso iv %d\r\n", iso_item.dly);
ISO_S2_ON();
iso_item.dly = 0;
iso_item.step = kIsoStep_PosVolt;
@@ -244,7 +244,7 @@ void bms_poll_iso(uint32_t base_time)
if (((is_volt_ad_stable(iso_item.ad_buf[kIsoVolt_Other], ISO_SAMPLE_CNT, ISO_STABLE_AD_RATE) == true) || (iso_item.dly >= ISO_SAMPLE_TIME_MAX))
&& (iso_item.dly >= ISO_SAMPLE_TIME_MIN))
{
- KIT_DEBUG_PRINTF("iso pv %d\r\n", iso_item.dly);
+ KIT_PRINTF("iso pv %d\r\n", iso_item.dly);
ISO_S2_OFF();
ISO_S3_ON();
iso_item.dly = 0;
@@ -257,7 +257,7 @@ void bms_poll_iso(uint32_t base_time)
if (((is_volt_ad_stable(iso_item.ad_buf[kIsoVolt_Other], ISO_SAMPLE_CNT, ISO_STABLE_AD_RATE) == true) || (iso_item.dly >= ISO_SAMPLE_TIME_MAX))
&& (iso_item.dly >= ISO_SAMPLE_TIME_MIN))
{
- KIT_DEBUG_PRINTF("iso nv %d\r\n", iso_item.dly);
+ KIT_PRINTF("iso nv %d\r\n", iso_item.dly);
ISO_S3_OFF();
iso_item.dly = 0;
iso_item.v3 = kit_get_int32_avg_filter_max_min(iso_item.ad_buf[kIsoVolt_Other], ISO_SAMPLE_CNT);
diff --git a/app/stm32fxxx_app/app/main.c b/app/stm32fxxx_app/app/main.c
index 093e2ff..76ddc9e 100644
--- a/app/stm32fxxx_app/app/main.c
+++ b/app/stm32fxxx_app/app/main.c
@@ -14,7 +14,7 @@ int main()
{
__disable_irq();
- KIT_DEBUG_PRINTF("bcu start \r\n");
+ KIT_PRINTF("bcu start \r\n");
drv_clk_set_system_tick(APP_CFG_INT_PRIO_SYSTICK, 1, ucos_irq_handler);
OS_TRACE_INIT();
diff --git a/app/stm32fxxx_app/app/ocv_tables.c b/app/stm32fxxx_app/app/ocv_tables.c
index 80cf973..8ae41ce 100644
--- a/app/stm32fxxx_app/app/ocv_tables.c
+++ b/app/stm32fxxx_app/app/ocv_tables.c
@@ -63,13 +63,13 @@ uint16_t bms_check_pwr_on_ocv(uint16_t soc)
uint32_t now_time = drv_rtc_get_tick();
uint32_t last_time = get_eeprom_data(kEep_PowerOffTimeL, kEepromDataType_Double);
uint32_t standby_time = (uint32_t)get_eeprom_data(kEep_OcvStandbyCur_Time, kEepromDataType_Low) * 360;
- KIT_DEBUG_PRINTF("OCV Last Time:%d \r\n", last_time);
- KIT_DEBUG_PRINTF("OCV Now Time:%d \r\n", now_time);
+ KIT_PRINTF("OCV Last Time:%d \r\n", last_time);
+ KIT_PRINTF("OCV Now Time:%d \r\n", now_time);
if((standby_time != 0) && (now_time > last_time)
&& ((now_time - last_time) >= standby_time))
{
ocv_dly = standby_time * 1000 - KIT_SECOND_CONVERT(30);
- KIT_DEBUG_PRINTF("Power On OCV\r\n");
+ KIT_PRINTF("Power On OCV\r\n");
soc = bms_check_ocv(soc);
}
return soc;
diff --git a/app/stm32fxxx_app/app/task_register.c b/app/stm32fxxx_app/app/task_register.c
index 5f66ed6..bacf97f 100644
--- a/app/stm32fxxx_app/app/task_register.c
+++ b/app/stm32fxxx_app/app/task_register.c
@@ -17,7 +17,7 @@ const uint8_t tcp_server_task_name[W5500_MODBUS_NUM][14] =
void poll_1ms_task_init(void);
void poll_10ms_task_init(void);
-
+void poll_mqtt_init(void);
bool is_first_run = false;
static int a = 0;
@@ -48,6 +48,12 @@ void bms_poll_bmu_handler(uint32_t base_time)
bms_poll_bmu(base_time);
}
+void task_mqtt_handler(uint32_t base_time)
+{
+ mqtt_publish_bms_data(base_time);
+}
+
+
void task_100ms_handler(uint32_t base_time)
{
static uint32_t cout100ms = 0;
@@ -76,6 +82,8 @@ GLOBAL_TASK_VARS_CCM(modbus_rtu_task3, 8, 50, 5000, 400, NULL,
GLOBAL_TASK_VARS_CCM(ord_comm_can_task, 5, 100, 5000, 400, NULL, task_can1_handler, NULL);
GLOBAL_TASK_VARS_CCM(bms_poll_bmu_task, 9, 100, 5000, 400, bms_bmu_init, bms_poll_bmu_handler, NULL);
+GLOBAL_TASK_VARS_CCM(bms_poll_mqtt_task, 9, 1000, 5000, 400, poll_mqtt_init, task_mqtt_handler, NULL);
+
#define BMU_FINISH_BIT (0u)
#define SIGNAL_FINISH_BIT (1u)
@@ -106,26 +114,26 @@ void poll_1ms_task_init(void)
bms_init_di_do(bmsCircuitCtrl, kDoCtrlStrategy_End, doLogicArray);
bsp_create_task(&poll_10ms_task, (uint8_t *)"10ms");
- //KIT_DEBUG_PRINTF("cur_hv init start \r\n");
+ //KIT_PRINTF("cur_hv init start \r\n");
//debug here is no more run
bms_init_cur_hv();
- //KIT_DEBUG_PRINTF("cur_hv init ok \r\n");
+ //KIT_PRINTF("cur_hv init ok \r\n");
while(KIT_GET_BIT_32(is_data_ok, BMU_FINISH_BIT) == 0)
{
bsp_task_delay_ms(10);
}
//ʱʼ 300ms ȷź
- //KIT_DEBUG_PRINTF("signal init start \r\n");
+ //KIT_PRINTF("signal init start \r\n");
bms_poll_statistic(0);
bms_init_signal();
//ˢźŲ ȷ糣յҪպdo
task_dido_ctrl_handle(1000);
- //KIT_DEBUG_PRINTF("signal init ok \r\n");
+ //KIT_PRINTF("signal init ok \r\n");
KIT_SET_BIT_MASK_32(is_data_ok, SIGNAL_FINISH_BIT);
bsp_create_task(&ord_ctrl_task, (uint8_t *)"ctrl");
@@ -138,9 +146,9 @@ void poll_10ms_task_init(void)
uint8_t i = 0;
bms_init_fdb();
//ʱʼ ȴӻϵ粢ʼ 500ms 1300ms()
- KIT_DEBUG_PRINTF("bmu init start \r\n");
+ KIT_PRINTF("bmu init start \r\n");
//bms_init_chain_bmu();
- KIT_DEBUG_PRINTF("bmu init ok \r\n");
+ KIT_PRINTF("bmu init ok \r\n");
bms_poll_statistic(0);
//SOCʼҪͳ
bms_init_soc();
@@ -153,7 +161,7 @@ void poll_10ms_task_init(void)
{
bsp_task_delay_ms(10);
}
- KIT_DEBUG_PRINTF("data init ok \r\n");
+ KIT_PRINTF("data init ok \r\n");
protocol_comm_init();
@@ -182,7 +190,25 @@ void poll_10ms_task_init(void)
}
+void poll_mqtt_init(void)
+{
+ static uint16_t qfc41d_init_count = 0;
+ static uint16_t mqtt_init_count = 0;
+ while(drv_qfc41d_init() && qfc41d_init_count < 10)
+ {
+ drv_wdog_feed();
+ kit_time_dly_ms(100);
+ qfc41d_init_count++;
+ }
+ // MQTT ʼ
+ while(drv_mqtt_init()&& mqtt_init_count < 10)
+ {
+ drv_wdog_feed();
+ kit_time_dly_ms(100);
+ mqtt_init_count++;
+ }
+}
/*****************************************************************************
* @brief ucosϵͳжϻص
* @param[in] void:
diff --git a/app/stm32fxxx_app/app/task_register.h b/app/stm32fxxx_app/app/task_register.h
index 20c033e..c10191f 100644
--- a/app/stm32fxxx_app/app/task_register.h
+++ b/app/stm32fxxx_app/app/task_register.h
@@ -40,7 +40,7 @@ extern "C" {
#include "hv_adc_manager.h"
#include "ucos_ii.h"
#include "cpu_core.h"
-
+#include "drv_wdog.h"
#include "os_cpu.h"
#include "kit_debug.h"
@@ -48,7 +48,7 @@ extern "C" {
#include "bmu_manager.h"
#include "bmu_adbms1818.h"
#include "protocol_comm.h"
-
+#include "protocol_mqtt_bcu.h"
typedef void (*SN_BMS_INIT_CALL)(uint32_t base_time);
int sn_bms_init(SN_BMS_INIT_CALL call);
diff --git a/app/stm32fxxx_app/prj/BCU_APP.uvprojx b/app/stm32fxxx_app/prj/BCU_APP.uvprojx
index 63cee65..9bcd3d5 100644
--- a/app/stm32fxxx_app/prj/BCU_APP.uvprojx
+++ b/app/stm32fxxx_app/prj/BCU_APP.uvprojx
@@ -50,7 +50,7 @@
1
.\Objects\
- BCU_APP2
+ BCU_APP
1
0
1
@@ -340,7 +340,7 @@
STM32F40_41xxx,APP_START_ADDR = 0x08020000,UCOS2,BSE1B,ADS_8688_EN
- ..\app;..\..\..\library\bsp;..\..\..\library\core;..\..\..\library\kit;..\..\..\library\drv_peripheral;..\ord;..\..\..\library\drv_stm32f4xx;..\..\..\library\J1939;..\protocol;..\..\..\library\ucos\uC-OS2\Source;..\..\..\library\ucos\uC-OS2\Ports\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-OS2\Cfg\Template;..\..\..\library\ucos\uC-CPU\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-CPU\Cfg\Template;..\..\..\library\ucos\uC-CPU\Template;..\..\..\library\ucos\uC-CPU;..\..\..\library\ucos\uC-LIB;..\..\..\library\ucos\uC-LIB\Cfg\Template;..\..\..\library\ucos\uC-LIB\Ports\ARM-Cortex-M4\RealView;..\..\..\library\ucos;..\..\..\library\segger\Config;..\..\..\library\segger\Sample\uCOS-II;..\..\..\library\segger\Sample\uCOS-II\Config;..\..\..\library\segger\SEGGER;..\table
+ ..\app;..\..\..\library\bsp;..\..\..\library\core;..\..\..\library\kit;..\..\..\library\drv_peripheral;..\ord;..\..\..\library\drv_stm32f4xx;..\..\..\library\J1939;..\protocol;..\..\..\library\ucos\uC-OS2\Source;..\..\..\library\ucos\uC-OS2\Ports\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-OS2\Cfg\Template;..\..\..\library\ucos\uC-CPU\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-CPU\Cfg\Template;..\..\..\library\ucos\uC-CPU\Template;..\..\..\library\ucos\uC-CPU;..\..\..\library\ucos\uC-LIB;..\..\..\library\ucos\uC-LIB\Cfg\Template;..\..\..\library\ucos\uC-LIB\Ports\ARM-Cortex-M4\RealView;..\..\..\library\ucos;..\..\..\library\segger\Config;..\..\..\library\segger\Sample\uCOS-II;..\..\..\library\segger\Sample\uCOS-II\Config;..\..\..\library\segger\SEGGER;..\table;..\..\..\library\cjson
@@ -638,6 +638,11 @@
1
..\..\..\library\drv_peripheral\drv_eg25gminipice.c
+
+ drv_qfc41d.c
+ 1
+ ..\..\..\library\drv_peripheral\drv_qfc41d.c
+
@@ -1032,6 +1037,21 @@
1
..\protocol\protocol_modbus_bcu.c
+
+ protocol_mqtt_bcu.c
+ 1
+ ..\protocol\protocol_mqtt_bcu.c
+
+
+
+
+ Cjson
+
+
+ cJSON.c
+ 1
+ ..\..\..\library\cjson\cJSON.c
+
@@ -1599,6 +1619,11 @@
1
..\..\..\library\drv_peripheral\drv_eg25gminipice.c
+
+ drv_qfc41d.c
+ 1
+ ..\..\..\library\drv_peripheral\drv_qfc41d.c
+
@@ -1924,6 +1949,21 @@
1
..\protocol\protocol_modbus_bcu.c
+
+ protocol_mqtt_bcu.c
+ 1
+ ..\protocol\protocol_mqtt_bcu.c
+
+
+
+
+ Cjson
+
+
+ cJSON.c
+ 1
+ ..\..\..\library\cjson\cJSON.c
+
@@ -1943,4 +1983,13 @@
+
+
+
+ BCU_APP
+ 1
+
+
+
+
diff --git a/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c
new file mode 100644
index 0000000..c7f01e5
--- /dev/null
+++ b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c
@@ -0,0 +1,107 @@
+/******************************************************************************
+ * @file protocol_mqtt_bcu.c
+ * @brief protocol_mqtt_bcu
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+
+#include "protocol_mqtt_bcu.h"
+
+//밴ģ
+const devPointMap bms_points[] = {
+ {"BCU_2", 0, 0, NULL}, // ܸ澯
+ {"BCU_3", 0, 0, NULL}, // ܹ
+ {"BCU_4", 0, 0, NULL}, // ѹ澯һ
+ {"BCU_5", 0, 0, NULL}, // Ƿѹ澯һ
+ {"BCU_6", 0, 0, NULL}, // ¸澯һ
+ {"BCU_7", 0, 0, NULL}, // ¸澯һ
+ {"BCU_8", 0, 0, NULL}, // ѹ澯һ
+ {"BCU_9", 0, 0, NULL}, // 澯һ
+};
+
+const int bms_point_count = sizeof(bms_points) / sizeof(bms_points[0]);
+
+void protocol_build_json(uint16_t groupId)
+{
+ int val = 0;
+ cJSON* root = cJSON_CreateObject();
+
+ cJSON_AddNumberToObject(root, "timeStamp", drv_rtc_get_tick());
+
+ // devData
+ cJSON* devDataArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(root, "devData", devDataArr);
+
+ // ÿһ豸
+ cJSON* deviceObj = cJSON_CreateObject();
+ cJSON_AddItemToArray(devDataArr, deviceObj);
+
+ cJSON_AddStringToObject(deviceObj, "devType", "4");
+ cJSON_AddStringToObject(deviceObj, "devName", "BCU");
+ cJSON_AddStringToObject(deviceObj, "devId", "001");
+ cJSON_AddStringToObject(deviceObj, "sn", "SN123456");
+
+ // data
+ cJSON* dataObj = cJSON_CreateObject();
+ cJSON_AddItemToObject(deviceObj, "data", dataObj);
+
+ for (int i = 0; i < bms_point_count; ++i)
+ {
+ const devPointMap* point = &bms_points[i];
+ if(point->groupId == groupId)
+ {
+ if (bms_points[i].get_val != NULL)
+ {
+ val = point->get_val(point->input);
+ }
+ else
+ {
+ val = 0; // Ĭֵ
+ }
+ }
+ cJSON_AddNumberToObject(dataObj, point->key, val);
+ }
+
+ // תΪ JSON ַ
+ char* json_str = cJSON_PrintUnformatted(root);
+ if (json_str)
+ {
+ drv_mqtt_publish(json_str, strlen(json_str));
+ cJSON_free(json_str);
+ }
+
+ cJSON_Delete(root);
+}
+
+
+void publish_all_bms_groups(void) {
+ uint8_t max_group = 0;
+
+ for (size_t i = 0; i < bms_point_count; i++) {
+ if (bms_points[i].groupId > max_group) {
+ max_group = bms_points[i].groupId;
+ }
+ }
+
+ for (uint8_t g = 0; g <= max_group; g++) {
+ protocol_build_json(g);
+ }
+}
+
+void mqtt_publish_bms_data(uint32_t basetime)
+{
+ static uint32_t mqtt_cycle_tick = 0;
+ static uint8_t groupMax = 0;
+ uint16_t i = 0;
+
+ mqtt_cycle_tick += basetime;
+
+ if(mqtt_cycle_tick > 60000)
+ {
+ mqtt_cycle_tick = 0;
+ publish_all_bms_groups();
+ }
+
+}
+
diff --git a/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c.orig b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c.orig
new file mode 100644
index 0000000..3ddcdda
--- /dev/null
+++ b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.c.orig
@@ -0,0 +1,93 @@
+/******************************************************************************
+ * @file protocol_mqtt_bcu.c
+ * @brief protocol_mqtt_bcu
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+
+#include "protocol_mqtt_bcu.h"
+
+
+const devPointMap bms_points[] = {
+ {"BCU_2", NULL}, // ܸ澯
+ {"BCU_3", NULL}, // ܹ
+ {"BCU_4", NULL}, // ѹ澯һ
+ {"BCU_5", NULL}, // Ƿѹ澯һ
+ {"BCU_6", NULL}, // ¸澯һ
+ {"BCU_7", NULL}, // ¸澯һ
+ {"BCU_8", NULL}, // ѹ澯һ
+ {"BCU_9", NULL}, // 澯һ
+};
+
+const int bms_point_count = sizeof(bms_points) / sizeof(bms_points[0]);
+
+char* protocol_build_json(void)
+{
+ cJSON* root = cJSON_CreateObject();
+ if (!root) return NULL;
+
+ // ʱֶΣ˴滻ʵʱ亯
+ cJSON_AddNumberToObject(root, "timeStamp", drv_rtc_get_tick());
+
+ // devData
+ cJSON* devDataArr = cJSON_CreateArray();
+ cJSON_AddItemToObject(root, "devData", devDataArr);
+
+ // ÿһ豸
+ cJSON* deviceObj = cJSON_CreateObject();
+ cJSON_AddItemToArray(devDataArr, deviceObj);
+
+ cJSON_AddStringToObject(deviceObj, "devType", "BMS");
+ cJSON_AddStringToObject(deviceObj, "devName", "BCU");
+ cJSON_AddStringToObject(deviceObj, "devId", "001");
+ cJSON_AddStringToObject(deviceObj, "sn", "SN123456");
+
+ // data
+ cJSON* dataObj = cJSON_CreateObject();
+ cJSON_AddItemToObject(deviceObj, "data", dataObj);
+
+ for (int i = 0; i < bms_point_count; ++i)
+ {
+ const char* key = bms_points[i].key;
+ int val = 0;
+
+ if (bms_points[i].get_val != NULL)
+ {
+ val = bms_points[i].get_val();
+ }
+ else
+ {
+ val = 0; // Ĭֵ
+ }
+
+ cJSON_AddNumberToObject(dataObj, key, val);
+ }
+
+ // תΪ JSON ַ
+ char* json_str = cJSON_PrintUnformatted(root); // ʹ Unformatted
+ cJSON_Delete(root);
+ return json_str;
+}
+
+void mqtt_publish_bms_data(uint16_t basetime)
+{
+ static uint32_t mqtt_cycle_tick = 0;
+ mqtt_cycle_tick += basetime;
+
+ if(mqtt_cycle_tick > 60000)
+ {
+ mqtt_cycle_tick = 0;
+ char* json_str = protocol_build_json();
+ if (json_str == NULL)
+ {
+ return;
+ }
+
+ drv_mqtt_publish(json_str, strlen(json_str));
+
+ cJSON_free(json_str);
+ }
+
+}
+
diff --git a/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h
new file mode 100644
index 0000000..8ba15e3
--- /dev/null
+++ b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ * @file protocol_mqtt_bcu.h
+ * @brief protocol_mqtt_bcu.h
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+#ifndef PROTOCOL_MQTT_BCU_H_
+#define PROTOCOL_MQTT_BCU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "cJSON.h"
+#include "drv_qfc41d.h"
+#include "drv_rtc.h"
+
+typedef struct {
+ const char* key; // JSON еļ "BCU_2"
+ uint8_t groupId; // mqttΪjsonƣڷ鴫,0ʼ
+ uint16_t input; // get_valΣڻȡkeyӦ
+ uint32_t (*get_val)(uint16_t); // ӦֵĻȡ
+} devPointMap;
+
+
+extern const devPointMap bms_points[];
+
+void mqtt_publish_bms_data(uint32_t basetime);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h.orig b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h.orig
new file mode 100644
index 0000000..61bf6d7
--- /dev/null
+++ b/app/stm32fxxx_app/protocol/protocol_mqtt_bcu.h.orig
@@ -0,0 +1,36 @@
+/******************************************************************************
+ * @file protocol_mqtt_bcu.h
+ * @brief protocol_mqtt_bcu.h
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+#ifndef PROTOCOL_MQTT_BCU_H_
+#define PROTOCOL_MQTT_BCU_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+#include "cJSON.h"
+#include "drv_qfc41d.h"
+#include "drv_rtc.h"
+
+typedef struct {
+ const char* key; // JSON еļ "BCU_2"
+ uint32_t (*get_val)(uint16_t); // ӦֵĻȡ
+} devPointMap;
+
+
+extern const devPointMap bms_points[];
+
+void mqtt_publish_bms_data(uint32_t basetime);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
\ No newline at end of file
diff --git a/library/bsp/bsp_adbms1818.c b/library/bsp/bsp_adbms1818.c
index 83737f3..bdcad58 100644
--- a/library/bsp/bsp_adbms1818.c
+++ b/library/bsp/bsp_adbms1818.c
@@ -110,7 +110,7 @@ void check_error(int error)
{
if (error == -1)
{
- KIT_DEBUG_PRINTF("A PEC error was detected in the received data");
+ KIT_PRINTF("A PEC error was detected in the received data");
}
}
@@ -124,30 +124,30 @@ void print_cells(uint8_t datalog_en)
{
if (datalog_en == 0)
{
- KIT_DEBUG_PRINTF(" IC ");
-// KIT_DEBUG_PRINTF(current_ic + 1, DEC);
- KIT_DEBUG_PRINTF(", ");
+ KIT_PRINTF(" IC ");
+// KIT_PRINTF(current_ic + 1, DEC);
+ KIT_PRINTF(", ");
for (int i = 0; i < BMS_IC[0].ic_reg.cell_channels; i++)
{
- KIT_DEBUG_PRINTF(" C");
-// KIT_DEBUG_PRINTF(i + 1, DEC);
-// KIT_DEBUG_PRINTF(":");
-// KIT_DEBUG_PRINTF(BMS_IC[current_ic].cells.c_codes[i] * 0.0001, 4);
- KIT_DEBUG_PRINTF(",");
+ KIT_PRINTF(" C");
+// KIT_PRINTF(i + 1, DEC);
+// KIT_PRINTF(":");
+// KIT_PRINTF(BMS_IC[current_ic].cells.c_codes[i] * 0.0001, 4);
+ KIT_PRINTF(",");
}
- KIT_DEBUG_PRINTF("\n");
+ KIT_PRINTF("\n");
}
else
{
- KIT_DEBUG_PRINTF(" Cells, ");
+ KIT_PRINTF(" Cells, ");
for (int i = 0; i < BMS_IC[0].ic_reg.cell_channels; i++)
{
-// KIT_DEBUG_PRINTF(BMS_IC[current_ic].cells.c_codes[i] * 0.0001, 4);
- KIT_DEBUG_PRINTF(",");
+// KIT_PRINTF(BMS_IC[current_ic].cells.c_codes[i] * 0.0001, 4);
+ KIT_PRINTF(",");
}
}
}
- KIT_DEBUG_PRINTF("\n");
+ KIT_PRINTF("\n");
}
void ADBMS1818_reset_crc_count(uint8_t total_ic, cell_asic *ic)
diff --git a/library/bsp/bsp_boot.c b/library/bsp/bsp_boot.c
index 985271e..124a1bd 100644
--- a/library/bsp/bsp_boot.c
+++ b/library/bsp/bsp_boot.c
@@ -222,7 +222,7 @@ bool bsp_boot_move_firmware(BootItem *item, uint32_t start_addr, uint32_t max_le
{
drv_flash_read_u32(item->flash_item, item->back_up_addr + APP_CFG_BOOT_FW_LENGTH_OFFSET, &data);
KIT_ASSERT_PARAM(data < (max_len - APP_CFG_BOOT_FW_DATA_OFFSET));
- KIT_DEBUG_PRINTF("GUIDE:need update\r\n");
+ KIT_PRINTF("GUIDE:need update\r\n");
if((data < (max_len - APP_CFG_BOOT_FW_DATA_OFFSET)) && (kit_check_crc16((uint8_t *)(item->back_up_addr + APP_CFG_BOOT_FW_DATA_OFFSET), data) == 0))
{
bsp_flash_erase_page(item->flash_item, start_addr, data);
@@ -243,7 +243,7 @@ bool bsp_boot_move_firmware(BootItem *item, uint32_t start_addr, uint32_t max_le
}
else
{
- KIT_DEBUG_PRINTF("GUIDE:crc err\r\n");
+ KIT_PRINTF("GUIDE:crc err\r\n");
}
}
}
diff --git a/library/bsp/bsp_task.c b/library/bsp/bsp_task.c
index d2be2d1..3f0973e 100644
--- a/library/bsp/bsp_task.c
+++ b/library/bsp/bsp_task.c
@@ -83,7 +83,7 @@ void bsp_task_beat_wdog(void)
{
//task_item.reset_call(i);
cur_task->is_time_out = true;
- KIT_DEBUG_PRINTF("wdog timeout task id %d \r\n", cur_task->task_id);
+ KIT_PRINTF("wdog timeout task id %d \r\n", cur_task->task_id);
}
// is_timeout = true;
}
@@ -131,7 +131,7 @@ kit_ret_e bsp_create_task(task_array_t* task, uint8_t * name)
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSTaskNameSet(task->task_id, name, &res);
- KIT_DEBUG_PRINTF("task creat %s \r\n", name);
+ KIT_PRINTF("task creat %s \r\n", name);
#else
res = OSTaskCreate(_task_template, (void *)task, &task->stk_array[task->stk_size - 1], task->task_id);
#endif
diff --git a/library/cjson/cJSON.c b/library/cjson/cJSON.c
new file mode 100644
index 0000000..d7c7236
--- /dev/null
+++ b/library/cjson/cJSON.c
@@ -0,0 +1,3164 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ 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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef ENABLE_LOCALES
+#include
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#ifdef true
+#undef true
+#endif
+#define true ((cJSON_bool)1)
+
+#ifdef false
+#undef false
+#endif
+#define false ((cJSON_bool)0)
+
+/* define isnan and isinf for ANSI C, if in C99 or above, isnan and isinf has been defined in math.h */
+#ifndef isinf
+#define isinf(d) (isnan((d - d)) && !isnan(d))
+#endif
+#ifndef isnan
+#define isnan(d) (d != d)
+#endif
+
+#ifndef NAN
+#ifdef _WIN32
+#define NAN sqrt(-1.0)
+#else
+#define NAN 0.0/0.0
+#endif
+#endif
+
+typedef struct {
+ const unsigned char *json;
+ size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+ return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item)
+{
+ if (!cJSON_IsString(item))
+ {
+ return NULL;
+ }
+
+ return item->valuestring;
+}
+
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item)
+{
+ if (!cJSON_IsNumber(item))
+ {
+ return (double) NAN;
+ }
+
+ return item->valuedouble;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 18)
+ #error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+ static char version[15];
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+ return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1, const unsigned char *string2)
+{
+ if ((string1 == NULL) || (string2 == NULL))
+ {
+ return 1;
+ }
+
+ if (string1 == string2)
+ {
+ return 0;
+ }
+
+ for(; tolower(*string1) == tolower(*string2); (void)string1++, string2++)
+ {
+ if (*string1 == '\0')
+ {
+ return 0;
+ }
+ }
+
+ return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks
+{
+ void *(CJSON_CDECL *allocate)(size_t size);
+ void (CJSON_CDECL *deallocate)(void *pointer);
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dllimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+ return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+ free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+ return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+/* strlen of character literals resolved at compile time */
+#define static_strlen(string_literal) (sizeof(string_literal) - sizeof(""))
+
+static internal_hooks global_hooks = { internal_malloc, internal_free, internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string, const internal_hooks * const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL)
+ {
+ return NULL;
+ }
+
+ length = strlen((const char*)string) + sizeof("");
+ copy = (unsigned char*)hooks->allocate(length);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (hooks == NULL)
+ {
+ /* Reset hooks */
+ global_hooks.allocate = malloc;
+ global_hooks.deallocate = free;
+ global_hooks.reallocate = realloc;
+ return;
+ }
+
+ global_hooks.allocate = malloc;
+ if (hooks->malloc_fn != NULL)
+ {
+ global_hooks.allocate = hooks->malloc_fn;
+ }
+
+ global_hooks.deallocate = free;
+ if (hooks->free_fn != NULL)
+ {
+ global_hooks.deallocate = hooks->free_fn;
+ }
+
+ /* use realloc only if both free and malloc are used */
+ global_hooks.reallocate = NULL;
+ if ((global_hooks.allocate == malloc) && (global_hooks.deallocate == free))
+ {
+ global_hooks.reallocate = realloc;
+ }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+ cJSON* node = (cJSON*)hooks->allocate(sizeof(cJSON));
+ if (node)
+ {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+ cJSON *next = NULL;
+ while (item != NULL)
+ {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL))
+ {
+ cJSON_Delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL))
+ {
+ global_hooks.deallocate(item->valuestring);
+ item->valuestring = NULL;
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ global_hooks.deallocate(item->string);
+ item->string = NULL;
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+ struct lconv *lconv = localeconv();
+ return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
+}
+
+typedef struct
+{
+ const unsigned char *content;
+ size_t length;
+ size_t offset;
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+ internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item, parse_buffer * const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = get_decimal_point();
+ size_t i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0; (i < (sizeof(number_c_string) - 1)) && can_access_at_index(input_buffer, i); i++)
+ {
+ switch (buffer_at_offset(input_buffer)[i])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+loop_end:
+ number_c_string[i] = '\0';
+
+ number = strtod((const char*)number_c_string, (char**)&after_end);
+ if (number_c_string == after_end)
+ {
+ return false; /* parse_error */
+ }
+
+ item->valuedouble = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)number;
+ }
+
+ item->type = cJSON_Number;
+
+ input_buffer->offset += (size_t)(after_end - number_c_string);
+ return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+ if (number >= INT_MAX)
+ {
+ object->valueint = INT_MAX;
+ }
+ else if (number <= (double)INT_MIN)
+ {
+ object->valueint = INT_MIN;
+ }
+ else
+ {
+ object->valueint = (int)number;
+ }
+
+ return object->valuedouble = number;
+}
+
+/* Note: when passing a NULL valuestring, cJSON_SetValuestring treats this as an error and return NULL */
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring)
+{
+ char *copy = NULL;
+ size_t v1_len;
+ size_t v2_len;
+ /* if object's type is not cJSON_String or is cJSON_IsReference, it should not set valuestring */
+ if ((object == NULL) || !(object->type & cJSON_String) || (object->type & cJSON_IsReference))
+ {
+ return NULL;
+ }
+ /* return NULL if the object is corrupted or valuestring is NULL */
+ if (object->valuestring == NULL || valuestring == NULL)
+ {
+ return NULL;
+ }
+
+ v1_len = strlen(valuestring);
+ v2_len = strlen(object->valuestring);
+
+ if (v1_len <= v2_len)
+ {
+ /* strcpy does not handle overlapping string: [X1, X2] [Y1, Y2] => X2 < Y1 or Y2 < X1 */
+ if (!( valuestring + v1_len < object->valuestring || object->valuestring + v2_len < valuestring ))
+ {
+ return NULL;
+ }
+ strcpy(object->valuestring, valuestring);
+ return object->valuestring;
+ }
+ copy = (char*) cJSON_strdup((const unsigned char*)valuestring, &global_hooks);
+ if (copy == NULL)
+ {
+ return NULL;
+ }
+ if (object->valuestring != NULL)
+ {
+ cJSON_free(object->valuestring);
+ }
+ object->valuestring = copy;
+
+ return copy;
+}
+
+typedef struct
+{
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL))
+ {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length))
+ {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX)
+ {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length)
+ {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2))
+ {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX)
+ {
+ newsize = INT_MAX;
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL)
+ {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char*)p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ }
+ else
+ {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char*)p->hooks.allocate(newsize);
+ if (!newbuffer)
+ {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL))
+ {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char*)buffer_pointer);
+}
+
+/* securely comparison of floating-point variables */
+static cJSON_bool compare_double(double a, double b)
+{
+ double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b);
+ return (fabs(a - b) <= maxVal * DBL_EPSILON);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26] = {0}; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ double test = 0.0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if (isnan(d) || isinf(d))
+ {
+ length = sprintf((char*)number_buffer, "null");
+ }
+ else if(d == (double)item->valueint)
+ {
+ length = sprintf((char*)number_buffer, "%d", item->valueint);
+ }
+ else
+ {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char*)number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char*)number_buffer, "%lg", &test) != 1) || !compare_double((double)test, d))
+ {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char*)number_buffer, "%1.17g", d);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occurred */
+ if ((length < 0) || (length > (int)(sizeof(number_buffer) - 1)))
+ {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t)length + sizeof(""));
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t)length); i++)
+ {
+ if (number_buffer[i] == decimal_point)
+ {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t)length;
+
+ return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+ unsigned int h = 0;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ /* parse digit */
+ if ((input[i] >= '0') && (input[i] <= '9'))
+ {
+ h += (unsigned int) input[i] - '0';
+ }
+ else if ((input[i] >= 'A') && (input[i] <= 'F'))
+ {
+ h += (unsigned int) 10 + input[i] - 'A';
+ }
+ else if ((input[i] >= 'a') && (input[i] <= 'f'))
+ {
+ h += (unsigned int) 10 + input[i] - 'a';
+ }
+ else /* invalid */
+ {
+ return 0;
+ }
+
+ if (i < 3)
+ {
+ /* shift left to make place for the next nibble */
+ h = h << 4;
+ }
+ }
+
+ return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(const unsigned char * const input_pointer, const unsigned char * const input_end, unsigned char **output_pointer)
+{
+ long unsigned int codepoint = 0;
+ unsigned int first_code = 0;
+ const unsigned char *first_sequence = input_pointer;
+ unsigned char utf8_length = 0;
+ unsigned char utf8_position = 0;
+ unsigned char sequence_length = 0;
+ unsigned char first_byte_mark = 0;
+
+ if ((input_end - first_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ /* get the first utf16 sequence */
+ first_code = parse_hex4(first_sequence + 2);
+
+ /* check that the code is valid */
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF)))
+ {
+ goto fail;
+ }
+
+ /* UTF16 surrogate pair */
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF))
+ {
+ const unsigned char *second_sequence = first_sequence + 6;
+ unsigned int second_code = 0;
+ sequence_length = 12; /* \uXXXX\uXXXX */
+
+ if ((input_end - second_sequence) < 6)
+ {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u'))
+ {
+ /* missing second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* get the second utf16 sequence */
+ second_code = parse_hex4(second_sequence + 2);
+ /* check that the code is valid */
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF))
+ {
+ /* invalid second half of the surrogate pair */
+ goto fail;
+ }
+
+
+ /* calculate the unicode codepoint from the surrogate pair */
+ codepoint = 0x10000 + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+ }
+ else
+ {
+ sequence_length = 6; /* \uXXXX */
+ codepoint = first_code;
+ }
+
+ /* encode as UTF-8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ if (codepoint < 0x80)
+ {
+ /* normal ascii, encoding 0xxxxxxx */
+ utf8_length = 1;
+ }
+ else if (codepoint < 0x800)
+ {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ utf8_length = 2;
+ first_byte_mark = 0xC0; /* 11000000 */
+ }
+ else if (codepoint < 0x10000)
+ {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 3;
+ first_byte_mark = 0xE0; /* 11100000 */
+ }
+ else if (codepoint <= 0x10FFFF)
+ {
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 4;
+ first_byte_mark = 0xF0; /* 11110000 */
+ }
+ else
+ {
+ /* invalid unicode codepoint */
+ goto fail;
+ }
+
+ /* encode as utf8 */
+ for (utf8_position = (unsigned char)(utf8_length - 1); utf8_position > 0; utf8_position--)
+ {
+ /* 10xxxxxx */
+ (*output_pointer)[utf8_position] = (unsigned char)((codepoint | 0x80) & 0xBF);
+ codepoint >>= 6;
+ }
+ /* encode first byte */
+ if (utf8_length > 1)
+ {
+ (*output_pointer)[0] = (unsigned char)((codepoint | first_byte_mark) & 0xFF);
+ }
+ else
+ {
+ (*output_pointer)[0] = (unsigned char)(codepoint & 0x7F);
+ }
+
+ *output_pointer += utf8_length;
+
+ return sequence_length;
+
+fail:
+ return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item, parse_buffer * const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ unsigned char *output_pointer = NULL;
+ unsigned char *output = NULL;
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"')
+ {
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ size_t allocation_length = 0;
+ size_t skipped_bytes = 0;
+ while (((size_t)(input_end - input_buffer->content) < input_buffer->length) && (*input_end != '\"'))
+ {
+ /* is escape sequence */
+ if (input_end[0] == '\\')
+ {
+ if ((size_t)(input_end + 1 - input_buffer->content) >= input_buffer->length)
+ {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length) || (*input_end != '\"'))
+ {
+ goto fail; /* string ended unexpectedly */
+ }
+
+ /* This is at most how much we need for the output */
+ allocation_length = (size_t) (input_end - buffer_at_offset(input_buffer)) - skipped_bytes;
+ output = (unsigned char*)input_buffer->hooks.allocate(allocation_length + sizeof(""));
+ if (output == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+ }
+
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end)
+ {
+ if (*input_pointer != '\\')
+ {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else
+ {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1)
+ {
+ goto fail;
+ }
+
+ switch (input_pointer[1])
+ {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer, input_end, &output_pointer);
+ if (sequence_length == 0)
+ {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+
+ item->type = cJSON_String;
+ item->valuestring = (char*)output;
+
+ input_buffer->offset = (size_t) (input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (output != NULL)
+ {
+ input_buffer->hooks.deallocate(output);
+ output = NULL;
+ }
+
+ if (input_pointer != NULL)
+ {
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+ }
+
+ return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input, printbuffer * const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL)
+ {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++)
+ {
+ switch (*input_pointer)
+ {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32)
+ {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL)
+ {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0)
+ {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0'; (void)input_pointer++, output_pointer++)
+ {
+ if ((*input_pointer > 31) && (*input_pointer != '\"') && (*input_pointer != '\\'))
+ {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ }
+ else
+ {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer)
+ {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char*)output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+ return print_string_ptr((unsigned char*)item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL))
+ {
+ return NULL;
+ }
+
+ if (cannot_access_at_index(buffer, 0))
+ {
+ return buffer;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32))
+ {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length)
+ {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL) || (buffer->offset != 0))
+ {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4) && (strncmp((const char*)buffer_at_offset(buffer), "\xEF\xBB\xBF", 3) == 0))
+ {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ size_t buffer_length;
+
+ if (NULL == value)
+ {
+ return NULL;
+ }
+
+ /* Adding null character size due to require_null_terminated. */
+ buffer_length = strlen(value) + sizeof("");
+
+ return cJSON_ParseWithLengthOpts(value, buffer_length, return_parse_end, require_null_terminated);
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ parse_buffer buffer = { 0, 0, 0, 0, { 0, 0, 0 } };
+ cJSON *item = NULL;
+
+ /* reset error position */
+ global_error.json = NULL;
+ global_error.position = 0;
+
+ if (value == NULL || 0 == buffer_length)
+ {
+ goto fail;
+ }
+
+ buffer.content = (const unsigned char*)value;
+ buffer.length = buffer_length;
+ buffer.offset = 0;
+ buffer.hooks = global_hooks;
+
+ item = cJSON_New_Item(&global_hooks);
+ if (item == NULL) /* memory fail */
+ {
+ goto fail;
+ }
+
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+ {
+ /* parse failure. ep is set. */
+ goto fail;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated)
+ {
+ buffer_skip_whitespace(&buffer);
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+ {
+ goto fail;
+ }
+ }
+ if (return_parse_end)
+ {
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
+ }
+
+ return item;
+
+fail:
+ if (item != NULL)
+ {
+ cJSON_Delete(item);
+ }
+
+ if (value != NULL)
+ {
+ error local_error;
+ local_error.json = (const unsigned char*)value;
+ local_error.position = 0;
+
+ if (buffer.offset < buffer.length)
+ {
+ local_error.position = buffer.offset;
+ }
+ else if (buffer.length > 0)
+ {
+ local_error.position = buffer.length - 1;
+ }
+
+ if (return_parse_end != NULL)
+ {
+ *return_parse_end = (const char*)local_error.json + local_error.position;
+ }
+
+ global_error = local_error;
+ }
+
+ return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length)
+{
+ return cJSON_ParseWithLengthOpts(value, buffer_length, 0, 0);
+}
+
+#define cjson_min(a, b) (((a) < (b)) ? (a) : (b))
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format, const internal_hooks * const hooks)
+{
+ static const size_t default_buffer_size = 256;
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL)
+ {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer))
+ {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL)
+ {
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer, buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ buffer->buffer = NULL;
+ }
+ else /* otherwise copy the JSON over to a new buffer */
+ {
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+ if (printed == NULL)
+ {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer, cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ buffer->buffer = NULL;
+ }
+
+ return printed;
+
+fail:
+ if (buffer->buffer != NULL)
+ {
+ hooks->deallocate(buffer->buffer);
+ buffer->buffer = NULL;
+ }
+
+ if (printed != NULL)
+ {
+ hooks->deallocate(printed);
+ printed = NULL;
+ }
+
+ return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+ return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+ return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if (prebuffer < 0)
+ {
+ return NULL;
+ }
+
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+ if (!p.buffer)
+ {
+ return NULL;
+ }
+
+ p.length = (size_t)prebuffer;
+ p.offset = 0;
+ p.noalloc = false;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ if (!print_value(item, &p))
+ {
+ global_hooks.deallocate(p.buffer);
+ p.buffer = NULL;
+ return NULL;
+ }
+
+ return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if ((length < 0) || (buffer == NULL))
+ {
+ return false;
+ }
+
+ p.buffer = (unsigned char*)buffer;
+ p.length = (size_t)length;
+ p.offset = 0;
+ p.noalloc = true;
+ p.format = format;
+ p.hooks = global_hooks;
+
+ return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item, parse_buffer * const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL))
+ {
+ return false; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "null", 4) == 0))
+ {
+ item->type = cJSON_NULL;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* false */
+ if (can_read(input_buffer, 5) && (strncmp((const char*)buffer_at_offset(input_buffer), "false", 5) == 0))
+ {
+ item->type = cJSON_False;
+ input_buffer->offset += 5;
+ return true;
+ }
+ /* true */
+ if (can_read(input_buffer, 4) && (strncmp((const char*)buffer_at_offset(input_buffer), "true", 4) == 0))
+ {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '\"'))
+ {
+ return parse_string(item, input_buffer);
+ }
+ /* number */
+ if (can_access_at_index(input_buffer, 0) && ((buffer_at_offset(input_buffer)[0] == '-') || ((buffer_at_offset(input_buffer)[0] >= '0') && (buffer_at_offset(input_buffer)[0] <= '9'))))
+ {
+ return parse_number(item, input_buffer);
+ }
+ /* array */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '['))
+ {
+ return parse_array(item, input_buffer);
+ }
+ /* object */
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '{'))
+ {
+ return parse_object(item, input_buffer);
+ }
+
+ return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL))
+ {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF)
+ {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL)
+ {
+ return false;
+ }
+ strcpy((char*)output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw:
+ {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL)
+ {
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL)
+ {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* head of the linked list */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[')
+ {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ']'))
+ {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || buffer_at_offset(input_buffer)[0] != ']')
+ {
+ goto fail; /* expected end of array */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Array;
+ item->child = head;
+
+ input_buffer->offset++;
+
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_element = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL)
+ {
+ if (!print_value(current_element, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next)
+ {
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if(output_buffer->format)
+ {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item, parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* linked list head */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT)
+ {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '{'))
+ {
+ goto fail; /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == '}'))
+ {
+ goto success; /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0))
+ {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do
+ {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL)
+ {
+ goto fail; /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL)
+ {
+ /* start the linked list */
+ current_item = head = new_item;
+ }
+ else
+ {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ if (cannot_access_at_index(input_buffer, 1))
+ {
+ goto fail; /* nothing comes after the comma */
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_string(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* swap valuestring and string, because we parsed the name */
+ current_item->string = current_item->valuestring;
+ current_item->valuestring = NULL;
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != ':'))
+ {
+ goto fail; /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer))
+ {
+ goto fail; /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ }
+ while (can_access_at_index(input_buffer, 0) && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0) || (buffer_at_offset(input_buffer)[0] != '}'))
+ {
+ goto fail; /* expected end of object */
+ }
+
+success:
+ input_buffer->depth--;
+
+ if (head != NULL) {
+ head->prev = current_item;
+ }
+
+ item->type = cJSON_Object;
+ item->child = head;
+
+ input_buffer->offset++;
+ return true;
+
+fail:
+ if (head != NULL)
+ {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item, printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_item = item->child;
+
+ if (output_buffer == NULL)
+ {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t) (output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item)
+ {
+ if (output_buffer->format)
+ {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char*)current_item->string, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t) (output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer))
+ {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = ((size_t)(output_buffer->format ? 1 : 0) + (size_t)(current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (current_item->next)
+ {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format)
+ {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer, output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL)
+ {
+ return false;
+ }
+ if (output_buffer->format)
+ {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++)
+ {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *child = NULL;
+ size_t size = 0;
+
+ if (array == NULL)
+ {
+ return 0;
+ }
+
+ child = array->child;
+
+ while(child != NULL)
+ {
+ size++;
+ child = child->next;
+ }
+
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+ return (int)size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+ cJSON *current_child = NULL;
+
+ if (array == NULL)
+ {
+ return NULL;
+ }
+
+ current_child = array->child;
+ while ((current_child != NULL) && (index > 0))
+ {
+ index--;
+ current_child = current_child->next;
+ }
+
+ return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+ if (index < 0)
+ {
+ return NULL;
+ }
+
+ return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object, const char * const name, const cJSON_bool case_sensitive)
+{
+ cJSON *current_element = NULL;
+
+ if ((object == NULL) || (name == NULL))
+ {
+ return NULL;
+ }
+
+ current_element = object->child;
+ if (case_sensitive)
+ {
+ while ((current_element != NULL) && (current_element->string != NULL) && (strcmp(name, current_element->string) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+ else
+ {
+ while ((current_element != NULL) && (case_insensitive_strcmp((const unsigned char*)name, (const unsigned char*)(current_element->string)) != 0))
+ {
+ current_element = current_element->next;
+ }
+ }
+
+ if ((current_element == NULL) || (current_element->string == NULL)) {
+ return NULL;
+ }
+
+ return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item, const internal_hooks * const hooks)
+{
+ cJSON *reference = NULL;
+ if (item == NULL)
+ {
+ return NULL;
+ }
+
+ reference = cJSON_New_Item(hooks);
+ if (reference == NULL)
+ {
+ return NULL;
+ }
+
+ memcpy(reference, item, sizeof(cJSON));
+ reference->string = NULL;
+ reference->type |= cJSON_IsReference;
+ reference->next = reference->prev = NULL;
+ return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+ cJSON *child = NULL;
+
+ if ((item == NULL) || (array == NULL) || (array == item))
+ {
+ return false;
+ }
+
+ child = array->child;
+ /*
+ * To find the last item in array quickly, we use prev in array
+ */
+ if (child == NULL)
+ {
+ /* list is empty, start new one */
+ array->child = item;
+ item->prev = item;
+ item->next = NULL;
+ }
+ else
+ {
+ /* append to the end */
+ if (child->prev)
+ {
+ suffix_object(child->prev, item);
+ array->child->prev = item;
+ }
+ }
+
+ return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ return add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+ return (void*)string;
+}
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+ #pragma GCC diagnostic pop
+#endif
+
+
+static cJSON_bool add_item_to_object(cJSON * const object, const char * const string, cJSON * const item, const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL) || (object == item))
+ {
+ return false;
+ }
+
+ if (constant_key)
+ {
+ new_key = (char*)cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ }
+ else
+ {
+ new_key = (char*)cJSON_strdup((const unsigned char*)string, hooks);
+ if (new_key == NULL)
+ {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL))
+ {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item)
+{
+ return add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ if (array == NULL)
+ {
+ return false;
+ }
+
+ return add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item)
+{
+ if ((object == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ return add_item_to_object(object, string, create_reference(item, &global_hooks), &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+ cJSON *null = cJSON_CreateNull();
+ if (add_item_to_object(object, name, null, &global_hooks, false))
+ {
+ return null;
+ }
+
+ cJSON_Delete(null);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+ cJSON *true_item = cJSON_CreateTrue();
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
+ {
+ return true_item;
+ }
+
+ cJSON_Delete(true_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+ cJSON *false_item = cJSON_CreateFalse();
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
+ {
+ return false_item;
+ }
+
+ cJSON_Delete(false_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+ cJSON *bool_item = cJSON_CreateBool(boolean);
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+ {
+ return bool_item;
+ }
+
+ cJSON_Delete(bool_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+ cJSON *number_item = cJSON_CreateNumber(number);
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
+ {
+ return number_item;
+ }
+
+ cJSON_Delete(number_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+ cJSON *string_item = cJSON_CreateString(string);
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
+ {
+ return string_item;
+ }
+
+ cJSON_Delete(string_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+ cJSON *raw_item = cJSON_CreateRaw(raw);
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+ {
+ return raw_item;
+ }
+
+ cJSON_Delete(raw_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+ cJSON *object_item = cJSON_CreateObject();
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
+ {
+ return object_item;
+ }
+
+ cJSON_Delete(object_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+ cJSON *array = cJSON_CreateArray();
+ if (add_item_to_object(object, name, array, &global_hooks, false))
+ {
+ return array;
+ }
+
+ cJSON_Delete(array);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+ if ((parent == NULL) || (item == NULL) || (item != parent->child && item->prev == NULL))
+ {
+ return NULL;
+ }
+
+ if (item != parent->child)
+ {
+ /* not the first element */
+ item->prev->next = item->next;
+ }
+ if (item->next != NULL)
+ {
+ /* not the last element */
+ item->next->prev = item->prev;
+ }
+
+ if (item == parent->child)
+ {
+ /* first element */
+ parent->child = item->next;
+ }
+ else if (item->next == NULL)
+ {
+ /* last element */
+ parent->child->prev = item->prev;
+ }
+
+ /* make sure the detached item doesn't point anywhere anymore */
+ item->prev = NULL;
+ item->next = NULL;
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ if (which < 0)
+ {
+ return NULL;
+ }
+
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ cJSON *after_inserted = NULL;
+
+ if (which < 0 || newitem == NULL)
+ {
+ return false;
+ }
+
+ after_inserted = get_array_item(array, (size_t)which);
+ if (after_inserted == NULL)
+ {
+ return add_item_to_array(array, newitem);
+ }
+
+ if (after_inserted != array->child && after_inserted->prev == NULL) {
+ /* return false if after_inserted is a corrupted array item */
+ return false;
+ }
+
+ newitem->next = after_inserted;
+ newitem->prev = after_inserted->prev;
+ after_inserted->prev = newitem;
+ if (after_inserted == array->child)
+ {
+ array->child = newitem;
+ }
+ else
+ {
+ newitem->prev->next = newitem;
+ }
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement)
+{
+ if ((parent == NULL) || (parent->child == NULL) || (replacement == NULL) || (item == NULL))
+ {
+ return false;
+ }
+
+ if (replacement == item)
+ {
+ return true;
+ }
+
+ replacement->next = item->next;
+ replacement->prev = item->prev;
+
+ if (replacement->next != NULL)
+ {
+ replacement->next->prev = replacement;
+ }
+ if (parent->child == item)
+ {
+ if (parent->child->prev == parent->child)
+ {
+ replacement->prev = replacement;
+ }
+ parent->child = replacement;
+ }
+ else
+ { /*
+ * To find the last item in array quickly, we use prev in array.
+ * We can't modify the last item's next pointer where this item was the parent's child
+ */
+ if (replacement->prev != NULL)
+ {
+ replacement->prev->next = replacement;
+ }
+ if (replacement->next == NULL)
+ {
+ parent->child->prev = replacement;
+ }
+ }
+
+ item->next = NULL;
+ item->prev = NULL;
+ cJSON_Delete(item);
+
+ return true;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem)
+{
+ if (which < 0)
+ {
+ return false;
+ }
+
+ return cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t)which), newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string, cJSON *replacement, cJSON_bool case_sensitive)
+{
+ if ((replacement == NULL) || (string == NULL))
+ {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst) && (replacement->string != NULL))
+ {
+ cJSON_free(replacement->string);
+ }
+ replacement->string = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if (replacement->string == NULL)
+ {
+ return false;
+ }
+
+ replacement->type &= ~cJSON_StringIsConst;
+
+ return cJSON_ReplaceItemViaPointer(object, get_object_item(object, string, case_sensitive), replacement);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object, const char *string, cJSON *newitem)
+{
+ return replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = boolean ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (num <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_String;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL)
+ {
+ item->type = cJSON_String | cJSON_IsReference;
+ item->valuestring = (char*)cast_away_const(string);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Object | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Array | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Raw;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type=cJSON_Array;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item)
+ {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber((double)numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (strings == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateString(strings[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p,n);
+ }
+ p = n;
+ }
+
+ if (a && a->child) {
+ a->child->prev = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse);
+
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+ return cJSON_Duplicate_rec(item, 0, recurse );
+}
+
+cJSON * cJSON_Duplicate_rec(const cJSON *item, size_t depth, cJSON_bool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *child = NULL;
+ cJSON *next = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item)
+ {
+ goto fail;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item(&global_hooks);
+ if (!newitem)
+ {
+ goto fail;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring)
+ {
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+ if (!newitem->valuestring)
+ {
+ goto fail;
+ }
+ }
+ if (item->string)
+ {
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+ if (!newitem->string)
+ {
+ goto fail;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse)
+ {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ child = item->child;
+ while (child != NULL)
+ {
+ if(depth >= CJSON_CIRCULAR_LIMIT) {
+ goto fail;
+ }
+ newchild = cJSON_Duplicate_rec(child, depth + 1, true); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild)
+ {
+ goto fail;
+ }
+ if (next != NULL)
+ {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ next->next = newchild;
+ newchild->prev = next;
+ next = newchild;
+ }
+ else
+ {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild;
+ next = newchild;
+ }
+ child = child->next;
+ }
+ if (newitem && newitem->child)
+ {
+ newitem->child->prev = newchild;
+ }
+
+ return newitem;
+
+fail:
+ if (newitem != NULL)
+ {
+ cJSON_Delete(newitem);
+ }
+
+ return NULL;
+}
+
+static void skip_oneline_comment(char **input)
+{
+ *input += static_strlen("//");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if ((*input)[0] == '\n') {
+ *input += static_strlen("\n");
+ return;
+ }
+ }
+}
+
+static void skip_multiline_comment(char **input)
+{
+ *input += static_strlen("/*");
+
+ for (; (*input)[0] != '\0'; ++(*input))
+ {
+ if (((*input)[0] == '*') && ((*input)[1] == '/'))
+ {
+ *input += static_strlen("*/");
+ return;
+ }
+ }
+}
+
+static void minify_string(char **input, char **output) {
+ (*output)[0] = (*input)[0];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+
+
+ for (; (*input)[0] != '\0'; (void)++(*input), ++(*output)) {
+ (*output)[0] = (*input)[0];
+
+ if ((*input)[0] == '\"') {
+ (*output)[0] = '\"';
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ return;
+ } else if (((*input)[0] == '\\') && ((*input)[1] == '\"')) {
+ (*output)[1] = (*input)[1];
+ *input += static_strlen("\"");
+ *output += static_strlen("\"");
+ }
+ }
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ char *into = json;
+
+ if (json == NULL)
+ {
+ return;
+ }
+
+ while (json[0] != '\0')
+ {
+ switch (json[0])
+ {
+ case ' ':
+ case '\t':
+ case '\r':
+ case '\n':
+ json++;
+ break;
+
+ case '/':
+ if (json[1] == '/')
+ {
+ skip_oneline_comment(&json);
+ }
+ else if (json[1] == '*')
+ {
+ skip_multiline_comment(&json);
+ } else {
+ json++;
+ }
+ break;
+
+ case '\"':
+ minify_string(&json, (char**)&into);
+ break;
+
+ default:
+ into[0] = json[0];
+ json++;
+ into++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xff) == cJSON_True;
+}
+
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+ if (item == NULL)
+ {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive)
+{
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF)))
+ {
+ return false;
+ }
+
+ /* check if type is valid */
+ switch (a->type & 0xFF)
+ {
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ case cJSON_Number:
+ case cJSON_String:
+ case cJSON_Raw:
+ case cJSON_Array:
+ case cJSON_Object:
+ break;
+
+ default:
+ return false;
+ }
+
+ /* identical objects are equal */
+ if (a == b)
+ {
+ return true;
+ }
+
+ switch (a->type & 0xFF)
+ {
+ /* in these cases and equal type is enough */
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ return true;
+
+ case cJSON_Number:
+ if (compare_double(a->valuedouble, b->valuedouble))
+ {
+ return true;
+ }
+ return false;
+
+ case cJSON_String:
+ case cJSON_Raw:
+ if ((a->valuestring == NULL) || (b->valuestring == NULL))
+ {
+ return false;
+ }
+ if (strcmp(a->valuestring, b->valuestring) == 0)
+ {
+ return true;
+ }
+
+ return false;
+
+ case cJSON_Array:
+ {
+ cJSON *a_element = a->child;
+ cJSON *b_element = b->child;
+
+ for (; (a_element != NULL) && (b_element != NULL);)
+ {
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+
+ a_element = a_element->next;
+ b_element = b_element->next;
+ }
+
+ /* one of the arrays is longer than the other */
+ if (a_element != b_element) {
+ return false;
+ }
+
+ return true;
+ }
+
+ case cJSON_Object:
+ {
+ cJSON *a_element = NULL;
+ cJSON *b_element = NULL;
+ cJSON_ArrayForEach(a_element, a)
+ {
+ /* TODO This has O(n^2) runtime, which is horrible! */
+ b_element = get_object_item(b, a_element->string, case_sensitive);
+ if (b_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(a_element, b_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
+ * TODO: Do this the proper way, this is just a fix for now */
+ cJSON_ArrayForEach(b_element, b)
+ {
+ a_element = get_object_item(a, b_element->string, case_sensitive);
+ if (a_element == NULL)
+ {
+ return false;
+ }
+
+ if (!cJSON_Compare(b_element, a_element, case_sensitive))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+ return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+ global_hooks.deallocate(object);
+ object = NULL;
+}
diff --git a/library/cjson/cJSON.h b/library/cjson/cJSON.h
new file mode 100644
index 0000000..37520bb
--- /dev/null
+++ b/library/cjson/cJSON.h
@@ -0,0 +1,306 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ 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 cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
+
+CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+For *nix builds that support visibility attribute, you can define similar behavior by
+
+setting default visibility to hidden by adding
+-fvisibility=hidden (for gcc)
+or
+-xldscope=hidden (for sun cc)
+to CFLAGS
+
+then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+*/
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type) type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 18
+
+#include
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON
+{
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *next;
+ struct cJSON *prev;
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ struct cJSON *child;
+
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
+ char *valuestring;
+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+ int valueint;
+ /* The item's number, if type==cJSON_Number */
+ double valuedouble;
+
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks
+{
+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
+ void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* Limits the length of circular references can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_CIRCULAR_LIMIT
+#define CJSON_CIRCULAR_LIMIT 10000
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check item type and return its value */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
+CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/array that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items.
+ * The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detach items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ * need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ * The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
+ * The input pointer json cannot point to a read-only address area, such as a string constant,
+ * but should point to a readable and writable address area. */
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
+CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
+
+/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
+#define cJSON_SetBoolValue(object, boolValue) ( \
+ (object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
+ (object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
+ cJSON_Invalid\
+)
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/library/drv_peripheral/drv_eg25gminipice.c b/library/drv_peripheral/drv_eg25gminipice.c
index a382f3b..8fd9bf0 100644
--- a/library/drv_peripheral/drv_eg25gminipice.c
+++ b/library/drv_peripheral/drv_eg25gminipice.c
@@ -108,14 +108,14 @@ void drv_mqtt_connect(void)
drv_send_at_cmd("AT+QMTOPEN=0,\"mqtt.example.com\",1883", 5000);
drv_send_at_cmd("AT+QMTCONN=0,\"client_id\",\"username\",\"password\"", 5000);
}
-
+/*
void drv_mqtt_publish(const char *topic, const char *message)
{
char cmd[128];
sprintf(cmd, "AT+QMTPUB=0,0,0,0,\"%s\",\"%s\"", topic, message);
drv_send_at_cmd(cmd, 500);
}
-
+*/
/*
diff --git a/library/drv_peripheral/drv_eg25gminipice.h b/library/drv_peripheral/drv_eg25gminipice.h
index add306b..75d8212 100644
--- a/library/drv_peripheral/drv_eg25gminipice.h
+++ b/library/drv_peripheral/drv_eg25gminipice.h
@@ -50,11 +50,12 @@ void drv_uart2_sendString(const char *str);
void drv_send_at_cmd(const char *cmd, int delay_ms);
void drv_eg25g_init(void);
void drv_mqtt_connect(void);
-void drv_mqtt_publish(const char *topic, const char *message);
+//void drv_mqtt_publish(const char *topic, const char *message);
void drv_sim_push_data(Lte4GItem* item, uint8_t *buf, uint16_t len);
#endif //DRV_EG25GMINIPICE_H_
+
\ No newline at end of file
diff --git a/library/drv_peripheral/drv_qfc41d.c b/library/drv_peripheral/drv_qfc41d.c
new file mode 100644
index 0000000..bff6d43
--- /dev/null
+++ b/library/drv_peripheral/drv_qfc41d.c
@@ -0,0 +1,313 @@
+/******************************************************************************
+ * @file drv_qfc41d.c
+ * @brief drv_qfc41d driver
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+
+#include "drv_qfc41d.h"
+
+uint8_t rev_buff[QFC41D_MAX_RECV_SIZE] = {0};
+uint8_t send_buff[QFC41D_MAX_SEND_SIZE] = {0};
+uint8_t wifiName[40] = {0}, wifiPassWord[40] = {0}, bleName[40] = {0};
+
+char cmd[100] = {0}; //ջռʹ
+//
+WifiBleItem qfc41dItem = {
+ .dev = QFC41D_UART_PORT,
+ .buf_pos = 0,
+ .buf_size = QFC41D_MAX_RECV_SIZE,
+ .buf = rev_buff,
+ .sendCall = NULL,
+};
+
+static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len)
+{
+ uint16_t i = 0;
+
+ if((item != NULL) && (item->buf_pos + len < item->buf_size))
+ {
+ item->buf[item->buf_pos++] = buf[i];
+ // зʾһ AT ָ
+ if (buf[i] == '\n')
+ {
+ item->buf[item->buf_pos] = '\0'; // ӽ
+ item->buf_pos = 0; // һ
+ }
+ }
+}
+
+
+static void drv_qf41d_uart_rx_it_call(kit_ret_e res, void *data)
+{
+ OS_TRACE_ISR_ENTER();
+ drv_qfc41d_push_data(&qfc41dItem, data, 1);
+ OS_TRACE_ISR_EXIT();
+}
+
+// ͵ַ
+void drv_wireless_send_char(char c)
+{
+ while (!(USART2->SR & USART_SR_TXE)); // ȴͻ
+ USART2->DR = c;
+}
+
+// ַ
+void drv_wireless_send_string(const char *str)
+{
+ while (*str)
+ {
+ drv_wireless_send_char(*str++);
+ }
+ drv_wireless_send_char('\r'); // CR
+ drv_wireless_send_char('\n'); // LF
+}
+
+
+// AT ָȴֵ
+int drv_at_send_cmd(const char *cmd, const char *response, uint32_t timeout)
+{
+ memset(qfc41dItem.buf, 0, QFC41D_MAX_RECV_SIZE);
+ qfc41dItem.buf_pos = 0; // սջ
+
+ drv_wireless_send_string(cmd);
+
+ uint32_t start_time = kit_time_get_tick(); // ȡǰʱ
+ while (kit_time_get_tick() - start_time < timeout)
+ {
+ if (strstr((char *)qfc41dItem.buf, response))
+ {
+ return 1; // ɹƥ䷵ֵ
+ }
+ }
+ return 0; // ʱδյ
+}
+
+static uint8_t drv_wifi_init()
+{
+ // 1. ģ鲨
+ if (!drv_at_send_cmd(QFC41D_SET_BATE, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("WiFi Module not responding!\r\n");
+ return 1 ;
+ }
+
+ // 2. AT ָ
+ if (!drv_at_send_cmd("AT", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("WiFi Module not responding!\r\n");
+ return 1 ;
+ }
+
+ // 3. Wi-Fi Ϊ DHCPʹ
+ if (!drv_at_send_cmd(QFC41D_SET_DHCP_ENABLE, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set WiFi mode!\r\n");
+ return 1;
+ }
+
+ // 4. Wi-Fi
+ snprintf(cmd, sizeof(cmd), "AT+QSTAAPINFODEF=%s,%s", wifiName, wifiPassWord);
+ if (!drv_at_send_cmd(cmd, "WIFI CONNECTED", WIFI_TIMEOUT * 2))
+ {
+ KIT_PRINTF("Failed to connect to WiFi!\r\n");
+ //return 1; //-ֹӰִ
+ }
+
+ // 5. ȡ IP ַ
+ if (!drv_at_send_cmd("AT+QGETIP=station", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to get IP address!\r\n");
+ //return 1; //-ֹӰִ
+ }
+
+ KIT_PRINTF("WiFi Initialization Successful!\r\n");
+ return 0;
+}
+
+static uint8_t drv_ble_init()
+{
+
+ // 1. ʼ,Ϊ
+ if (!drv_at_send_cmd("AT+QBLEINIT=2", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to power off BLE!\r\n");
+ return 1;
+ }
+
+ // 2.
+ snprintf(cmd, sizeof(cmd), "AT+QBLENAME=%s", bleName);
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set BLE name!\r\n");
+ return 1;
+ }
+
+ // 3. ù㲥
+ if (!drv_at_send_cmd("AT+QBLEADVPARAM=2048,2048", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to enable BLE!\r\n");
+ return 1;
+ }
+
+ // 4. ù㲥
+ if (!drv_at_send_cmd("AT+QBLEADVDATA=06094643343144", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to enable BLE!\r\n");
+ return 1;
+ }
+
+ // 5.
+ if (!drv_at_send_cmd("AT+QBLEGATTSSRV=FFF0", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set BLE role!\r\n");
+ return 1;
+ }
+
+ // 6. ֵ
+ if (!drv_at_send_cmd("AT+QBLEGATTSSRV=FFF1", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set BLE role!\r\n");
+ return 1;
+ }
+
+ // 7. ʼ㲥
+ if (!drv_at_send_cmd("AT+QBLEADVSTART", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to start BLE advertising!\r\n");
+ return 1;
+ }
+
+ KIT_PRINTF("BLE Initialization Successful!\r\n");
+ return 0;
+}
+
+
+uint8_t drv_qfc41d_init(void)
+{
+ //ʼ
+ drv_uart_init((UartDev)qfc41dItem.dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_WIRELESSUart_Tx, kGpioType_WIRELESSUart_Rx);
+
+ //ýջص
+ drv_uart_set_interrupt(QFC41D_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, drv_qf41d_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2
+
+ //ʼwifi
+ if(drv_wifi_init() != 0)
+ {
+ return 1;
+ }
+
+ /* Ԥ
+ //ʼBLE
+ if (drv_ble_init() != 0)
+ {
+ return 1;
+ }
+ */
+
+ return 0;
+}
+
+#define MQTT_BROKER "mqtt.example.com" // MQTT ַ
+#define MQTT_PORT 1883 // MQTT ˿
+#define MQTT_CLIENT_ID "fc41d_client" // ͻ ID
+#define MQTT_USER "user" // MQTT û
+#define MQTT_PASSWORD "password" // MQTT
+#define MQTT_TOPIC "fc41d/topic" // /
+#define MQTT_MESSAGE "Hello from FC41D!" // ͵Ϣ
+
+// MQTT
+static uint8_t drv_mqtt_connect()
+{
+
+ //1 MQTT Эİ汾Ϊ V4
+ snprintf(cmd, sizeof(cmd), "AT+QMTCFG=\"version\",1,4");
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set MQTT server!\r\n");
+ return 1;
+ }
+
+ //2 MQTT ͻ֮ĻỰ
+ snprintf(cmd, sizeof(cmd), "AT+QMTOPEN=1,\"%s\",%d",MQTT_BROKER,MQTT_PORT);
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set MQTT server!\r\n");
+ return 1;
+ }
+
+
+ //2MQTT ͻ֮佨 MQTT AT+QMTCONN=,,,
+ snprintf(cmd, sizeof(cmd), "AT+QMTCONN=1,%s,%s,%s",MQTT_CLIENT_ID,MQTT_USER, MQTT_PASSWORD);
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
+ return 1;
+ }
+
+
+ KIT_PRINTF("MQTT Connection Successful!\r\n");
+ return 0;
+}
+
+// MQTT
+static uint8_t drv_mqtt_subscribe()
+{
+ snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=1,1,\"%s\",0", MQTT_TOPIC);
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to subscribe to topic!\r\n");
+ return 1;
+ }
+
+ KIT_PRINTF("Subscribed to MQTT topic successfully!\r\n");
+ return 0;
+}
+
+// MQTT Ϣ
+/*
+ * AT+QMTPUB=,,,,,,
+ * length Χ0~1500
+ * str mqttjson
+ */
+uint8_t drv_mqtt_publish(char* str,uint16_t length)
+{
+ snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,0,0,%s,%d,%s",MQTT_TOPIC, length,str);
+ if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to publish message!\r\n");
+ return 1;
+ }
+
+ KIT_PRINTF("MQTT Message Published Successfully!\r\n");
+ return 0;
+}
+
+// MQTT ʼ
+uint8_t drv_mqtt_init()
+{
+ if (drv_mqtt_connect() != 0)
+ {
+ return 1;
+ }
+
+ if (drv_mqtt_subscribe() != 0)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/drv_peripheral/drv_qfc41d.c.orig b/library/drv_peripheral/drv_qfc41d.c.orig
new file mode 100644
index 0000000..435c38d
--- /dev/null
+++ b/library/drv_peripheral/drv_qfc41d.c.orig
@@ -0,0 +1,150 @@
+/******************************************************************************
+ * @file drv_qfc41d.c
+ * @brief drv_qfc41d driver
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+
+#include "drv_qfc41d.h"
+
+uint8_t rev_buff[QFC41D_MAX_RECV_SIZE] = {0};
+uint8_t send_buff[QFC41D_MAX_SEND_SIZE] = {0};
+uint8_t wifiName[40] = {0}, wifiPassWord[40] = {0};
+
+//
+WifiBleItem qfc41dItem = {
+ .dev = QFC41D_UART_PORT,
+ .buf_pos = 0,
+ .buf_size = QFC41D_MAX_RECV_SIZE,
+ .buf = rev_buff,
+ .sendCall = NULL,
+};
+
+static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len)
+{
+ uint16_t i = 0;
+
+ if((item != NULL) && (item->buf_pos + len < item->buf_size))
+ {
+ item->buf[item->buf_pos++] = buf[i];
+ // зʾһ AT ָ
+ if (buf[i] == '\n')
+ {
+ item->buf[item->buf_pos] = '\0'; // ӽ
+ item->buf_pos = 0; // һ
+ }
+ }
+}
+
+
+static void qf41d_uart_rx_it_call(kit_ret_e res, void *data)
+{
+ OS_TRACE_ISR_ENTER();
+ drv_qfc41d_push_data(&qfc41dItem, data, 1);
+ OS_TRACE_ISR_EXIT();
+}
+
+// ͵ַ
+void drv_wireless_send_char(char c)
+{
+ while (!(USART2->SR & USART_SR_TXE)); // ȴͻ
+ USART2->DR = c;
+}
+
+// ַ
+void drv_wireless_send_string(const char *str)
+{
+ while (*str)
+ {
+ drv_wireless_send_char(*str++);
+ }
+ drv_wireless_send_char('\r'); // CR
+ drv_wireless_send_char('\n'); // LF
+}
+
+
+// AT ָȴֵ
+int drv_wifi_send_cmd(const char *cmd, const char *response, uint32_t timeout)
+{
+ memset(qfc41dItem.buf, 0, QFC41D_MAX_RECV_SIZE);
+ qfc41dItem.buf_pos = 0; // սջ
+
+ drv_wireless_send_string(cmd);
+
+ uint32_t start_time = kit_time_get_tick(); // ȡǰʱ
+ while (kit_time_get_tick() - start_time < timeout)
+ {
+ if (strstr((char *)qfc41dItem.buf, response))
+ {
+ return 1; // ɹƥ䷵ֵ
+ }
+ }
+ return 0; // ʱδյ
+}
+
+static uint8_t drv_wifi_init()
+{
+ // 1. AT ָ
+ if (!drv_wifi_send_cmd("AT", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("WiFi Module not responding!\r\n");
+ return 1 ;
+ }
+
+ // 2. Wi-Fi Ϊ STA ģʽ
+ if (!drv_wifi_send_cmd("AT+CWMODE=1", "OK", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to set WiFi mode!\r\n");
+ return 1;
+ }
+
+ // 3. Wi-Fi
+ char cmd[128];
+ snprintf(cmd, sizeof(cmd), "AT+CWJAP=\"%s\",\"%s\"", wifiName, wifiPassWord);
+ if (!drv_wifi_send_cmd(cmd, "WIFI CONNECTED", WIFI_TIMEOUT * 2))
+ {
+ KIT_PRINTF("Failed to connect to WiFi!\r\n");
+ //return 1; //-ֹӰִ
+ }
+
+ // 4. ȡ IP ַ
+ if (!drv_wifi_send_cmd("AT+CIFSR", ".", WIFI_TIMEOUT))
+ {
+ KIT_PRINTF("Failed to get IP address!\r\n");
+ //return 1; //-ֹӰִ
+ }
+
+ KIT_PRINTF("WiFi Initialization Successful!\r\n");
+ return 0;
+}
+
+uint8_t drv_qfc41d_init(void)
+{
+ //ʼ
+ drv_uart_init((UartDev)qfc41dItem.dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_WIRELESSUart_Tx, kGpioType_WIRELESSUart_Rx);
+
+ //ýջص
+ drv_uart_set_interrupt(QFC41D_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, qf41d_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2
+
+ //ʼwifi
+ if(drv_wifi_init() != 0)
+ {
+ return 1;
+` }
+
+ //ʼ
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/library/drv_peripheral/drv_qfc41d.h b/library/drv_peripheral/drv_qfc41d.h
new file mode 100644
index 0000000..942b0b1
--- /dev/null
+++ b/library/drv_peripheral/drv_qfc41d.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ * @file drv_qfc41d.h
+ * @brief drv_qfc41d.h
+ * @version V1.0
+ * @author Gary
+ * @copyright
+ ******************************************************************************/
+#ifndef DRV_QFC41D_H_
+#define DRV_QFC41D_H_
+
+#include
+#include
+#include
+#include
+#include "drv_uart.h"
+#include "kit_macro.h"
+#include "ucos_ii.h"
+#include "gpio_manager.h"
+#include "kit_time.h"
+#include "kit_debug.h"
+
+#define QFC41D_UART_PORT kUartDev_2
+#define QFC41D_MAX_SEND_SIZE 2048
+#define QFC41D_MAX_RECV_SIZE 200
+#define WIFI_TIMEOUT 100
+
+#define QFC41D_RESTART_CMD "AT+QRST"
+#define QFC41D_PING_CMD "AT+QPING="
+#define QFC41D_LOW_POWER_MODE "AT+QLOWPOWER"
+#define QFC41D_GET_MACK_ADDR "AT+QWLMAC"
+#define QFC41D_GET_WIFISTA_STATUS "AT+QSTAST"
+#define QFC41D_SET_DHCP_ENABLE "AT+QSTADHCPDEF=1"
+
+//ôڲ:AT+QSETBAND=[,] ,ڲʡʡԸò沨ʡ0:沨 1:沨
+#define QFC41D_SET_BATE "AT+QSETBAND=115200,1"
+
+
+
+/* ģΪΧ豸ʱ GATT
+ * AT+QBLEGATTSNTFY=[,],
+ * ַͣ˫ţֵ UUID ȣ2 ֽڻ 16 ֽڡ
+ * ͡ʮݳȡʹøòʱģὫתΪʮٽ ͡磬Ϊ 123456ģὫתΪ 0x123456 з͡
+ * ַͣ˫ţGATT ݡ
+ */
+
+
+#define QFC41D_BLE_INIT "AT+QBLEINIT=2"
+
+typedef void (*FC41DSendCall)(UartDev dev, uint8_t *buf, uint16_t len);
+
+typedef struct
+{
+ uint8_t dev;
+ uint16_t buf_pos;
+ uint16_t buf_size;
+ uint8_t *buf;
+ FC41DSendCall sendCall;
+}WifiBleItem;
+
+uint8_t drv_qfc41d_init(void);
+
+// MQTT ʼ
+uint8_t drv_mqtt_init();
+
+// MQTT Ϣ
+uint8_t drv_mqtt_publish(char* str,uint16_t length);
+
+#endif //DRV_QFC41D_H_
+
diff --git a/library/drv_peripheral/drv_w5500.c b/library/drv_peripheral/drv_w5500.c
index 0230686..02dfe5c 100644
--- a/library/drv_peripheral/drv_w5500.c
+++ b/library/drv_peripheral/drv_w5500.c
@@ -61,7 +61,7 @@ void drv_w5500_init(W5500Item *item, uint32_t ip, uint16_t *port_array, uint32_t
#ifdef W5500_DEBUG
drv_w5500_read_comm_reg(item, W5500_GAR0_REG_0x01, buf, 4 + 4 + 6 + 4);
KIT_MODULE_PRINTF(W5500_PRT_EN, "w5500 param:");
- KIT_DEBUG_PRINTF_U8_BUF(buf, 4 + 4 + 6 + 4);
+ KIT_PRINTF_U8_BUF(buf, 4 + 4 + 6 + 4);
#endif
w5500_semaphore = OSSemCreate(1);
}
diff --git a/library/drv_stm32f4xx/drv_misc.c b/library/drv_stm32f4xx/drv_misc.c
index e61edaa..63038a3 100644
--- a/library/drv_stm32f4xx/drv_misc.c
+++ b/library/drv_stm32f4xx/drv_misc.c
@@ -76,7 +76,7 @@ void PVD_IRQHandler(void)
RCC->APB1ENR = 0;
pwr_off_call();
-// KIT_DEBUG_PRINTF("%s\r\n", "Poweroff");
+// KIT_PRINTF("%s\r\n", "Poweroff");
}
}
diff --git a/library/drv_stm32f4xx/drv_rtc.c b/library/drv_stm32f4xx/drv_rtc.c
index e2832cf..2c6c230 100644
--- a/library/drv_stm32f4xx/drv_rtc.c
+++ b/library/drv_stm32f4xx/drv_rtc.c
@@ -60,7 +60,7 @@ bool drv_rtc_init(void)
uint32_t dly = 0;
//if((RCC->BDCR & RCC_BDCR_RTCEN_POS) != RCC_BDCR_RTCEN_POS)
{
- KIT_DEBUG_PRINTF("rtc init\r\n");
+ KIT_PRINTF("rtc init\r\n");
RCC->APB1ENR |= RCC_APB1Periph_PWR;
//使能允许写入RTC和后备寄存器
PWR->CR |= PWR_CR_DBP;
@@ -71,11 +71,11 @@ bool drv_rtc_init(void)
bsp_task_delay_ms(10);
if(dly++ > 500)
{
- KIT_DEBUG_PRINTF("rtc fail \r\n");
+ KIT_PRINTF("rtc fail \r\n");
return res;
}
}
- KIT_DEBUG_PRINTF("rtc dly %d\r\n", dly);
+ KIT_PRINTF("rtc dly %d\r\n", dly);
RCC->BDCR |= (RCC_RTCCLKSource_LSE | RCC_BDCR_RTCEN_POS);
//RTC配置使用默认配置
//设置同步分频系数和异步分频系数,默认为1Hz = 32768/(同步分频 + 1)/(异步分频 + 1)
@@ -189,7 +189,9 @@ uint32_t drv_rtc_get_tick(void)
{
tmp.tm_mon--;
tmp.tm_year = (tmp.tm_year > 2018) ? (tmp.tm_year - 1900) : 119;
- res = kit_time_get_stamp(2019, &tmp);
+ res = mktime(&tmp);
+
+ //res = kit_time_get_stamp(2019, &tmp);
}
return res;
diff --git a/library/kit/kit_data.h b/library/kit/kit_data.h
index 86c612b..6f71b68 100644
--- a/library/kit/kit_data.h
+++ b/library/kit/kit_data.h
@@ -7,6 +7,7 @@ extern "C" {
#include "kit_macro.h"
+
uint8_t kit_check_crc8(uint16_t msg_id, const uint8_t *buf, uint32_t len);
void kit_append_crc8(uint16_t msg_id,uint8_t* buf, uint32_t len);
uint8_t kit_check_sum8(uint8_t *buf, uint16_t len);
diff --git a/library/kit/kit_debug.c b/library/kit/kit_debug.c
index 9cc91a5..78fa40b 100644
--- a/library/kit/kit_debug.c
+++ b/library/kit/kit_debug.c
@@ -7,12 +7,12 @@
void kit_assert_param(uint8_t* file, uint32_t line)
{
- KIT_DEBUG_PRINTF("%d, %s, %d\r\n", kit_time_get_tick(), file, line);
+ KIT_PRINTF("%d, %s, %d\r\n", kit_time_get_tick(), file, line);
}
void kit_assert_res(uint8_t* file, uint32_t line, uint32_t dev, kit_ret_e res)
{
- KIT_DEBUG_PRINTF("%d, %s, line:%d, dev:%d, res:%d\r\n", kit_time_get_tick(), file, line, dev, res);
+ KIT_PRINTF("%d, %s, line:%d, dev:%d, res:%d\r\n", kit_time_get_tick(), file, line, dev, res);
}
void kit_debug_queue(uint16_t *buf, uint8_t len, uint16_t value)
diff --git a/library/kit/kit_debug.h b/library/kit/kit_debug.h
index 8e718fa..ca2fbfc 100644
--- a/library/kit/kit_debug.h
+++ b/library/kit/kit_debug.h
@@ -32,7 +32,7 @@ extern "C" {
#if defined (DEBUG_PRINTF_RTT)
#include "SEGGER_RTT.h"
- #define KIT_DEBUG_PRINTF(fmt, args...) \
+ #define KIT_PRINTF(fmt, args...) \
do\
{\
SEGGER_RTT_printf(0, "%d %s>> ", kit_time_get_tick(), __FUNCTION__);\
@@ -46,7 +46,7 @@ extern "C" {
SEGGER_RTT_printf(0, fmt, ##args);\
}
- #define KIT_DEBUG_PRINTF_TIME() \
+ #define KIT_PRINTF_TIME() \
do\
{\
SEGGER_RTT_printf(0, "%d %s>> ", kit_time_get_tick(), __FUNCTION__);\
@@ -54,7 +54,7 @@ extern "C" {
}while(0)
#elif defined (DEBUG_ASSERT_UART)
#include "stdio.h"
- #define KIT_DEBUG_PRINTF(fmt, args...) \
+ #define KIT_PRINTF(fmt, args...) \
do\
{\
printf("%d %s>> ", kit_time_get_tick(), __FUNCTION__);\
@@ -62,12 +62,12 @@ extern "C" {
}while(0)
#else
- #define KIT_DEBUG_PRINTF(fmt, args...) ((void)0)
+ #define KIT_PRINTF(fmt, args...) ((void)0)
#endif
#if defined (DEBUG_PRINTF_RTT)
#include "SEGGER_RTT.h"
- #define KIT_DEBUG_PRINTF_U8_BUF(buf, len) \
+ #define KIT_PRINTF_U8_BUF(buf, len) \
do\
{\
uint32_t i = 0; \
@@ -79,7 +79,7 @@ extern "C" {
SEGGER_RTT_printf(0, "\r\n");\
}while(0)
- #define KIT_DEBUG_PRINTF_U16_BUF(buf, len) \
+ #define KIT_PRINTF_U16_BUF(buf, len) \
do\
{\
uint32_t i = 0; \
@@ -91,7 +91,7 @@ extern "C" {
SEGGER_RTT_printf(0, "\r\n");\
}while(0)
- #define KIT_DEBUG_PRINTF_I32_BUF(buf, len) \
+ #define KIT_PRINTF_I32_BUF(buf, len) \
do\
{\
uint32_t i = 0; \
@@ -104,7 +104,7 @@ extern "C" {
}while(0)
#elif defined (DEBUG_ASSERT_UART)
#include "stdio.h"
- #define KIT_DEBUG_PRINTF(fmt, args...) \
+ #define KIT_PRINTF(fmt, args...) \
do\
{\
printf("%d %s>> ", kit_time_get_tick(), __FUNCTION__);\
@@ -112,10 +112,10 @@ extern "C" {
}while(0)
#else
- #define KIT_DEBUG_PRINTF_U8_BUF(buf, len) ((void)0)
- #define KIT_DEBUG_PRINTF_U16_BUF(buf, len) ((void)0)
- #define KIT_DEBUG_PRINTF_I32_BUF(buf, len) ((void)0)
- #define KIT_DEBUG_PRINTF(fmt, args...) ((void)0)
+ #define KIT_PRINTF_U8_BUF(buf, len) ((void)0)
+ #define KIT_PRINTF_U16_BUF(buf, len) ((void)0)
+ #define KIT_PRINTF_I32_BUF(buf, len) ((void)0)
+ #define KIT_PRINTF(fmt, args...) ((void)0)
#define KIT_MODULE_PRINTF(en, fmt, args...) ((void)0)
#endif
diff --git a/library/kit/kit_macro.h b/library/kit/kit_macro.h
index 29f7888..f59f6bd 100644
--- a/library/kit/kit_macro.h
+++ b/library/kit/kit_macro.h
@@ -9,19 +9,16 @@ extern "C"
#include
#include
- typedef enum
- {
- kKit_Ret_Ok = 0x00,
- kKit_Ret_Error,
- kKit_Ret_Null,
- kKit_Ret_TimeOut,
- kKit_Ret_OutRange,
+/***************************жȼ*********************/
+#define APP_CFG_INT_PRIO_PWR_OFF 0u
+#define APP_CFG_INT_PRIO_CAN1_RX 1u
+#define APP_CFG_INT_PRIO_CAN1_TX 2u
+#define APP_CFG_INT_PRIO_CAN2_RX 3u
+#define APP_CFG_INT_PRIO_CAN2_TX 4u
+
+#define APP_CFG_INT_PRIO_SYSTICK 5u
+#define APP_CFG_INT_PRIO_UART2_RX 6u
- kKit_Ret_NullPtr,
- kKit_Ret_ParamErr,
- kKit_Ret_CheckErr,
- kKit_Ret_OverFlow,
- } kit_ret_e;
#define USE_BIT_ARRAY false
#define KIT_ABS(a) (((a) < 0) ? (-(a)) : (a))
@@ -30,7 +27,7 @@ extern "C"
#define KIT_MIN(a, b) (((a) < (b)) ? (a) : (b))
#if (USE_BIT_ARRAY == true)
- extern const uint32_t bit_array[];
+extern const uint32_t bit_array[];
#define KIT_BIT_MASK_32(pos) bit_array[bit]
#else
#define KIT_BIT_MASK_32(pos) ((uint32_t)0x01u << (pos))
@@ -49,8 +46,8 @@ extern "C"
#define KIT_GET_BIT_64(val, pos) ((val) & KIT_BIT_MASK_64(pos))
#define KIT_TOGGLE_BIT(val, mask) ((val) ^= (mask))
#define KIT_BIT_MASK_64S(start, end) ((0xFFFFFFFFFFFFFFFFu << (start)) & (0xFFFFFFFFFFFFFFFFu >> (63u - (uint32_t)(end))))
- // #define KIT_IS_BIT_SET(val, mask) (((val) & (mask)) == (mask))
- // #define KIT_IS_BIT_CLR(val, mask) (((val) & (mask)) == 0u)
+// #define KIT_IS_BIT_SET(val, mask) (((val) & (mask)) == (mask))
+// #define KIT_IS_BIT_CLR(val, mask) (((val) & (mask)) == 0u)
#define KIT_CREATE_IP(ip1, ip2, ip3, ip4) ((ip1) + ((uint32_t)(ip2) << 8) + ((uint32_t)(ip3) << 16) + ((uint32_t)(ip4) << 24))
#define KIT_CUR_CONVERT(val) ((val * 10))
@@ -182,11 +179,25 @@ extern "C"
#define ARM_WRITE_INT32U(addr) *((uint32_t *)(addr))
- typedef void (*NoArgFuncCall)(void);
- typedef void (*VoidArgFunCall)(void *arg);
- typedef void (*UintArgFunCall)(uint32_t arg);
- typedef void (*KitIrqCall)(kit_ret_e res, void *data);
- typedef void (*UintArgFunCall2)(kit_ret_e res, uint32_t data);
+typedef enum
+{
+ kKit_Ret_Ok = 0x00,
+ kKit_Ret_Error,
+ kKit_Ret_Null,
+ kKit_Ret_TimeOut,
+ kKit_Ret_OutRange,
+
+ kKit_Ret_NullPtr,
+ kKit_Ret_ParamErr,
+ kKit_Ret_CheckErr,
+ kKit_Ret_OverFlow,
+} kit_ret_e;
+
+typedef void (*NoArgFuncCall)(void);
+typedef void (*VoidArgFunCall)(void *arg);
+typedef void (*UintArgFunCall)(uint32_t arg);
+typedef void (*KitIrqCall)(kit_ret_e res, void *data);
+typedef void (*UintArgFunCall2)(kit_ret_e res, uint32_t data);
#ifdef __cplusplus
}
diff --git a/library/kit/kit_macro.h.orig b/library/kit/kit_macro.h.orig
new file mode 100644
index 0000000..59c403f
--- /dev/null
+++ b/library/kit/kit_macro.h.orig
@@ -0,0 +1,206 @@
+#ifndef _KIT_MACRO_H_
+#define _KIT_MACRO_H_
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include
+#include
+#include
+
+/***************************жȼ*********************/
+#define APP_CFG_INT_PRIO_PWR_OFF 0u
+#define APP_CFG_INT_PRIO_CAN1_RX 1u
+#define APP_CFG_INT_PRIO_CAN1_TX 2u
+#define APP_CFG_INT_PRIO_CAN2_RX 3u
+#define APP_CFG_INT_PRIO_CAN2_TX 4u
+
+#define APP_CFG_INT_PRIO_SYSTICK 5u
+#define APP_CFG_INT_PRIO_UART2_RX 6u
+
+
+#define USE_BIT_ARRAY false
+#define KIT_ABS(a) (((a) < 0) ? (-(a)) : (a))
+#define KIT_ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a)))
+#define KIT_MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define KIT_MIN(a, b) (((a) < (b)) ? (a) : (b))
+
+#if (USE_BIT_ARRAY == true)
+ extern const uint32_t bit_array[];
+#define KIT_BIT_MASK_32(pos) bit_array[bit]
+#else
+#define KIT_BIT_MASK_32(pos) ((uint32_t)0x01u << (pos))
+#define KIT_BIT_MASK_64(pos) ((uint64_t)0x01u << (pos))
+#endif
+
+#define KIT_GET_BIT_VAL(val, pos) (((val) >> (pos)) & 0x01u)
+
+#define KIT_SET_BIT_MASK_32_AT_POS(val, pos, bit) ((val) |= ((bit) << (pos)))
+#define KIT_BIT_MASK_32S(start, end) ((0xFFFFFFFFu << (start)) & (0xFFFFFFFFu >> (31u - (uint32_t)(end))))
+#define KIT_SET_BIT_MASK_32(val, pos) ((val) |= KIT_BIT_MASK_32(pos))
+#define KIT_SET_BIT_MASK_64(val, pos) ((val) |= KIT_BIT_MASK_64(pos))
+#define KIT_CLR_BIT_32(val, pos) ((val) &= ~KIT_BIT_MASK_32(pos))
+#define KIT_CLR_BIT_64(val, pos) ((val) &= ~KIT_BIT_MASK_64(pos))
+#define KIT_GET_BIT_32(val, pos) ((val) & KIT_BIT_MASK_32(pos))
+#define KIT_GET_BIT_64(val, pos) ((val) & KIT_BIT_MASK_64(pos))
+#define KIT_TOGGLE_BIT(val, mask) ((val) ^= (mask))
+#define KIT_BIT_MASK_64S(start, end) ((0xFFFFFFFFFFFFFFFFu << (start)) & (0xFFFFFFFFFFFFFFFFu >> (63u - (uint32_t)(end))))
+ // #define KIT_IS_BIT_SET(val, mask) (((val) & (mask)) == (mask))
+ // #define KIT_IS_BIT_CLR(val, mask) (((val) & (mask)) == 0u)
+
+#define KIT_CREATE_IP(ip1, ip2, ip3, ip4) ((ip1) + ((uint32_t)(ip2) << 8) + ((uint32_t)(ip3) << 16) + ((uint32_t)(ip4) << 24))
+#define KIT_CUR_CONVERT(val) ((val * 10))
+#define KIT_TEMP_CONVERT(val) ((val + 50) * 10)
+#define KIT_MILLI_CONVERT(val) (val)
+#define KIT_SECOND_CONVERT(val) ((val) * 1000)
+#define KIT_MINUTE_CONVERT(val) (KIT_SECOND_CONVERT(val) * 60)
+#define KIT_HOUR_CONVERT(val) (KIT_MINUTE_CONVERT(val) * 60)
+
+#define READ_BT_INT8U(ADDRESS, POS) (POS++, ADDRESS[POS - 1])
+#define READ_BT_INT16U(ADDRESS, POS) (POS += 2, (ADDRESS[POS - 1]) + ((uint16_t)(ADDRESS[POS - 2]) << 8))
+#define READ_BT_INT16U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 1]) + ((uint16_t)(ADDRESS[POS]) << 8))
+#define READ_BT_INT24U(ADDRESS, POS) (POS += 3, (ADDRESS[POS - 1]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 3]) << 16))
+#define READ_BT_INT24U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 2]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS]) << 16))
+#define READ_BT_INT32U(ADDRESS, POS) (POS += 4, (ADDRESS[POS - 1]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 3]) << 16) + ((uint32_t)(ADDRESS[POS - 4]) << 24))
+#define READ_BT_INT32U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS + 3]) + ((uint32_t)(ADDRESS[POS + 2]) << 8) + ((uint32_t)(ADDRESS[POS + 1]) << 16) + ((uint32_t)(ADDRESS[POS]) << 24))
+
+#define READ_LT_INT8U(ADDRESS, POS) (POS++, ADDRESS[POS - 1])
+#define READ_LT_INT16U(ADDRESS, POS) (POS += 2, (ADDRESS[POS - 2]) + ((uint16_t)(ADDRESS[POS - 1]) << 8))
+#define READ_LT_INT24U(ADDRESS, POS) (POS += 3, (ADDRESS[POS - 3]) + ((uint32_t)(ADDRESS[POS - 2]) << 8) + ((uint32_t)(ADDRESS[POS - 1]) << 16))
+#define READ_LT_INT32U(ADDRESS, POS) (POS += 4, (ADDRESS[POS - 4]) + ((uint32_t)(ADDRESS[POS - 3]) << 8) + ((uint32_t)(ADDRESS[POS - 2]) << 16) + ((uint32_t)(ADDRESS[POS - 1]) << 24))
+
+#define READ_LT_INT8U_BY_CONST_POS(ADDRESS, POS) (ADDRESS[POS])
+#define READ_LT_INT16U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint16_t)(ADDRESS[POS + 1]) << 8))
+#define READ_LT_INT24U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS + 2]) << 16))
+#define READ_LT_INT32U_BY_CONST_POS(ADDRESS, POS) ((ADDRESS[POS]) + ((uint32_t)(ADDRESS[POS + 1]) << 8) + ((uint32_t)(ADDRESS[POS + 2]) << 16) + ((uint32_t)(ADDRESS[POS + 3]) << 24))
+
+#define WRITE_BT_INT8U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)(VALUE); \
+ }
+#define WRITE_BT_INT16U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF); \
+ }
+#define WRITE_BT_INT24U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF); \
+ }
+#define WRITE_BT_INT32U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 24); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS++] = (uint8_t)(VALUE & 0xFF); \
+ }
+
+#define WRITE_BT_INT16U_BY_CONST_POS(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS + 1] = (uint8_t)(VALUE & 0xFF); \
+ }
+#define WRITE_BT_INT32U_BY_CONST_POS(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS] = (uint8_t)((VALUE) >> 24); \
+ ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 16); \
+ ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS + 3] = (uint8_t)(VALUE & 0xFF); \
+ }
+
+#define WRITE_LT_INT32U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)(VALUE); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 24); \
+ }
+#define WRITE_LT_INT24U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)(VALUE); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 16); \
+ }
+#define WRITE_LT_INT16U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)(VALUE); \
+ ADDRESS[POS++] = (uint8_t)((VALUE) >> 8); \
+ }
+#define WRITE_LT_INT8U(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS++] = (uint8_t)(VALUE); \
+ }
+
+#define WRITE_LT_INT32U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
+ { \
+ if (POS + 3 < SIZE) \
+ WRITE_LT_INT32U(ADDRESS, POS, VALUE); \
+ }
+#define WRITE_LT_INT24U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
+ { \
+ if (POS + 2 < SIZE) \
+ WRITE_LT_INT24U(ADDRESS, POS, VALUE); \
+ }
+#define WRITE_LT_INT16U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
+ { \
+ if (POS + 1 < SIZE) \
+ WRITE_LT_INT16U(ADDRESS, POS, VALUE); \
+ }
+#define WRITE_LT_INT8U_WITH_BUFF_SIZE(ADDRESS, POS, VALUE, SIZE) \
+ { \
+ if (POS < SIZE) \
+ WRITE_LT_INT8U(ADDRESS, POS, VALUE); \
+ }
+
+#define WRITE_LT_INT16U_BY_CONST_POS(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS] = (uint8_t)(VALUE); \
+ ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8); \
+ }
+#define WRITE_LT_INT24U_BY_CONST_POS(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS] = (uint8_t)(VALUE); \
+ ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 16); \
+ }
+#define WRITE_LT_INT32U_BY_CONST_POS(ADDRESS, POS, VALUE) \
+ { \
+ ADDRESS[POS] = (uint8_t)(VALUE); \
+ ADDRESS[POS + 1] = (uint8_t)((VALUE) >> 8); \
+ ADDRESS[POS + 2] = (uint8_t)((VALUE) >> 16); \
+ ADDRESS[POS + 3] = (uint8_t)((VALUE) >> 24); \
+ }
+
+#define ARM_READ_INT16U(addr) *((uint16_t *)(addr))
+#define ARM_READ_INT32U(addr) *((uint32_t *)(addr))
+
+#define ARM_WRITE_INT32U(addr) *((uint32_t *)(addr))
+
+ typedef enum
+ {
+ kKit_Ret_Ok = 0x00,
+ kKit_Ret_Error,
+ kKit_Ret_Null,
+ kKit_Ret_TimeOut,
+ kKit_Ret_OutRange,
+
+ kKit_Ret_NullPtr,
+ kKit_Ret_ParamErr,
+ kKit_Ret_CheckErr,
+ kKit_Ret_OverFlow,
+ } kit_ret_e;
+
+ typedef void (*NoArgFuncCall)(void);
+ typedef void (*VoidArgFunCall)(void *arg);
+ typedef void (*UintArgFunCall)(uint32_t arg);
+ typedef void (*KitIrqCall)(kit_ret_e res, void *data);
+ typedef void (*UintArgFunCall2)(kit_ret_e res, uint32_t data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/library/segger/SEGGER_HardFaultHandler.c b/library/segger/SEGGER_HardFaultHandler.c
index a003a27..be486fb 100644
--- a/library/segger/SEGGER_HardFaultHandler.c
+++ b/library/segger/SEGGER_HardFaultHandler.c
@@ -255,7 +255,7 @@ void HardFaultHandler(unsigned int* pStack)
// Halt execution
// To step out of the HardFaultHandler, change the variable value to != 0.
//
- KIT_DEBUG_PRINTF("%s\r\n", "HardFault");
+ KIT_PRINTF("%s\r\n", "HardFault");
bms_write_hardfault_data((uint8_t *)&HardFaultRegs, 64);
drv_misc_reset_mcu();
#else