After understanding that the device (and not Weave) should poll and update the air temperature state with IOTA_MAP_SET()
, I tackled this with a pthread.
Here's my main.c
...
#include <pthread.h>
// Function ran by background thread
void *update_air_temperature() {
GoogTempSensor* ambient_air_temperature =
GoogHvacControllerDevice_get_ambient_air_temperature(g_hvac_controller);
GoogTempSensor_State* ambient_air_temperature_state =
GoogTempSensor_get_state(ambient_air_temperature);
while(1) {
// Update air temperature state every 90 seconds
// Read air temperature from sensor
// Code to read sensor and assign value to air_temperature
float air_temperature;
...
// Update air temperature state
IOTA_MAP_SET(ambient_air_temperature_state, degrees_celsius, air_temperature);
sleep(90);
}
return NULL;
}
static IotaDaemon* create_hvac_controller_daemon_(void) {
IOTA_LOG_INFO("Inside create_hvac_controller_daemon_");
// Create the example hvac controller interface.
g_hvac_controller = GoogHvacControllerDevice_create(
GoogHvacControllerDevice_WITH_AMBIENT_AIR_TEMPERATURE |
GoogHvacControllerDevice_WITH_AMBIENT_AIR_HUMIDITY |
GoogHvacControllerDevice_WITH_DISPLAY_UNITS |
GoogHvacControllerDevice_WITH_HEAT_SUBSYSTEM |
GoogHvacControllerDevice_WITH_HEAT_SETTING);
IotaDevice* iota_device = iota_device_create_from_interface(
(IotaInterface*)g_hvac_controller, (IotaModelManifestId){"AHXXX"});
if (iota_device == NULL) {
IOTA_LOG_ERROR("Device create from interface failed");
GoogHvacControllerDevice_destroy(g_hvac_controller);
return NULL;
}
g_iota_daemon = host_framework_create_daemon("hvac_controller", iota_device);
// Set default state of traits on the hvac_controller.
example_hvac_controller_configure(g_hvac_controller, g_iota_daemon,
"Heating");
// Background thread to update air temperature
pthread_t thread1;
pthread_create(&thread1, NULL, update_air_temperature, NULL);
return g_iota_daemon;
}
int main(int argc, char** argv) {
HostIotaFrameworkConfig config = (HostIotaFrameworkConfig){
.base =
(IotaFrameworkConfig){
.cli_commands = NULL,
.num_commands = 0,
.builder = create_hvac_controller_daemon_,
},
.argc = argc,
.argv = argv,
.user_data = NULL,
.name = "hvac controller",
};
return host_framework_main(&config);
}
Don't forget to add -lpthread to the makefile:
...
EXTRA_LIBS=-lpthread
EXAMPLE_OUT_DIR := $(ARCH_OUT_DIR)/examples/$(EXAMPLE)
...
$(EXAMPLE_BIN): $(LIBIOTA_STATIC_LIB) $(PLATFORM_STATIC_LIB) \
$(EXAMPLES_COMMON_LIB) $(HOST_DEVFW_LIB) \
$(EXAMPLE_OBJECTS) | $(EXAMPLE_OUT_DIR)
$(CC) -Wl,--start-group $^ -Wl,--end-group -o $@ $(LDLIBS) $(PLATFORM_LDLIBS) $(EXTRA_LIBS)
...
Keep in mind that you should only report the new air temperature when it changes, and at a max frequency of 90 seconds. From the documentation:
Changes to the measured ambient temperature should be reported to the
cloud service when the temperature value changes by the minimum level
of granularity for the device UI, for example in 0.5 or 1 degree. If
the device does not support event-based reporting and utilizes
polling, the device should confirm a temperature value change of 0.5
or 1 degree, whichever is the UI's level of granularity, and update
the cloud service at most once every 90 seconds.