Nordic nRF52840 で Zigbee 温湿度測定をシュミレーションするエンドデバイスを作る

Nordic の SDK には、Zigbee で温度と気圧を測定するエンドデバイスの例があります。
今回はこれを基に、温度と湿度を測定するエンドデバイスを作成します。

元の ~~温度測定はnRF52 の SoC の温度を取得、大気圧は模擬的な値を生成~~ 温度測定、大気圧共に模擬的な値を生成しています。
今回作るものも、温湿度とも模擬的な値を出力するものとします。


# 環境
SDK nRF5_SDK_for_Thread_and_Zigbee_v4.0.0_dc7186b
Nordic nRF52840 (アオノドン2019)を使用

# 元にするプログラム

SDKディレクトリ中 examples - zigbee - experimental 中の、「multi_sensor」を元にして作っていきます。

# 設定内容

以下の項目はそのまま引き継ぎます。

- 周波数 (2.4GHz)
- チャンネル
- デバイスタイプ (エンドポイント)
- アドレス設定 (コーディネーターから自動割当)
- エンドポイント番号 (10)
- プロファイルID (Home Automation Profile = 0x0104)


cf., Zigbee のおさらい
https://qiita.com/nanbuwks/items/c480d9093af53f51c66a

- クラスタ番号は下記の通り設定します。

# クラスタを変更する


multi_sensor は

- クラスタ0402 (温度測定) 
- クラスタ0403 (圧力測定)

を備えていました。

これを温湿度測定に変更し、

- クラスタ0402 (温度測定) 
- クラスタ0405 (相対湿度測定)

とします。

実際のクラスタの定義を見てみると、SDKディレクトリ内の external/zboss/include/zcl/zb_zcl_common.h 内で以下のように定義されています。

```

 /* Measurement and Sensing */
  ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT = 0x0400,   /**< Illuminance measurement */
  ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT = 0x0402,          /**< Temperature measurement */
  ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT = 0x0403,      /**< Pressure measurement */
  ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT = 0x0405,  /**< Relative humidity measurement */
  ZB_ZCL_CLUSTER_ID_OCCUPANCY_SENSING = 0x0406,  /**< Occupancy sensing */
```

main.c では以下のようにクラスタ定義を利用しているので

```

static void zb_app_timer_handler(void * context)
{
    zb_zcl_status_t zcl_status;
    static zb_int16_t new_temp_value, new_pres_value;

    /* Get new temperature measured value */
    new_temp_value = (zb_int16_t)sensorsim_measure(&m_temperature_sim_state, &m_temperature_sim_cfg);
    zcl_status = zb_zcl_set_attr_val(MULTI_SENSOR_ENDPOINT, 
                                     ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, 
                                     ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                     ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, 
                                     (zb_uint8_t *)&new_temp_value, 
                                     ZB_FALSE);
    if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
    {
        NRF_LOG_INFO("Set temperature value fail. zcl_status: %d", zcl_status);
    }

    /* Get new pressure measured value */
    new_pres_value = (zb_int16_t)sensorsim_measure(&m_pressure_sim_state, &m_pressure_sim_cfg);
    zcl_status = zb_zcl_set_attr_val(MULTI_SENSOR_ENDPOINT,
                                     ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, 
                                     ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                     ZB_ZCL_ATTR_PRES_MEASUREMENT_VALUE_ID, 
                                     (zb_uint8_t *)&new_pres_value, 
                                     ZB_FALSE);
```

これの、
                                     ZB_ZCL_CLUSTER_ID_PRESSURE_MEASUREMENT, 
を
ZB_ZCL_CLUSTER_ID_REL_HUMIDITY_MEASUREMENT,

に変更します

# クラスタリストなどの書き換え

また、

```

ZB_ZCL_DECLARE_PRES_MEASUREMENT_ATTRIB_LIST(pressure_attr_list, 
                                            &m_dev_ctx.pres_attr.measure_value, 
                                            &m_dev_ctx.pres_attr.min_measure_value, 
                                            &m_dev_ctx.pres_attr.max_measure_value, 
                                            &m_dev_ctx.pres_attr.tolerance);

ZB_DECLARE_MULTI_SENSOR_CLUSTER_LIST(multi_sensor_clusters,
                                     basic_attr_list,
                                     identify_attr_list,
                                     temperature_attr_list,
                                     pressure_attr_list);

```

を

```

ZB_ZCL_DECLARE_REL_HUMIDITY_MEASUREMENT_ATTRIB_LIST(humidity_attr_list, 
                                            &m_dev_ctx.humi_attr.measure_value, 
                                            &m_dev_ctx.humi_attr.min_measure_value, 
                                            &m_dev_ctx.humi_attr.max_measure_value, 
                                            &m_dev_ctx.humi_attr.tolerance);

ZB_DECLARE_MULTI_SENSOR_CLUSTER_LIST(multi_sensor_clusters,
                                     basic_attr_list,
                                     identify_attr_list,
                                     temperature_attr_list,
                                     humidity_attr_list);

```
に変更します。


# 湿度の定義ファイルの確認

次に、書き換え元で使用している圧力の定義ファイルは

components/zigbee/pressure_cluster/zb_zcl_pressure_measurement.h

ですが、

新たに仕様する湿度の定義ファイルは


 external/zboss/include/zcl/zb_zcl_rel_humidity_measurement.h

となります。

# 変数名の変更

これの記述に合わせて main.c と zb_multi_sensor.hを書き換えます。

具体的には、presser に由来する変数名などを rel_humidity に由来する変数名などに書き換えます。

# tolerance アトリビュートの削除

注意点として、

```

ZB_ZCL_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(temperature_attr_list, 
                                            &m_dev_ctx.temp_attr.measure_value,
                                            &m_dev_ctx.temp_attr.min_measure_value, 
                                            &m_dev_ctx.temp_attr.max_measure_value, 
                                            &m_dev_ctx.temp_attr.tolerance);

ZB_ZCL_DECLARE_REL_HUMIDITY_MEASUREMENT_ATTRIB_LIST(rel_humidity_attr_list, 
                                            &m_dev_ctx.rel_humidity_attr.measure_value, 
                                            &m_dev_ctx.rel_humidity_attr.min_measure_value, 
                                            &m_dev_ctx.rel_humidity_attr.max_measure_value);


```

のように、rel_humidity には attr.tolerance が無いのでそれに関係する記述を削除します。

# 実行(デバッグ中)

CLIにつなげてデータを取ろうとした所。CLI側のログです。

```

> bdb role zc
Coordinator set
Done
> bdb start
Started coordinator
Done
> zdo match_desc 0xffff 0xffff 0x0104 2 0x0402 0x0405 0
Sending broadcast request.
> 
src_addr=FE13 ep=10

Done
zdo ieee_addr 0xFE13
> f4ce3686fe8d957b
Done
zdo eui64
f4ce365035f26ad5
Done
> zdo bind on f4ce3686fe8d957b 10 f4ce365035f26ad5 64 0x0402 0xFE13
> 
Done
zcl subscribe on  f4ce3686fe8d957b 10 0x0402 0x0104 0 41
> Done
zcl subscribe on  f4ce3686fe8d957b 10 0x0405 0x0104 0 41
> 
Error: Unable to configure attribute 0 reporting. Status: 141
Error: One or more attributes reporting were not configured successfully
log enable into zigbee.report
Unknown severity level: into
> log enable info zigbee.report
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3400
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3350
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3300
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3250
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3200
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3150
<info> zigbee.report: Received value updates from the remote node 0xFE13
<info> zigbee.report:     Profile: 0x0104 Cluster: 0x0402 Attribute: 0x0000 Type: 41 Value: 3100
```