Controlling Nimble BLE Advertising Scan Channels on S3

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Fri Jan 05, 2024 7:13 pm

How do I control the advertising scan channels for numble ble_gap_disc() on the S3?

There appears to be an undocumented API in the ROM -- ble_ll_scan_channel_setting(). Is that what I want? What are the parameters? Why isn't this documented?

irahul
Posts: 46
Joined: Fri Jun 18, 2021 10:07 am

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby irahul » Mon Jan 08, 2024 3:52 am

> How do I control the advertising scan channels for numble ble_gap_disc() on the S3?

ble_gap_disc is used to discover / scan for devices in the vicinity. Per spec, during scanning there is no way host can set the channel, hence no such API exists in NimBLE / Bluedroid stack

However, if you refer to spec, then both LE Set Advertising params and LE set ext advertising params, has a way to set the advertising channel_map, where host can set the preferred channel. Peripheral can advertise on a particular channel.

> There appears to be an undocumented API in the ROM -- ble_ll_scan_channel_setting(). Is that what I want? What are the parameters? Why isn't this documented?


Because that code is not exposed and is part of proprietary Espressif closed library code. It is more for internal usage.

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Mon Jan 08, 2024 2:47 pm

So what is the best way to build a battery powered temperature sensor which connects to an ESP based device? The ESP device is mains powered and also on wifi with a small amount of traffic. My goal here is to minimize the number of packets the temp sensor is sending. If I use BLE advertising to send the temperature I have to send three packets (37,38,39) because I don't know what channel the ESP is listening on. Even if I send three packets the ESP is only seeing the temp 75% of the time. So in the current model I have to send six packets to have a good chance of communicating to the ESP.

The temp sensor tracks the temp and when it changes 0.2C it sends the temp. That results in a packet on average of once about every six minutes. I don't want to set up a BLE connection because that takes even more power. Maximum connection interval is four seconds which is 20x as many packets.

So what is the best way to send a packet to the ESP when the ESP is listening? The only thing the BLE engine on the ESP is doing is listening for the temp sensor, it is not dealing with any other BLE traffic. One proposal I found when searching is to set the scan interval up as high as possible, and then cancel the scan before it switches channels. Keep doing that as a technique to prevent the scan channel from changing. Does the ESP scan in a pre-determined order allowing this technique to work?

The temp sensor is a multiprotocol radio and I put the S3 into a different mode than BLE? Temp sensor can't generate wifi packets.

irahul
Posts: 46
Joined: Fri Jun 18, 2021 10:07 am

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby irahul » Thu Jan 11, 2024 4:09 am

Hello @jonsmirl,

Please try below in your application.

typedef enum {
SCAN_ALL_CHANNLE,
ONLY_SCAN_CHANNEL_37,
ONLY_SCAN_CHANNEL_38,
ONLY_SCAN_CHANNEL_39,
SCAN_MODE_TYPE_ERROR,
} scan_mode_config_t;

extern uint8_t esp_ble_scan_channel_setting(scan_mode_config_t scan_mode);


So your application can be modified as:

On peripheral side, set the channel number you would be advertising on , say on channel 37 . This can be done by passing appropriate parameters when calling le set adv parameters.

The on central side, you invoke the above API , BEFORE starting scanning. I.e. set the channel number to scan on ,and then start scanning. Please let me know if any more query.


Thanks.

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Thu Jan 11, 2024 6:33 pm

I have implemented esp_ble_scan_channel_setting() and verified that it works as expected. However, that does not seem to be the cause of my problems. If I set the sensor to Channel 37 and the S3 to Channel 39 I receive no packets, if I set them both to Channel 39 I see packets.

Also note that I have esp-matter also running on this S3. It is not doing much of anything but it does keep active wifi for things like MDNS.

As a test I have set my sensor to send three packets with 100ms spacing on channel 39 once per second. I have a sniffer which monitors these packets to verify they are being sent and are receivable. The sniffer is Nordic based and it never misses a single packet.

This is what I see on the S3. Note the Count column. If no packets are being dropped I should see each Count repeated three times at 100ms intervals. If you look between Count 262 and Count 265 I dropped ten packets in a row and received nothing for 2.8 seconds.

Code: Select all

I (1081616) ble_advert: BLE 34:f1:ae:d4:10:00 Count 257 RSSI 193 Temp 2086 Humid 39 Battery 3371
I (1081816) ble_advert: BLE 34:f1:ae:d4:10:00 Count 257 RSSI 193 Temp 2086 Humid 39 Battery 3371
I (1082636) ble_advert: BLE 34:f1:ae:d4:10:00 Count 258 RSSI 191 Temp 2085 Humid 39 Battery 3328
I (1082846) ble_advert: BLE 34:f1:ae:d4:10:00 Count 258 RSSI 192 Temp 2085 Humid 39 Battery 3328
I (1083766) ble_advert: BLE 34:f1:ae:d4:10:00 Count 259 RSSI 192 Temp 2087 Humid 39 Battery 3371
I (1083866) ble_advert: BLE 34:f1:ae:d4:10:00 Count 259 RSSI 192 Temp 2087 Humid 39 Battery 3371
I (1084676) ble_advert: BLE 34:f1:ae:d4:10:00 Count 260 RSSI 191 Temp 2084 Humid 39 Battery 3328
I (1084886) ble_advert: BLE 34:f1:ae:d4:10:00 Count 260 RSSI 191 Temp 2084 Humid 39 Battery 3328
I (1085706) ble_advert: BLE 34:f1:ae:d4:10:00 Count 261 RSSI 191 Temp 2084 Humid 39 Battery 3371
I (1085816) ble_advert: BLE 34:f1:ae:d4:10:00 Count 261 RSSI 191 Temp 2084 Humid 39 Battery 3371
I (1085926) ble_advert: BLE 34:f1:ae:d4:10:00 Count 261 RSSI 191 Temp 2084 Humid 39 Battery 3371
I (1086936) ble_advert: BLE 34:f1:ae:d4:10:00 Count 262 RSSI 192 Temp 2086 Humid 39 Battery 3328
I (1089786) ble_advert: BLE 34:f1:ae:d4:10:00 Count 265 RSSI 192 Temp 2085 Humid 39 Battery 3371
I (1090816) ble_advert: BLE 34:f1:ae:d4:10:00 Count 266 RSSI 192 Temp 2085 Humid 39 Battery 3328
I (1090926) ble_advert: BLE 34:f1:ae:d4:10:00 Count 266 RSSI 192 Temp 2085 Humid 39 Battery 3328
I (1091036) ble_advert: BLE 34:f1:ae:d4:10:00 Count 266 RSSI 191 Temp 2085 Humid 39 Battery 3328
I (1091836) ble_advert: BLE 34:f1:ae:d4:10:00 Count 267 RSSI 191 Temp 2084 Humid 39 Battery 3328
I (1091946) ble_advert: BLE 34:f1:ae:d4:10:00 Count 267 RSSI 191 Temp 2084 Humid 39 Battery 3328
I (1092046) ble_advert: BLE 34:f1:ae:d4:10:00 Count 267 RSSI 191 Temp 2084 Humid 39 Battery 3328
I (1092856) ble_advert: BLE 34:f1:ae:d4:10:00 Count 268 RSSI 191 Temp 2085 Humid 39 Battery 3328
I (1093066) ble_advert: BLE 34:f1:ae:d4:10:00 Count 268 RSSI 191 Temp 2085 Humid 39 Battery 3328
I (1093986) ble_advert: BLE 34:f1:ae:d4:10:00 Count 269 RSSI 192 Temp 2085 Humid 39 Battery 3328
I (1094096) ble_advert: BLE 34:f1:ae:d4:10:00 Count 269 RSSI 192 Temp 2085 Humid 39 Battery 3328
I (1095116) ble_advert: BLE 34:f1:ae:d4:10:00 Count 270 RSSI 192 Temp 2086 Humid 39 Battery 3328
I (1096136) ble_advert: BLE 34:f1:ae:d4:10:00 Count 271 RSSI 191 Temp 2085 Humid 39 Battery 3328
I (1096946) ble_advert: BLE 34:f1:ae:d4:10:00 Count 272 RSSI 191 Temp 2085 Humid 39 Battery 3328
The scan should permanently be running on Channel 39. So why am I dropping so many packets? The RSSI is really good, the devices are only 40cm apart.

Code: Select all

typedef enum {
SCAN_ALL_CHANNLE,
ONLY_SCAN_CHANNEL_37,
ONLY_SCAN_CHANNEL_38,
ONLY_SCAN_CHANNEL_39,
SCAN_MODE_TYPE_ERROR,
} scan_mode_config_t;

extern "C" uint8_t esp_ble_scan_channel_setting(scan_mode_config_t scan_mode);

esp_err_t StartScan()
{
    uint8_t ownAddrType;
    struct ble_gap_disc_params discParams;
    int rc;

    /* Figure out address to use while advertising. */
    rc = ble_hs_id_infer_auto(0, &ownAddrType);
    if (rc != 0)
    {
        // ChipLogError(DeviceLayer, "ble_hs_id_infer_auto failed: %d", rc);
        return ESP_ERR_INVALID_STATE;
    }

    /* Set up discovery parameters. */
    memset(&discParams, 0, sizeof(discParams));

    /* Tell the controller to filter the duplicates. */
    discParams.filter_duplicates = 0;
    /* Perform passive scanning. */
    discParams.passive = 1;
    /* Use defaults for the rest of the parameters. */
    discParams.itvl = 0;
    discParams.window = 0;
    discParams.filter_policy = 0;
    discParams.limited = 0;

    esp_ble_scan_channel_setting(ONLY_SCAN_CHANNEL_39);

    /* Start the discovery process. */
    rc = ble_gap_disc(ownAddrType, BLE_HS_FOREVER, &discParams, OnBleCentralEvent, NULL);
    if (rc != 0)
    {
        ESP_LOGE(TAG, "ble_gap_disc failed: %d", rc);
        return ESP_ERR_INVALID_STATE;
    }
    return ESP_OK;
}

irahul
Posts: 46
Joined: Fri Jun 18, 2021 10:07 am

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby irahul » Fri Jan 12, 2024 6:13 am

Hello @jonsmirl,

Setting scan interval and window as 0 would result in default value. Can you modify them to 100 ms ( so set value as 160 decimal ).

Also, is this operation being done in open air ? which can result in packet loss ?

Can you shutdown matter activity on wifi also for testing purpose. We can confirm if coex activity is taking some bandwidth resulting in such behaviour as you observe.

Is the packet loss observed multiple times at your end ? or periodically ?

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Fri Jan 12, 2024 6:57 pm

Here's the periodicity of dropping packets. It is sending three packets once per second. These are the seconds when all three were dropped. First column is the seconds count, second is the delta seconds. The average delta is 25 seconds. Starts at 315. No code is changed from previous post.

Code: Select all

325	
377	52
440	63
466	26
468	2
542	74
609	67
620	11
681	61
706	25
754	48
812	58
857	45
864	7
949	85
995	46
1033	38
1104	71
1130	26
1160	30
1168	8
1228	60
1262	34
1337	75
1386	49
1481	95
1535	54
1575	40
1581	6
1593	12
1597	4
1620	23
1645	25
1657	12
1659	2
1718	59
1736	18
1739	3
1796	57
1803	7
1849	46
1877	28
1881	4
1927	46
1938	11
1972	34
1991	19
1996	5
2040	44
2068	28
2070	2
2088	18
2091	3
2201	110
2207	6
2209	2
2246	37
2301	55
2305	4
2349	44
2372	23
2422	50
2443	21
2459	16
2462	3
2492	30
2494	2
2496	2
2499	3
2505	6
2507	2
2511	4
2535	24
2538	3
2543	5
2548	5
2550	2
2559	9
2561	2
2566	5
2569	3
2577	8
2606	29
2614	8
2617	3
2623	6
2648	25
2655	7
2658	3
2660	2
2667	7
2699	32
2705	6
2712	7
2732	20
2738	6
2740	2
2745	5
2748	3
2769	21
2776	7
2780	4
2786	6
2804	18
2806	2
2809	3
2818	9
2824	6
2826	2
2852	26
2856	4
2859	3
2877	18
2879	2
2882	3
2885	3
2890	5
2929	39
2952	23
2965	13
2984	19
2986	2
2990	4
2995	5
3024	29
3029	5
3031	2
3068	37
3102	34
3125	23
3134	9
3170	36
3205	35
3225	20
3234	9
3297	63
3321	24
3360	39
3365	5
3396	31
3415	19
3460	45
3484	24
3491	7
3493	2
3519	26
3556	37
3559	3
3595	36
3636	41
3650	14
3656	6
3667	11
3689	22
3695	6
3714	19
3720	6
3752	32
3760	8
3790	30
3824	34
3852	28
3885	33
3891	6
3930	39
3949	19
3954	5
4028	74
4048	20
4065	17
4120	55
4126	6
4134	8
4165	31
4173	8
4214	41
4256	42
4275	19
4295	20
4355	60
4379	24
4400	21
4415	15
4473	58
4496	23
4498	2
4535	37
4596	61
4613	17
4677	64
4679	2
4711	32
4731	20
4733	2
4782	49
4825	43
4831	6
4839	8
4842	3
4878	36
4884	6
4918	34
4954	36
4991	37
5025	34
5037	12
5060	23
5123	63
5141	18
5162	21
5164	2
5201	37
5203	2
5207	4
5215	8
5256	41
5263	7
5295	32
5340	45
5343	3
5376	33
5397	21
5438	41
5442	4
5482	40
5526	44
5601	75
5622	21
5638	16
5671	33
5716	45
5721	5
5754	33
5802	48
5828	26
5830	2
5838	8
5857	19
5908	51
5912	4
5951	39
5960	9
5993	33
6031	38
6053	22
6068	15
6092	24
6094	2
6102	8
6105	3
6143	38
6182	39
6218	36
6263	45
6288	25
6335	47
6376	41
6385	9
6387	2
6417	30
6423	6
6464	41
6554	90
6559	5
6579	20
6582	3
6587	5
6601	14
6606	5
6610	4
6646	36
6694	48
6773	79
6783	10
6807	24
6824	17
6900	76
6926	26
6930	4
6940	10
7021	81
7024	3
7061	37
7064	3
7100	36
7110	10
7149	39
7198	49
7220	22
7243	23
7245	2
7286	41
7306	20
7333	27
7335	2
7384	49
7435	51
7438	3
7467	29
7475	8
7479	4
7521	42
7563	42
7629	66
7646	17
7674	28
7686	12
7707	21
7713	6
7727	14
7762	35
7801	39
7854	53
7873	19
7903	30
7925	22
7987	62
8010	23
8015	5
8114	99
8120	6
8129	9
8131	2
8133	2
8185	52
8188	3
8221	33
8255	34
8261	6
8277	16
8300	23
8325	25
8327	2
8378	51
8420	42
8441	21
8468	27
8490	22
8496	6
8498	2
8510	12
8519	9
8523	4
8525	2
8528	3
8557	29
8562	5
8569	7
8662	93
8668	6
8671	3
8754	83
8764	10
8803	39
8805	2
8844	39
8858	14
8869	11
8897	28
8908	11
8942	34
8950	8
8981	31
9000	19
9004	4
9030	26
9045	15
9079	34
9171	92
9216	45
9224	8
9302	78
9312	10
9314	2
9324	10
9351	27
9353	2
9435	82
9437	2
9535	98
9539	4
9568	29
9584	16
9661	77
9664	3
9710	46
9722	12
9764	42
9769	5
9803	34
9822	19
9850	28
9859	9
9864	5
9867	3
9870	3
9921	51
9924	3
9932	8
9979	47
9983	4
10000	17
10035	35
10043	8
10077	34
10087	10
10092	5
10154	62
10163	9
10201	38
10251	50
10253	2
10257	4
10271	14
10329	58
10384	55
10390	6
10392	2
10451	59
10458	7
10460	2
10462	2
10515	53
10525	10
10529	4
10597	68
10642	45
10646	4
10760	114
10777	17
10840	63
10883	43
10892	9
10909	17
10982	73
11016	34

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Fri Jan 12, 2024 7:27 pm

Changing intvl and window to 160 doesn't seem to have any impact. Average of 33 seconds.

Code: Select all

8	
30	22
51	21
90	39
134	44
142	8
148	6
154	6
156	2
198	42
298	100
348	50
392	44
463	71
475	12
534	59
576	42
614	38
649	35
699	50
725	26
818	93
820	2
862	42
881	19
938	57
966	28
973	7
986	13

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Fri Jan 12, 2024 8:45 pm

Next I made a BLE only test program by stripping down the blecent example.

Code: Select all

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "esp_log.h"
#include "nvs_flash.h"
/* BLE */
#include "nimble/nimble_port.h"
#include "nimble/nimble_port_freertos.h"
#include "host/ble_hs.h"
#include "host/util/util.h"
#include "console/console.h"
#include "services/gap/ble_svc_gap.h"
#include "blecent.h"

static const char *TAG = "ble_cent";

void ReportDevice(const struct ble_hs_adv_fields *fields, const ble_addr_t *addr, uint8_t rssi)
{
    if (fields->mfg_data != NULL)
    {
        if ((fields->mfg_data[0] == 0x4c) && (fields->mfg_data[1] == 0xd))
        {

            int i = 2;
            uint16_t temp, humid, battery, count;
            temp = humid = battery = count = 0;
            while (i < fields->mfg_data_len)
            {
                switch (fields->mfg_data[i])
                {
                case 2:
                    temp = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                case 5:
                    humid = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                case 0xfe:
                    count = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                default:
                case 0xff:
                    battery = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                }
                i += 3;
            }
            ESP_LOGI(TAG, "BLE %s Count %u RSSI %u Temp %u Humid %u Battery %u", addr_str((void *)addr), count, rssi, temp, humid, battery);
        }
    }
}


/**
 * The nimble host executes this callback when a GAP event occurs.  The
 * application associates a GAP event callback with each connection that is
 * established.  blecent uses the same callback for all connections.
 *
 * @param event                 The event being signalled.
 * @param arg                   Application-specified argument; unused by
 *                                  blecent.
 *
 * @return                      0 if the application successfully handled the
 *                                  event; nonzero on failure.  The semantics
 *                                  of the return code is specific to the
 *                                  particular GAP event being signalled.
 */
static int
blecent_gap_event(struct ble_gap_event *event, void *arg)
{
    struct ble_gap_conn_desc desc;
    struct ble_hs_adv_fields fields;
    int rc;

    switch (event->type) {
    case BLE_GAP_EVENT_DISC:
        ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data);
        ReportDevice(&fields, &event->disc.addr, event->disc.rssi);
        return 0;


    default:
        return 0;
    }
}

typedef enum {
SCAN_ALL_CHANNLE,
ONLY_SCAN_CHANNEL_37,
ONLY_SCAN_CHANNEL_38,
ONLY_SCAN_CHANNEL_39,
SCAN_MODE_TYPE_ERROR,
} scan_mode_config_t;

extern uint8_t esp_ble_scan_channel_setting(scan_mode_config_t scan_mode);

/**
 * Initiates the GAP general discovery procedure.
 */
static void
blecent_scan(void)
{
    uint8_t own_addr_type;
    struct ble_gap_disc_params disc_params;
    int rc;

    /* Figure out address to use while advertising (no privacy for now) */
    rc = ble_hs_id_infer_auto(0, &own_addr_type);
    if (rc != 0) {
        MODLOG_DFLT(ERROR, "error determining address type; rc=%d\n", rc);
        return;
    }

    /* Tell the controller to filter duplicates; we don't want to process
     * repeated advertisements from the same device.
     */
    disc_params.filter_duplicates = 0;

    /**
     * Perform a passive scan.  I.e., don't send follow-up scan requests to
     * each advertiser.
     */
    disc_params.passive = 1;

    /* Use defaults for the rest of the parameters. */
    disc_params.itvl = 160;
    disc_params.window = 160;
    disc_params.filter_policy = 0;
    disc_params.limited = 0;

    esp_ble_scan_channel_setting(ONLY_SCAN_CHANNEL_39);

    rc = ble_gap_disc(own_addr_type, BLE_HS_FOREVER, &disc_params,
                      blecent_gap_event, NULL);
    if (rc != 0) {
        MODLOG_DFLT(ERROR, "Error initiating GAP discovery procedure; rc=%d\n",
                    rc);
    }
}

void blecent_host_task(void *param)
{
    ESP_LOGI(TAG, "BLE Host Task Started");
    /* This function will return only when nimble_port_stop() is executed */
    nimble_port_run();

    nimble_port_freertos_deinit();
}

static void
blecent_on_reset(int reason)
{
    MODLOG_DFLT(ERROR, "Resetting state; reason=%d\n", reason);
}

static void
blecent_on_sync(void)
{
    int rc;

    /* Make sure we have proper identity address set (public preferred) */
    rc = ble_hs_util_ensure_addr(0);
    assert(rc == 0);

    /* Begin scanning for a peripheral to connect to. */
    blecent_scan();
}

void
app_main(void)
{
    int rc;
    /* Initialize NVS — it is used to store PHY calibration data */
    esp_err_t ret = nvs_flash_init();
    if  (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    ret = nimble_port_init();
    if (ret != ESP_OK) {
        ESP_LOGE(TAG, "Failed to init nimble %d ", ret);
        return;
    }

        /* Configure the host. */
    ble_hs_cfg.reset_cb = blecent_on_reset;
    ble_hs_cfg.sync_cb = blecent_on_sync;
    ble_hs_cfg.store_status_cb = ble_store_util_status_rr;

    nimble_port_freertos_init(blecent_host_task);

}
I ran it for 20 minutes on bare S3 WROOM dev module.
3.1% packet loss. Once during the 20 minutes it lost all three.

Then I ran the same program on the target hardware which is inside a plastic case and uses a MINI module.
3.3% packet loss. Once during the 20 minutes it lost all three.

So maybe the plastic case is causing a little extra loss but nothing significant.

jonsmirl
Posts: 19
Joined: Tue Dec 08, 2015 10:59 pm

Re: Controlling Nimble BLE Advertising Scan Channels on S3

Postby jonsmirl » Fri Jan 12, 2024 9:36 pm

Next I started with the esp-matter/example/light code and added this file:

Code: Select all

#include <esp_err.h>
#include <esp_log.h>
#include <host/ble_gap.h>

static const char *TAG = "ble_advert";

static void
print_uuid(const ble_uuid_t *uuid)
{
    char buf[BLE_UUID_STR_LEN];

    printf("%s", ble_uuid_to_str(uuid, buf));
}

static void
print_bytes(const uint8_t *bytes, int len)
{
    int i;

    for (i = 0; i < len; i++)
    {
        printf("%s0x%02x", i != 0 ? ":" : "", bytes[i]);
    }
}

static char *
addr_str(const void *addr)
{
    static char buf[6 * 2 + 5 + 1];
    const uint8_t *u8p;

    u8p = (uint8_t *)addr;
    sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
            u8p[5], u8p[4], u8p[3], u8p[2], u8p[1], u8p[0]);

    return buf;
}

static void
print_adv_fields(const struct ble_hs_adv_fields *fields)
{
    char s[BLE_HS_ADV_MAX_SZ];
    const uint8_t *u8p;
    int i;

    printf("BLE Advert\n");

    if (fields->flags != 0)
    {
        printf("    flags=0x%02x\n", fields->flags);
    }

    if (fields->uuids16 != NULL)
    {
        printf("    uuids16(%scomplete)=",
               fields->uuids16_is_complete ? "" : "in");
        for (i = 0; i < fields->num_uuids16; i++)
        {
            print_uuid(&fields->uuids16[i].u);
            printf(" ");
        }
        printf("\n");
    }

    if (fields->uuids32 != NULL)
    {
        printf("    uuids32(%scomplete)=",
               fields->uuids32_is_complete ? "" : "in");
        for (i = 0; i < fields->num_uuids32; i++)
        {
            print_uuid(&fields->uuids32[i].u);
            printf(" ");
        }
        printf("\n");
    }

    if (fields->uuids128 != NULL)
    {
        printf("    uuids128(%scomplete)=",
               fields->uuids128_is_complete ? "" : "in");
        for (i = 0; i < fields->num_uuids128; i++)
        {
            print_uuid(&fields->uuids128[i].u);
            printf(" ");
        }
        printf("\n");
    }

    if (fields->name != NULL)
    {
        assert(fields->name_len < sizeof s - 1);
        memcpy(s, fields->name, fields->name_len);
        s[fields->name_len] = '\0';
        printf("    name(%scomplete)=%s\n",
               fields->name_is_complete ? "" : "in", s);
    }

    if (fields->tx_pwr_lvl_is_present)
    {
        printf("    tx_pwr_lvl=%d\n", fields->tx_pwr_lvl);
    }

    if (fields->slave_itvl_range != NULL)
    {
        printf("    slave_itvl_range=");
        print_bytes(fields->slave_itvl_range, BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN);
        printf("\n");
    }

    if (fields->svc_data_uuid16 != NULL)
    {
        printf("    svc_data_uuid16=");
        print_bytes(fields->svc_data_uuid16, fields->svc_data_uuid16_len);
        printf("\n");
    }

    if (fields->public_tgt_addr != NULL)
    {
        printf("    public_tgt_addr=");
        u8p = fields->public_tgt_addr;
        for (i = 0; i < fields->num_public_tgt_addrs; i++)
        {
            printf("public_tgt_addr=%s ", addr_str(u8p));
            u8p += BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN;
        }
        printf("\n");
    }

    if (fields->appearance_is_present)
    {
        printf("    appearance=0x%04x\n", fields->appearance);
    }

    if (fields->adv_itvl_is_present)
    {
        printf("    adv_itvl=0x%04x\n", fields->adv_itvl);
    }

    if (fields->svc_data_uuid32 != NULL)
    {
        printf("    svc_data_uuid32=");
        print_bytes(fields->svc_data_uuid32, fields->svc_data_uuid32_len);
        printf("\n");
    }

    if (fields->svc_data_uuid128 != NULL)
    {
        printf("    svc_data_uuid128=");
        print_bytes(fields->svc_data_uuid128, fields->svc_data_uuid128_len);
        printf("\n");
    }

    if (fields->uri != NULL)
    {
        printf("    uri=");
        print_bytes(fields->uri, fields->uri_len);
        printf("\n");
    }

    if (fields->mfg_data != NULL)
    {
        printf("    mfg_data=");
        print_bytes(fields->mfg_data, fields->mfg_data_len);
        printf("\n");
    }
}

void ReportDevice(const struct ble_hs_adv_fields *fields, const ble_addr_t *addr, uint8_t rssi)
{
    if (fields->mfg_data != NULL)
    {
        if ((fields->mfg_data[0] == 0x4c) && (fields->mfg_data[1] == 0xd))
        {

            int i = 2;
            uint16_t temp, humid, battery, count;
            temp = humid = battery = count = 0;
            while (i < fields->mfg_data_len)
            {
                switch (fields->mfg_data[i])
                {
                case 2:
                    temp = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                case 5:
                    humid = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                case 0xfe:
                    count = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                default:
                case 0xff:
                    battery = *(uint16_t *)&fields->mfg_data[i + 1];
                    break;
                }
                i += 3;
            }
            ESP_LOGI(TAG, "BLE %s Count %u RSSI %u Temp %u Humid %u Battery %u", addr_str((void *)addr), count, rssi, temp, humid, battery);
        }
    }
}

void RemoveDevice()
{
    // TODO
}

int OnBleCentralEvent(struct ble_gap_event *event, void *arg)
{
    switch (event->type)
    {
    case BLE_GAP_EVENT_DISC_COMPLETE:
    {
        return 0;
    }

    case BLE_GAP_EVENT_DISC:
    {

        /* Try to connect to the advertiser if it looks interesting. */
        struct ble_hs_adv_fields fields;
        ble_hs_adv_parse_fields(&fields, event->disc.data, event->disc.length_data);
        ReportDevice(&fields, &event->disc.addr, event->disc.rssi);
        return 0;
    }
    }

    return 0;
}

typedef enum {
SCAN_ALL_CHANNLE,
ONLY_SCAN_CHANNEL_37,
ONLY_SCAN_CHANNEL_38,
ONLY_SCAN_CHANNEL_39,
SCAN_MODE_TYPE_ERROR,
} scan_mode_config_t;

extern "C" uint8_t esp_ble_scan_channel_setting(scan_mode_config_t scan_mode);

esp_err_t StartScan()
{
    uint8_t ownAddrType;
    struct ble_gap_disc_params discParams;
    int rc;

    /* Figure out address to use while advertising. */
    rc = ble_hs_id_infer_auto(0, &ownAddrType);
    if (rc != 0)
    {
        // ChipLogError(DeviceLayer, "ble_hs_id_infer_auto failed: %d", rc);
        return ESP_ERR_INVALID_STATE;
    }

    /* Set up discovery parameters. */
    memset(&discParams, 0, sizeof(discParams));

    /* Tell the controller to filter the duplicates. */
    discParams.filter_duplicates = 0;
    /* Perform passive scanning. */
    discParams.passive = 1;
    /* Use defaults for the rest of the parameters. */
    discParams.itvl = 160;
    discParams.window = 160;
    discParams.filter_policy = 0;
    discParams.limited = 0;

    esp_ble_scan_channel_setting(ONLY_SCAN_CHANNEL_39);

    /* Start the discovery process. */
    rc = ble_gap_disc(ownAddrType, BLE_HS_FOREVER, &discParams, OnBleCentralEvent, NULL);
    if (rc != 0)
    {
        ESP_LOGE(TAG, "ble_gap_disc failed: %d", rc);
        return ESP_ERR_INVALID_STATE;
    }
    return ESP_OK;
}

esp_err_t StopScan()
{
    int rc = ble_gap_disc_cancel();
    if (rc != 0)
    {
        //(DeviceLayer, "ble_gap_disc_cancel failed: %d", rc);
        return ESP_ERR_INVALID_STATE;
    }
    // mDelegate->OnScanComplete();
    return ESP_OK;
}
Starting it from app_main.cpp with this:

Code: Select all

    case chip::DeviceLayer::DeviceEventType::kServerReady:
        ESP_LOGI(TAG, "Server ready");
        StartScan();
        break;
Used menuconfig to tell esp-matter to leave ble running.
I commissioned it so that wifi would start

Code: Select all

I (574396) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6440 RSSI 196 Temp 2129 Humid 37 Battery 3371
I (574506) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6440 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (574616) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6440 RSSI 199 Temp 2129 Humid 37 Battery 3371
I (575516) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6441 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (575626) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6441 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (576436) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6442 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (576546) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6442 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (576646) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6442 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (577456) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6443 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (577566) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6443 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (577666) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6443 RSSI 200 Temp 2129 Humid 37 Battery 3371
I (583686) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6449 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (595826) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6461 RSSI 195 Temp 2129 Humid 37 Battery 3371
I (595936) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6461 RSSI 198 Temp 2129 Humid 37 Battery 3371
I (597976) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6463 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (598886) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6464 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (598996) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6464 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (599096) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6464 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (599906) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6465 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (600016) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6465 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (600116) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6465 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (600926) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6466 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (601036) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6466 RSSI 199 Temp 2130 Humid 37 Battery 3371
I (601146) ble_advert: BLE 34:f1:ae:d4:10:00 Count 6466 RSSI 199 Temp 2130 Humid 37 Battery 3371
Now look at the difference, between 6461 and 6463 it dropped ten packets in a row, and between 6449 and 6461 it dropped over 30 in a row. It is dropping about 20% of all packets. Note that Matter was not actively sending packets during this period because Matter prints when it sends. MDNS doesn't print, so it could be active.

This is 100% espressif code except for the file above and it is on a S3 WROOM dev board.

Are Matter and MDNS coordinating on wifi coexistence?

Who is online

Users browsing this forum: Baidu [Spider], markkuk and 313 guests