dql2016 发表于 2021-7-5 19:58

RSL10-SENSE-DB-GEVK环境监测节点设计

本帖最后由 dql2016 于 2021-7-5 21:02 编辑

<h3>&nbsp;</h3>

<p>我的本次作品有一个环境监测节点,正好充分利用&nbsp;RSL10-SENSE-DB-GEVK的板载传感器:LV0104CS(环境光)、BME680(集成式高精度气体、压力、湿度和温度传感器)、INMP522(超低噪声数字麦克风)。原来调通了微信小程序与RSL10双向通信,RSL10端基于peripheral _server例程,后来在将传感器相关驱动、BDK相关组件添加到peripheral _server中后,无法同时采集数据和进行蓝牙通信了,原因在于RSL10-SENSE-DB-GEVK板卡的SDK和RSL10-002GEVB板卡的SDK相差太大,暂时没有精力去深究这个问题了,详见帖子:<strong>RSL10蓝牙特征值</strong>读写<a href="https://bbs.eeworld.com.cn/thread-1170300-1-1.html">https://bbs.eeworld.com.cn/thread-1170300-1-1.html</a>。因此只好另辟蹊径,周末抽空深入学习了RSL10-SENSE-DB-GEVK的SDK,在sense_ics_firmware例程的基础上实现了本次项目中环境监测节点的功能。环境监测节点的功能是将采集到的室内环境光、空气质量、温度、湿度、气压、声音通过蓝牙发送到微信小程序,并接受微信小程序下发的控制指令,当触发预设的规则后可以开启风扇等进行通风以改善室内空气质量,类似HAVC系统的功效,如图1所示。微信小程序拿到采集数据后,可以进行存储、分析,手机强大的性能或者是微信云平台的AI能力带来了无限可能。</p>

<p></p>

<p>图1 环境监测节点与微信小程序通信示意图</p>

<p>sense_ics_firmware例程通过自定义服务协议与安森美的官方手机app <strong>RSL10 Sense and Control</strong>通信&nbsp;,实现在手机app端显示板载传感器各项数据。在这个例程中,RSL10-SENSE-DB-GEVK板卡作为服务端,每种传感器、板载按键都被注册为一个服务节点,传感器采集的数据和按键状态则作为节点属性,客户端(手机app)向服务端请求读写属性值,这是一个典型的客户端-服务器模型。在这个协议中节点和属性用于访问具体的数据值,节点是属性的逻辑分组,它包含了一个具体设备的所有属性。属性是指可以被读取或者被写入的数据端点,每个节点具有的属性都是具体的。例如一个BLDC节点用于控制电动机,电动机具有可读可写的转速属性RPM,可写的方向属性DIR。请求令牌用于同步,客户端发出的每个请求包以&lsquo;0&rsquo;---&lsquo;~&rsquo;之间的随机数开头,服务端响应相同的请求令牌,因此两个不同的请求必须具有不同的请求令牌。分隔符&#39;/&#39;用于分割请求令牌、节点名、属性名、属性值。数据包长度可变,最大为20字节,一共有3中数据包:<br />
读请求包:用于索取给定属性的当前值。格式是<strong>请求令牌/节点名/属性名</strong>,例如s/ALS/LUX用于请求ALS节点的光照LUX属性值。<br />
写请求包:用于设置给定属性的新值。格式是<strong>请求令牌/节点名/属性名/属性值</strong>&nbsp;,例如d/BLDC/TGT/2560用于请求改变BLDC节点的TGT属性为整数值2560。客户端需要知道给定属性的数据类型,规范定义了标准节点和节点属性发现协议。<br />
响应包:一旦客户端请求到达服务端立即发送,格式是<strong>请求令牌/数据类型/值</strong>。<br />
响应包数据类型有:i有符号整数;f浮点数;h十六进制数;s字符串;t多个连续字符串,读请求时是页数,写请求时是给定页数的内容,可用于保存节点类型、节点描述、设备名、配置文件等;e错误字符串;n节点定义;p属性定义;c复合值,需要在应用中解析,在响应包中不包含数据类型。数据包是ascill字符串形式。</p>

<p></p>

<p>CMSIS-Pack文件夹下面的文档<em><strong>SL10 BLE Custom Service communication protocol.pdf</strong></em>详细介绍了这个通信协议。如图2、3、4展示了蓝牙调试app请求服务的过程:</p>

<p>图2 蓝牙app请求数据</p>

<p>图3 服务端响应数据1</p>

<p>图4&nbsp;服务端响应数据2</p>

<p>&nbsp;</p>

<p>本次项目不需要用到这个协议,只需要在这个例子的基础上进行一些修改即可。由于板卡硬件版本不支持光照传感器NOA1305取而代之的是LV0104CS,论坛大佬已分享相关帖子,这里我就直接把驱动拿来用,在此表示感谢。另外sense_ics_firmware例程也没有采集麦克风数据,因此对sense_ics_firmware例程的主要有2点:main.c函数中加入光照传感器LV0104CS和数字麦克风INMP522的初始化</p>

<pre>
<code class="language-cpp">//-----------------------------------------------------------------------------
// Copyright (c) 2018 Semiconductor Components Industries LLC
// (d/b/a "ON Semiconductor").All rights reserved.
// This software and/or documentation is licensed by ON Semiconductor under
// limited terms and conditions.The terms and conditions pertaining to the
// software and/or documentation are available at
// http://www.onsemi.com/site/pdf/ONSEMI_T&amp;C.pdf ("ON Semiconductor Standard
// Terms and Conditions of Sale, Section 8 Software") and if applicable the
// software license agreement.Do not use this software and/or documentation
// unless you have carefully read and you agree to the limited terms and
// conditions.By using this software and/or documentation, you agree to the
// limited terms and conditions.
//-----------------------------------------------------------------------------
#include &lt;stdio.h&gt;

#include &lt;BDK.h&gt;
#include &lt;BSP_Components.h&gt;
#include &lt;BLE_Components.h&gt;

#include &lt;ics/CS.h&gt;
#include &lt;ics/CS_Nodes.h&gt;
#include &lt;CSN_PB.h&gt; // PushButton custom node creation example

#include &lt;lv0104cs.h&gt;
#include &lt;lv0104cs_lux.h&gt;
#define AUDIO_DMIC0_GAIN                0x800
#define AUDIO_DMIC1_GAIN                0x800
#define AUDIO_OD_GAIN                   0x800

#define AUDIO_CONFIG                  (OD_AUDIOSLOWCLK            | \
                                       DMIC_AUDIOCLK            | \
                                       DECIMATE_BY_64             | \
                                       OD_UNDERRUN_PROTECT_ENABLE | \
                                       OD_DATA_MSB_ALIGNED      | \
                                       DMIC0_DATA_LSB_ALIGNED   | \
                                       DMIC1_DATA_LSB_ALIGNED   | \
                                       OD_DMA_REQ_DISABLE         | \
                                       DMIC0_DMA_REQ_DISABLE      | \
                                       DMIC1_DMA_REQ_DISABLE      | \
                                       OD_INT_GEN_DISABLE         | \
                                       DMIC0_INT_GEN_ENABLE       | \
                                       DMIC1_INT_GEN_DISABLE      | \
                                       OD_DISABLE               | \
                                       DMIC0_ENABLE               | \
                                       DMIC1_DISABLE)

int32_t dmic_value = 0;
int32_t dmic_max = 0;
int32_t dmic_min = INT32_MAX;
int32_t lv0104cs_status = -1;
int main(void)
{
        int32_t retval = 0;
    /* Initialize all needed BDK components. */
    BDK_Initialize();

    /* Initialize all LEDs. */
    LED_Initialize(LED_RED);
    LED_Initialize(LED_GREEN);
    LED_Initialize(LED_BLUE);


    //Initialize LV0104CS.
    retval = LV0104CS_LUX_Initialize();
    if (retval == LV0104CS_OK)
    {
      retval = LV0104CS_LUX_StartContinuous(0, NULL);
      if (retval == LV0104CS_OK)
      {
                lv0104cs_status= 0;
      }
      else
      {
                lv0104cs_status= 2;
      }
    }
    else
    {
          lv0104cs_status= 1;
    }
    printf("LV0104CS initialization: %s\n", lv0104cs_status == 0 ? "OK":"ERROR");

    //Configure DMIC input to test INMP522 microphone.
    // Configure AUDIOCLK to 2 MHz and AUDIOSLOWCLK to 1 MHz.
    CLK-&gt;DIV_CFG1 &amp;= ~(AUDIOCLK_PRESCALE_64 | AUDIOSLOWCLK_PRESCALE_4);
    CLK-&gt;DIV_CFG1 |= AUDIOCLK_PRESCALE_4 | AUDIOSLOWCLK_PRESCALE_2;

    //Configure OD, DMIC0 and DMIC1
    Sys_Audio_Set_Config(AUDIO_CONFIG);

    Sys_Audio_Set_DMICConfig(DMIC0_DCRM_CUTOFF_20HZ | DMIC1_DCRM_CUTOFF_20HZ |
                           DMIC1_DELAY_DISABLE | DMIC0_FALLING_EDGE |
                           DMIC1_RISING_EDGE, 0);

    Sys_Audio_DMICDIOConfig(DIO_6X_DRIVE | DIO_LPF_DISABLE | DIO_NO_PULL,
                            10, 6, DIO_MODE_AUDIOCLK);

    //Configure Gains for DMIC0, DMIC1 and OD
    AUDIO-&gt;DMIC0_GAIN = AUDIO_DMIC0_GAIN;
    NVIC_EnableIRQ(DMIC_OUT_OD_IN_IRQn);

    /* Indication - Initialization started. */
    LED_On(LED_BLUE);

    /* Initialize CS protocol, start Peripheral Server, Add Custom Service
   * Profile to it.
   */
    CS_Init();

    /* Optionally set advertising interval to be 200 to 250 ms long. */
    BDK_BLE_SetAdvertisementInterval(320, 400);

    /* Optionally set custom device name.
   * The name needs to contain one of 'IDK', 'BDK', 'RSL10' or 'BLE_Terminal'
   * patterns to be recognized by RSL10 Sense &amp; control mobile application.
   * Default: 'HB_BLE_Terminal'
   */
   BDK_BLE_SetLocalName("环境监测");

    /* Also add battery service if its RTE component is enabled. */
#if defined (RTE_BDK_BLE_PERIPHERAL_SERVER_BASS)
    BLE_BASS_Initialize(1000, 16);
    BLE_BASS_SetVoltageRange(CALC_VBAT_MEASURED(2.4f), CALC_VBAT_MEASURED(3.0f));
    // BLE_BASS_SetBattLevelInd(BattLevelChangeCallback);
#endif /* RTE_BDK_BLE_BASS_PRESENT */

    // Change default bus speed to 400kHz
    HAL_I2C_SetBusSpeed(HAL_I2C_BUS_SPEED_FAST);

    /* Add all enabled Custom Service Nodes. */
   // ASSERT_ALWAYS(CSN_ALS_CheckAvailability() == true);
   // ASSERT_ALWAYS(CS_RegisterNode(CSN_ALS_Create()) == CS_OK);

    ASSERT_ALWAYS(CSN_ENV_CheckAvailability() == true);
    ASSERT_ALWAYS(CS_RegisterNode(CSN_ENV_Create()) == CS_OK);

    ASSERT_ALWAYS(CSN_AO_CheckAvailability() == true);
    ASSERT_ALWAYS(CS_RegisterNode(CSN_AO_Create()) == CS_OK);

    ASSERT_ALWAYS(CS_RegisterNode(CSN_PB_Create()) == CS_OK);

    /* Indication - Initialization complete. */
    LED_Off(LED_BLUE);
    LED_On(LED_GREEN);
    HAL_Delay(250);
    LED_Off(LED_GREEN);

    CS_SYS_Info("Entering main loop.");
    while (1)
    {
      /* Execute any events that have occurred and refresh Watchdog. */
      BDK_Schedule();

      /* Enter sleep mode until an interrupt occurs. */
      SYS_WAIT_FOR_INTERRUPT;
    }

    return 0;
}

void DMIC_OUT_OD_IN_IRQHandler(void)
{
    dmic_value = (int32_t)AUDIO-&gt;DMIC0_DATA;

    if (dmic_max &lt; dmic_value)
    {
      dmic_max = dmic_value;
    }
    else
    {
      if (dmic_min &gt; dmic_value)
      {
            dmic_min = dmic_value;
      }
    }
}
</code></pre>

<p>在BSEC_ENV.c中BSEC_ENV_ReadData函数是一个定时调用的函数,在其中读取到数据后调用int CS_PlatformWrite(const char* tx_data, int tx_data_len)将数据以通知的方式发送出去。</p>

<p>这里的通信协议比较简单,将温度、湿度、光照、压力、空气质量、声音依次发送,先发高位字节,一共10个字节。</p>

<pre>
<code class="language-cpp">extern int32_t dmic_value;
extern int32_t dmic_max;
extern int32_t dmic_min;
extern lv0104cs_status;
extern struct BLE_ICS_Resources cs_res;
uint32_t lux = 0;
static void BSEC_ENV_ReadData(int64_t time_stamp_trigger, bsec_input_t *inputs,
      uint8_t *num_bsec_inputs, int32_t bsec_process_data)
{
    static struct bme680_field_data data;
    int8_t bme680_status = BME680_OK;
    int8_t buffer={0};

    /* We only have to read data if the previous call the bsec_sensor_control() actually asked for it */
    if (bsec_process_data)
    {
      bme680_status = bme680_get_sensor_data(&amp;data, &amp;bme680_g);
      ASSERT_DEBUG(bme680_status == BME680_OK);

      if (data.status &amp; BME680_NEW_DATA_MSK)
      {
            /* Pressure to be processed by BSEC */
            if (bsec_process_data &amp; BSEC_PROCESS_PRESSURE)
            {
                /* Place presssure sample into input struct */
                inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_PRESSURE;
                inputs[*num_bsec_inputs].signal = data.pressure;
                inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                (*num_bsec_inputs)++;
            }
            /* Temperature to be processed by BSEC */
            if (bsec_process_data &amp; BSEC_PROCESS_TEMPERATURE)
            {
                /* Place temperature sample into input struct */
                inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_TEMPERATURE;
#ifdef BME680_FLOAT_POINT_COMPENSATION
                inputs[*num_bsec_inputs].signal = data.temperature;
#else
                inputs[*num_bsec_inputs].signal = data.temperature / 100.0f;
#endif
                inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                (*num_bsec_inputs)++;

                /* Also add optional heatsource input which will be subtracted from the temperature reading to
               * compensate for device-specific self-heating (supported in BSEC IAQ solution)*/
                inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HEATSOURCE;
                inputs[*num_bsec_inputs].signal = bme680_temperature_offset_g;
                inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                (*num_bsec_inputs)++;
            }
            /* Humidity to be processed by BSEC */
            if (bsec_process_data &amp; BSEC_PROCESS_HUMIDITY)
            {
                /* Place humidity sample into input struct */
                inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HUMIDITY;
#ifdef BME680_FLOAT_POINT_COMPENSATION
                inputs[*num_bsec_inputs].signal = data.humidity;
#else
                inputs[*num_bsec_inputs].signal = data.humidity / 1000.0f;
#endif
                inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                (*num_bsec_inputs)++;
            }
            /* Gas to be processed by BSEC */
            if (bsec_process_data &amp; BSEC_PROCESS_GAS)
            {
                /* Check whether gas_valid flag is set */
                if (data.status &amp; BME680_GASM_VALID_MSK)
                {
                  /* Place sample into input struct */
                  inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_GASRESISTOR;
                  inputs[*num_bsec_inputs].signal = data.gas_resistance;
                  inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger;
                  (*num_bsec_inputs)++;
                }
            }
      }
      if (lv0104cs_status == 0)
      {
            LV0104CS_LUX_ReadLux(&amp;lux);
            printf("LV0104CS measured value:lux=%lu\n", lux);
      }
      CS_SYS_Info("INMP522 measured value: dmic_min=%ld dmic_value=%ld dmic_max=%ld\n", dmic_min, dmic_value,dmic_max);
      CS_SYS_Info("BME680 measured value: temperature=%d humidity=%d pressure=%d gas_resistance=%d\n",data.temperature/100,data.humidity/1000,data.pressure,data.gas_resistance);
      //通过通知发送给微信小程序
      buffer=data.temperature/100;//温度
      buffer=data.humidity/1000;//湿度
      buffer=((data.pressure &amp; 0xff00) &gt;&gt; 8 );//气压高8位
      buffer=(data.pressure &amp; 0x00ff);//气压低8位
      buffer=((data.gas_resistance &amp; 0xff00) &gt;&gt; 8 );//AQI高8位
      buffer=(data.gas_resistance &amp; 0x00ff);//AQI低8位
      buffer=((lux &amp; 0x0000ff00) &gt;&gt; 8 );//光照高8位
      buffer=(lux &amp; 0x000000ff);//光照低8位
      buffer=((dmic_value &amp; 0x0000ff00) &gt;&gt; 8 );//噪声高8位
      buffer=(dmic_value &amp; 0x000000ff);//噪声低8位
      if(cs_res.tx_cccd_value==0x0001)
      {
                        if(CS_PlatformWrite(buffer, sizeof(buffer))!=CS_OK)
                        {
                                CS_SYS_Info("=== CS_PlatformWrite Error ===");
                        }
      }
    }
}</code></pre>

<p>微信小程序发送给RSL10数据后会调用BLE_ICS.c中的BLE_ICS_GATTC_WriteReqInd回调,在这里可以得到通知是否开启/关闭</p>

<pre>
<code class="language-cpp">static int BLE_ICS_GATTC_WriteReqInd(ke_msg_id_t const msg_id,
      struct gattc_write_req_ind const *param, ke_task_id_t const dest_id,
      ke_task_id_t const src_id)
{
    uint8_t status = GAP_ERR_NO_ERROR;
    uint16_t att_num = 0;
    int conidx = BDK_BLE_GetConIdx();
    struct gattc_write_cfm *cfm;

    /* Check if connection is valid. */
    if (conidx == INVALID_DEV_IDX)
    {
      return KE_MSG_CONSUMED;
    }

    /* Check that offset is valid */
    if (param-&gt;offset != 0)
    {
      status = ATT_ERR_INVALID_OFFSET;
    }

    /* Get index of characteristic which was requested. */
    if (param-&gt;handle &gt; cs_res.start_hdl)
    {
      att_num = param-&gt;handle - cs_res.start_hdl - 1;
    }
    else
    {
      status = ATT_ERR_INVALID_HANDLE;
    }
    printf(&quot;[%d %s] get data from phone,att_num=%d\n&quot;,__LINE__,__FUNCTION__,att_num);
    if (status == GAP_ERR_NO_ERROR)
    {
      switch (att_num)
      {
      case ICS_IDX_TX_VALUE_CCC:
            if (param-&gt;length == 2)
            {
                    //手机APP端开启通知就是设置tx_cccd_value为0x0001关闭通知就是设置它的值为0x0000,
                //这是原来的值
               printf(&quot;[%d %s]old tx_cccd_value:0x%04x\n&quot;,__LINE__,__FUNCTION__,cs_res.tx_cccd_value);
               //要写入的新值
               printf(&quot;[%d %s]will write 0x&quot;,__LINE__,__FUNCTION__);
               //大端模式传输
               for(int i=param-&gt;length-1;i&gt;=0;i--)
               {
                       printf(&quot;%02x&quot;,param-&gt;value<i>);
               }
               printf(&quot; to it\n&quot;);
                memcpy(&amp;cs_res.tx_cccd_value, param-&gt;value, 2);
            }
            else
            {
                status = ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN;
            }
            break;

            /* New command was written. */
      case ICS_IDX_RX_VALUE_VAL:
            if (param-&gt;length &lt;= ICS_CHARACTERISTIC_VALUE_LENGTH)
            {
                    printf(&quot;[%d %s] get data from phone,rx_value:&quot;,__LINE__,__FUNCTION__);
                    for(int i=0;i&lt;param-&gt;length;i++)
                    {
                            printf(&quot;0x%02x &quot;,cs_res.tx_cccd_value);
                    }
                    printf(&quot;\n&quot;);
                memcpy(&amp;cs_res.rx_value, param-&gt;value, param-&gt;length);
                cs_res.rx_value_length = param-&gt;length;
            }
            else
            {
                status = ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN;
            }
            break;

      case ICS_IDX_RX_VALUE_CCC:
            if (param-&gt;length == 2)
            {
                    printf(&quot;[%d %s] get data from phone,rx_cccd_value=0x%04x\n&quot;,__LINE__,__FUNCTION__,cs_res.rx_cccd_value);
                memcpy(&amp;cs_res.rx_cccd_value, param-&gt;value, 2);
            }
            else
            {
                status = ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN;
            }
            break;

      default:
            status = ATT_ERR_WRITE_NOT_PERMITTED;
            break;
      }
    }

    cfm = KE_MSG_ALLOC(GATTC_WRITE_CFM, KE_BUILD_ID(TASK_GATTC, conidx),
            TASK_APP, gattc_write_cfm);

    cfm-&gt;handle = param-&gt;handle;
    cfm-&gt;status = status;

    ke_msg_send(cfm);

    /* Write indication handler */
    if (att_num == ICS_IDX_RX_VALUE_VAL &amp;&amp; cs_res.rx_write_handler != NULL
            &amp;&amp; status == GAP_ERR_NO_ERROR)
    {
      struct BLE_ICS_RxIndData ind;
      memcpy(ind.data, cs_res.rx_value, cs_res.rx_value_length);
      ind.data_len = cs_res.rx_value_length;

      cs_res.rx_write_handler(&amp;ind);
    }

    return KE_MSG_CONSUMED;
}</i></code></pre>

<p><i>在CS.c中CS_Loop函数可取得接收到的数据</i></p>

<pre>
<i>
<code class="language-cpp">int CS_Loop(int timeout)
{
        int errcode, bytes, i;
        uint32_t timestamp;
        struct CS_Request_Struct request;

        // Wait for BLE data with 10 ms timeout.
        errcode = CS_PlatformSleep(timeout);
        if (errcode != CS_OK)
        {
                return errcode;
        }

        timestamp = CS_PlatformTime();

        // Read available BLE packet.
        memset(cs_rx_buffer, 0, 21);
        //接收微信小程序发的数据
        errcode = CS_PlatformRead(cs_rx_buffer, 21, &amp;bytes);
        if (errcode != CS_OK || bytes &lt;= 0)
        {
                CS_SYS_Error(&quot;Platform read failed. (errcode=%d)&quot;, errcode);
                return CS_ERROR;
        }

#if CS_LOG_WITH_ANSI_COLORS != 0 &amp;&amp; defined RTE_DEVICE_BDK_OUTPUT_REDIRECTION
    CS_SYS_Info(&quot;Received request packet: &#39;&quot; COLORIZE(&quot;%s&quot;, CYAN, BOLD) &quot;&#39;&quot;,
            cs_rx_buffer);
#else
        CS_SYS_Info(&quot;Received request packet: &#39;%s&#39;&quot;, cs_rx_buffer);
#endif

        // Parse header information
        request.token = strtok(cs_rx_buffer, &quot;/&quot;);
        if (request.token == NULL)
        {
                CS_SYS_Error(&quot;Failed to parse request token.&quot;);
                return CS_ERROR;
        }
        if (strlen(request.token) != 1)
        {
                CS_SYS_Error(&quot;Invalid request token length.&quot;);
                return CS_ERROR;
        }
        if (request.token &lt; &#39;0&#39; || request.token &gt; &#39;~&#39;)
        {
                CS_SYS_Error(&quot;Invalid request token value.&quot;);
                return CS_ERROR;
        }

        request.node = strtok(NULL, &quot;/&quot;);
        if (request.node == NULL)
        {
                CS_SYS_Error(&quot;Failed to parse request node name.&quot;);
                return CS_ERROR;
        }

        request.property = strtok(NULL, &quot;/&quot;);
        if (request.property == NULL)
        {
                CS_SYS_Error(&quot;Failed to parse request node property.&quot;);
                return CS_ERROR;
        }

        // NULL for read requests
        request.property_value = strtok(NULL, &quot;/&quot;);

        // Iterate all available nodes to find a match.
        for (i = 0; i &lt; cs.node_cnt; ++i)
        {
                if (strcmp(request.node, cs.node<i>-&gt;name) == 0)
                {
                        // Matching node was found -&gt; pass request
                        errcode = cs.node<i>-&gt;request_handler(&amp;request, cs_node_response);
                        if (errcode == CS_OK &amp;&amp;
                          strlen(cs_node_response) &lt;= 18) // 2b for token + response = 20b
                        {
                                // Compose response packet from token + node response
                                sprintf(cs_tx_buffer, &quot;%s/%s&quot;, request.token, cs_node_response);
#if CS_LOG_WITH_ANSI_COLORS != 0 &amp;&amp; defined RTE_DEVICE_BDK_OUTPUT_REDIRECTION
                CS_SYS_Info(
                        &quot;Composed response packet &#39;&quot; COLORIZE(&quot;%s&quot;, MAGENTA, BOLD) &quot;&#39;&quot;,
                        cs_tx_buffer);
#else
                                CS_SYS_Info(&quot;Composed response packet &#39;%s&#39;&quot;, cs_tx_buffer);
#endif

                                // Send response to platform
                                int res_len = strlen(cs_tx_buffer);
                                if (CS_PlatformWrite(cs_tx_buffer, res_len) == CS_OK)
                                {
                                        timestamp = CS_PlatformTime() - timestamp;
                                        CS_SYS_Verbose(&quot;Request completed in %lu ms.&quot;, timestamp);
                                        return CS_OK;
                                }
                                else
                                {
                                        CS_SYS_Error(&quot;Platform send failed. (errcode=%d)&quot;, errcode);
                                        return CS_ERROR;
                                }
                        }
                        else
                        {
                                CS_SYS_Error(&quot;Node request processing error. (errcode=%d)&quot;, errcode);
                                sprintf(cs_tx_buffer, &quot;%s/e/UNK_ERROR&quot;, request.token);
                                errcode = CS_PlatformWrite(cs_tx_buffer, strlen(cs_tx_buffer));
                                if (errcode != CS_OK)
                                {
                                        CS_SYS_Error(&quot;Platform send failed. (errcode=%d)&quot;, errcode);
                                        return CS_ERROR;
                                }
                                // Node failed to process request
                                return CS_ERROR;
                        }
                }
        }

        CS_SYS_Error(&quot;No matching node found for &#39;%s&#39;&quot;, request.node);
        sprintf(cs_tx_buffer, &quot;%s/e/UNK_NODE&quot;, request.token);
        errcode = CS_PlatformWrite(cs_tx_buffer, strlen(cs_tx_buffer));
        if (errcode != CS_OK)
        {
                CS_SYS_Error(&quot;Platform send failed. (errcode=%d)&quot;, errcode);
                return CS_ERROR;
        }

        return CS_ERROR;
}</i></i></code></i></pre>

<p>&nbsp;</p>

<p><font face="monospace">下面来看看数据交互过程吧!</font></p>

<p><i><i><i></i></i></i></p>

<p><i><i><i>&nbsp;</i></i></i></p>

<p><i><i><i></i></i></i></p>

<p><i><i><i>&nbsp;</i></i></i></p>

<p><i><i><i></i></i></i></p>

<p><i><i><i>&nbsp;</i></i></i></p>

<p><i><i><i>微信小程序端接收到数据:</i></i></i></p>

<p><iframe allowfullscreen="true" frameborder="0" height="450" src="//player.bilibili.com/player.html?bvid=1to4y1C77d&amp;page=1" style="background:#eee;margin-bottom:10px;" width="750"></iframe><br />
&nbsp;</p>

<p><i><i><i>至此&nbsp;RSL10-SENSE-DB-GEVK板卡的功能就基于sense_ics_firmware例程实现,RSL10-002GEVB板卡的功能就基于peripheral _server例程实现,后续需要实现的节点功能就变的简单了。</i></i></i></p>

w494143467 发表于 2021-7-6 10:19

<p>不错不错,用微信小程序方便多了,都不用下载APP了!</p>

dql2016 发表于 2021-7-6 12:16

w494143467 发表于 2021-7-6 10:19
不错不错,用微信小程序方便多了,都不用下载APP了!

<p>跨平台方便</p>

okhxyyo 发表于 2021-7-6 15:28

<p>小程序确实挺方便的。</p>

dql2016 发表于 2021-7-6 16:58

okhxyyo 发表于 2021-7-6 15:28
小程序确实挺方便的。

<p><img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/smile.gif" width="48" /></p>

freebsder 发表于 2021-7-6 22:17

<p>小程序都做好了,从单片机到后台,厉害了。</p>

dql2016 发表于 2021-7-7 11:01

freebsder 发表于 2021-7-6 22:17
小程序都做好了,从单片机到后台,厉害了。

<p>正在研究数据库,小程序需要用微信云数据库,数据量大点要money<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/wanwan51.gif" width="48" /></p>

freebsder 发表于 2021-7-7 17:43

dql2016 发表于 2021-7-7 11:01
正在研究数据库,小程序需要用微信云数据库,数据量大点要money

<p>买个基本的云服务器呗,可玩性还比较大。</p>
页: [1]
查看完整版本: RSL10-SENSE-DB-GEVK环境监测节点设计