I followed this tutorial for installing a Kaa application into an ESP8266, and it worked after a few modifications: https://kaaproject.github.io/kaa/docs/v0.10.0/Programming-guide/Using-Kaa-endpoint-SDKs/C/SDK-ESP8266/
One of the modifications I had to make was to move a line of code in eagle.app.v6.ld because of byte overflow (arrow points to change I made):
...
.irom0.text : ALIGN(4)
{
_irom0_text_start = ABSOLUTE(.);
*(.literal.* .text.*) --> moved from ".text : ALIGN(4){...}"
...
}
...
After I did this I still had some byte overflow, so I modified the original cmake command from the documentation to disable cmake extensions that were taking up space:
cmake \
-DCMAKE_TOOLCHAIN_FILE=../kaa/toolchains/esp8266.cmake \
-DKAA_PLATFORM=esp8266 \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DWITH_EXTENSION_CONFIGURATION=OFF \
-DWITH_EXTENSION_EVENT=OFF \
-DWITH_EXTENSION_LOGGING=OFF \
-DWITH_EXTENSION_NOTIFICATION=OFF \
-DWITH_EXTENSION_USER=OFF \
-DWITH_ENCRYPTION=OFF \
-DKAA_MAX_LOG_LEVEL=3 ..
Finally, when I ran the make command. it worked. I then created and flashed the binaries into my ESP. Then I reset my ESP with GPIO0 high (so it can boot from flash) and the ESP sent "Hello, Kaa!" into the serial port I was connected to.
Now, however. I am trying to make it so that my ESP8266 connects to my Kaa server and generates an Endpoint Profile, so I need the code to create a transport channel to communicate to both the Bootstrap server and Operations server.
To do this, I tried using the code from Your First Kaa Application that generates fake temp readings and receives the configuration schema and pushes data to my Cassandra server via log appender: https://kaaproject.github.io/kaa/docs/v0.10.0/Programming-guide/Your-first-Kaa-application/
So in my attempt to do this, I left my directory the same:
CMakeLists.txt
driver/
uart.h
uart.c
ld/
eagle.app.v6.ld
eagle.rom.addr.v6.ld
kaa/
<put Kaa SDK here> --> replaced with new SDK with log and configuration schema
user/
user_main.c
src/
kaa_demo.c --> replaced with new code from "Your First Kaa Application"
I then replaced this code into my kaa_demo.c file:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <kaa/kaa.h>
#include <kaa/platform/kaa_client.h>
#include <kaa/kaa_error.h>
#include <extensions/configuration/kaa_configuration_manager.h>
#include <extensions/logging/kaa_logging.h>
#include <kaa/gen/kaa_logging_gen.h>
#include <kaa/platform/kaa_client.h>
#include <kaa/utilities/kaa_log.h>
#include <kaa/platform-impl/common/ext_log_upload_strategies.h>
static int32_t sample_period;
static time_t last_sample_time;
extern kaa_error_t ext_unlimited_log_storage_create(void **log_storage_context_p, kaa_logger_t *logger);
/* Retrieves current temperature. */
static int32_t get_temperature_sample(void)
{
/* For the sake of example, random data is used */
return rand() % 10 + 25;
}
/* Periodically called by Kaa SDK. */
static void example_callback(void *context)
{
time_t current_time = time(NULL);
/* Respect sample period */
if (difftime(current_time, last_sample_time) >= sample_period) {
int32_t temperature = get_temperature_sample();
printf("Sampled temperature: %i\n", temperature);
last_sample_time = current_time;
kaa_user_log_record_t *log_record = kaa_logging_data_collection_create();
log_record->temperature = temperature;
kaa_logging_add_record(kaa_client_get_context(context)->log_collector, log_record, NULL);
}
}
/* Receives new configuration data. */
static kaa_error_t on_configuration_updated(void *context, const kaa_root_configuration_t *conf)
{
(void) context;
printf("Received configuration data. New sample period: %i seconds\n", conf->sample_period);
sample_period = conf->sample_period;
return KAA_ERR_NONE;
}
int main(void)
{
/* Init random generator used to generate temperature */
srand(time(NULL));
/* Prepare Kaa client. */
kaa_client_t *kaa_client = NULL;
kaa_error_t error = kaa_client_create(&kaa_client, NULL);
if (error) {
return EXIT_FAILURE;
}
/* Configure notification manager. */
kaa_configuration_root_receiver_t receiver = {
.context = NULL,
.on_configuration_updated = on_configuration_updated
};
error = kaa_configuration_manager_set_root_receiver(
kaa_client_get_context(kaa_client)->configuration_manager,
&receiver);
if (error) {
return EXIT_FAILURE;
}
/* Obtain default configuration shipped within SDK. */
const kaa_root_configuration_t *dflt = kaa_configuration_manager_get_configuration(
kaa_client_get_context(kaa_client)->configuration_manager);
printf("Default sample period: %i seconds\n", dflt->sample_period);
sample_period = dflt->sample_period;
/* Configure data collection. */
void *log_storage_context = NULL;
void *log_upload_strategy_context = NULL;
/* The internal memory log storage distributed with Kaa SDK. */
error = ext_unlimited_log_storage_create(&log_storage_context,
kaa_client_get_context(kaa_client)->logger);
if (error) {
return EXIT_FAILURE;
}
/* Create a strategy based on timeout. */
error = ext_log_upload_strategy_create(
kaa_client_get_context(kaa_client), &log_upload_strategy_context,
KAA_LOG_UPLOAD_BY_TIMEOUT_STRATEGY);
if (error) {
return EXIT_FAILURE;
}
/* Strategy will upload logs every 5 seconds. */
error = ext_log_upload_strategy_set_upload_timeout(log_upload_strategy_context, 5);
if (error) {
return EXIT_FAILURE;
}
/* Specify log bucket size constraints. */
kaa_log_bucket_constraints_t bucket_sizes = {
.max_bucket_size = 32, /* Bucket size in bytes. */
.max_bucket_log_count = 2, /* Maximum log count in one bucket. */
};
/* Initialize the log storage and strategy (by default, they are not set). */
error = kaa_logging_init(kaa_client_get_context(kaa_client)->log_collector,
log_storage_context, log_upload_strategy_context, &bucket_sizes);
if (error) {
return EXIT_FAILURE;
}
/* Start Kaa SDK's main loop. example_callback is called once per second. */
error = kaa_client_start(kaa_client, example_callback, kaa_client, 1);
/* Should get here only after Kaa stops. */
kaa_client_destroy(kaa_client);
if (error) {
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
I left the CMakeLists.txt file the same:
cmake_minimum_required(VERSION 3.0.2)
project(kaa_demo C)
# Add Kaa SDK directory
add_subdirectory(kaa)
# Add source files
add_library(kaa_demo_s STATIC user/user_main.c driver/uart.c src/kaa_demo.c)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
if(NOT DEFINED ESP_RTOS_SDK)
set(ESP_RTOS_SDK /opt/Espressif/esp-rtos-sdk)
endif()
# specify include directories
target_include_directories(kaa_demo_s PUBLIC driver)
target_include_directories(kaa_demo_s PUBLIC .)
target_include_directories(kaa_demo_s PUBLIC
${ESP_RTOS_SDK}/extra_include
${ESP_RTOS_SDK}/include
${ESP_RTOS_SDK}/include/lwip
${ESP_RTOS_SDK}/include/lwip/ipv4
${ESP_RTOS_SDK}/include/lwip/ipv6
${ESP_RTOS_SDK}/include/espressif/
)
exec_program(xtensa-lx106-elf-gcc .
ARGS -print-libgcc-file-name
OUTPUT_VARIABLE ESP8266_LIBGCC
)
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/ld)
target_link_libraries(kaa_demo_s PUBLIC
kaac
${ESP_RTOS_SDK}/lib/libfreertos.a
${ESP_RTOS_SDK}/lib/libhal.a
${ESP_RTOS_SDK}/lib/libpp.a
${ESP_RTOS_SDK}/lib/libphy.a
${ESP_RTOS_SDK}/lib/libnet80211.a
${ESP_RTOS_SDK}/lib/libwpa.a
${ESP_RTOS_SDK}/lib/liblwip.a
${ESP_RTOS_SDK}/lib/libmain.a
${ESP_RTOS_SDK}/lib/libssl.a
${ESP_RTOS_SDK}/lib/libhal.a
${ESP8266_LIBGCC}
-Teagle.app.v6.ld
)
file(WRITE ${CMAKE_BINARY_DIR}/blank.c "")
add_executable(kaa_demo ${CMAKE_BINARY_DIR}/blank.c)
target_link_libraries(kaa_demo kaa_demo_s)
I left the user_main.c file the same:
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include "uart.h"
extern int main(void);
static void main_task(void *pvParameters)
{
(void)pvParameters;
main();
for (;;);
}
void user_init(void)
{
uart_init_new();
UART_SetBaudrate(UART0, 115200);
UART_SetPrintPort(UART0);
portBASE_TYPE error = xTaskCreate(main_task, "main_task", 512, NULL, 2, NULL );
if (error < 0) {
printf("Error creating main_task! Error code: %ld\r\n", error);
}
}
I left eagle.app.v6.ld (except for the modification described in the beginning) and eagle.rom.addr.ld, uart.h, and uart.c the same (obtained from github)
So when I change to the build directory and run this cmake command:
cmake \
-DCMAKE_TOOLCHAIN_FILE=../kaa/toolchains/esp8266.cmake \
-DKAA_PLATFORM=esp8266 \
-DCMAKE_BUILD_TYPE=MinSizeRel \
-DWITH_EXTENSION_CONFIGURATION=OFF \
-DWITH_EXTENSION_EVENT=OFF \
-DWITH_EXTENSION_LOGGING=OFF \
-DWITH_EXTENSION_NOTIFICATION=OFF \
-DWITH_EXTENSION_USER=OFF \
-DWITH_ENCRYPTION=OFF \
-DKAA_MAX_LOG_LEVEL=3 ..
I get this: (esp8266 is my username, kaa-app is the main directory that contains: CMakeLists.txt, build, drivers, etc.)
-- Default SDK location will be used: /opt/Espressif/esp-rtos-sdk
-- Toolchain path: /opt/Espressif/crosstool-NG/builds/xtensa-lx106-elf
-- ESP8266 SDK path: /opt/Espressif/esp-rtos-sdk
==================================
BUILD_TYPE = MinSizeRel
KAA_PLATFORM = esp8266
KAA_MAX_LOG_LEVEL = 3
==================================
BOOTSTRAP ENABLED
PROFILE ENABLED
KAA WILL BE INSTALLED TO /usr/local
-- Could NOT find Doxygen (missing: DOXYGEN_EXECUTABLE)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/esp8266/Documents/kaa-app/build
So then I run make, and I get this error:
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.example_callback+0x8): undefined reference to `time'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.example_callback+0xc): undefined reference to `difftime'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.example_callback+0x20): undefined reference to `kaa_logging_add_record'
libkaa_demo_s.a(kaa_demo2.c.obj): In function `example_callback':
kaa_demo2.c:(.text.example_callback+0x35): undefined reference to `time'
kaa_demo2.c:(.text.example_callback+0x42): undefined reference to `difftime'
kaa_demo2.c:(.text.example_callback+0x9e): undefined reference to `kaa_logging_add_record'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x10): undefined reference to `srand'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x14): undefined reference to `kaa_configuration_manager_set_root_receiver'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x18): undefined reference to `kaa_configuration_manager_get_configuration'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x1c): undefined reference to `ext_unlimited_log_storage_create'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x20): undefined reference to `ext_log_upload_strategy_create'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x24): undefined reference to `ext_log_upload_strategy_set_upload_timeout'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x28): undefined reference to `kaa_logging_init'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x3a): undefined reference to `time'
libkaa_demo_s.a(kaa_demo2.c.obj):(.text.startup.main+0x40): undefined reference to `srand'
libkaa_demo_s.a(kaa_demo2.c.obj): In function `main':
kaa_demo2.c:(.text.startup.main+0x69): undefined reference to `kaa_configuration_manager_set_root_receiver'
kaa_demo2.c:(.text.startup.main+0x7b): undefined reference to `kaa_configuration_manager_get_configuration'
kaa_demo2.c:(.text.startup.main+0xa5): undefined reference to `ext_unlimited_log_storage_create'
kaa_demo2.c:(.text.startup.main+0xb8): undefined reference to `ext_log_upload_strategy_create'
kaa_demo2.c:(.text.startup.main+0xc5): undefined reference to `ext_log_upload_strategy_set_upload_timeout'
kaa_demo2.c:(.text.startup.main+0xe6): undefined reference to `kaa_logging_init'
collect2: error: ld returned 1 exit status
CMakeFiles/kaa_demo.dir/build.make:120: recipe for target 'kaa_demo' failed
make[2]: *** [kaa_demo] Error 1
CMakeFiles/Makefile2:107: recipe for target 'CMakeFiles/kaa_demo.dir/all' failed
make[1]: *** [CMakeFiles/kaa_demo.dir/all] Error 2
Makefile:127: recipe for target 'all' failed
make: *** [all] Error 2
So it seems that when it tries linking the files it cannot find the new headers I included:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <kaa/kaa.h>
#include <kaa/platform/kaa_client.h>
#include <kaa/kaa_error.h>
#include <extensions/configuration/kaa_configuration_manager.h>
#include <extensions/logging/kaa_logging.h>
#include <kaa/gen/kaa_logging_gen.h>
#include <kaa/platform/kaa_client.h>
#include <kaa/utilities/kaa_log.h>
#include <kaa/platform-impl/common/ext_log_upload_strategies.h>
However, the target directory that is included in CMakeLists.txt contains the header files that I need (for the C headers):
${ESP_RTOS_SDK}/extra_include
So I really do not know what I need to add or modify, I am completely stuck. Any help would be much appreciated! Thanks!
For data_collection you have to set -DWITH_EXTENSION_LOGGING=ON
.
For esp8266 you have a different "time.h" library /kaa/src/kaa/platform-impl/esp8266/platform
that doesn't support the function time(NULL)
, but support
kaa_time_t kaa_esp8266_get_time(void);