简体   繁体   English

在 Weave Hvac 主机设备上持续更新气温

[英]Update air temperature continuously on Weave Hvac host device

I have an Hvac host device (see interface below) connected to Weave using Libiota and I'm having some trouble understanding how to update the current ambient air temperature (measured on the device).我有一个 Hvac 主机设备(见下面的界面)使用 Libiota 连接到 Weave,我在理解如何更新当前环境空气温度(在设备上测量)时遇到了一些麻烦。 I can measure it but I don't know how to update the state continuously so my Weave client displays the latest ambient air temperature.我可以测量它,但我不知道如何持续更新状态,以便我的 Weave 客户端显示最新的环境气温。

I don't fully understand this implementation note in 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." “当温度值以设备 UI 的最小粒度级别变化(例如 0.5 或 1 度)时,应将测量环境温度的变化报告给云服务。如果设备不支持基于事件的报告并利用轮询时,设备应确认温度值变化为 0.5 或 1 度,以 UI 的粒度级别为准,并且最多每 90 秒更新一次云服务。”

I'm able to update the current air temperature at device initialization (inside hvac_controller.c) and upon set temperature setting (ie when the heating temperature changes -inside hvac_controller_traits.c-).我能够在设备初始化(在 hvac_controller.c 内部)和设定温度设置时(即当加热温度改变时 - 在 hvac_controller_traits.c- 内部)更新当前空气温度。 I'm using this to update the ambient air temperature: IOTA_MAP_SET(ambient_air_temperature_state, degrees_celsius, myvalue);我正在使用它来更新环境空气温度: IOTA_MAP_SET(ambient_air_temperature_state, degrees_celsius, myvalue);

Interface:界面:

// 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);

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.在了解设备(而不是 Weave)应该使用IOTA_MAP_SET()轮询和更新气温状态后,我使用 pthread 解决了这个问题。

Here's my main.c这是我的 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:不要忘记在 makefile 中添加 -lpthread:

...
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.请记住,您应该只在新气温发生变化时报告新气温,并且最高频率为 90 秒。 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.当温度值以设备 UI 的最小粒度级别(例如 0.5 或 1 度)变化时,应将测量环境温度的变化报告给云服务。 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.如果设备不支持基于事件的报告并使用轮询,则设备应确认温度值变化为 0.5 或 1 度,以 UI 的粒度级别为准,并且最多每 90 秒更新一次云服务。

Changing libiota-owned state from outside of the daemon thread could cause trouble.从守护线程外部更改 libiota 拥有的状态可能会导致问题。 You should use host_iota_daemon_queue_application_job to post a callback to be invoked on the libiota daemon thread, rather than call IOTA_MAP_SET directly from your application thread.您应该使用host_iota_daemon_queue_application_job发布要在 libiota 守护程序线程上调用的回调,而不是直接从您的应用程序线程调用 IOTA_MAP_SET。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM