This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

ODD and EVEN addresses in Enocean switch example.

Hi,

I am trying to modify the enocean switch example to send the commands from the switch to different devices connected in the mesh. Example shows that the a0, a1 control the even addresses and b0, b1 control the even addresses. 

I am unable to trace where the routing of the data packets was hard-coded for odd and even addresses so that I can modify according to my requirement.

Some insight on that would be of great help.

Thank you.

Parents
  • Hi,

    Please take a look at the app_enocean_cb() function in main.c of the enocean switch example:

    /* This example translates the messages from the PTM215B switches to on/off client model messages.
    The mapping of the switches and corresponding client model messages is as follows:
    
    Pressing Switch 1 will turn ON LED 1 on the servers with ODD addresses.
    Pressing Switch 2 will turn OFF LED 1 on the servers with ODD addresses.
    Pressing Switch 3 will turn ON LED 1 on the servers with EVEN addresses.
    Pressing Switch 4 will turn OFF LED 1 on the servers with EVEN addresses.
    */
    static void app_enocean_cb(enocean_evt_t * p_evt)
    {
        if  (p_evt->type == ENOCEAN_EVT_DATA_RECEIVED)
        {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sw data A0: %d A1: %d B0: %d B1: %d Action: %d\n",
                  p_evt->params.data.status.a0,p_evt->params.data.status.a1,p_evt->params.data.status.b0,
                  p_evt->params.data.status.b1,p_evt->params.data.status.action);
    
            app_switch_debounce(&p_evt->params.data.status, enocean_device_index_get(p_evt));
        }
        else if (p_evt->type == ENOCEAN_EVT_SECURITY_MATERIAL_RECEIVED)
        {
            if (m_enocean_dev_cnt < MAX_ENOCEAN_DEVICES_SUPPORTED)
            {
                m_app_secmat_flash[m_enocean_dev_cnt].seq = p_evt->params.secmat.seq;
                memcpy(&m_app_secmat_flash[m_enocean_dev_cnt].ble_gap_addr[0],
                       p_evt->p_ble_gap_addr, BLE_GAP_ADDR_LEN);
                memcpy(&m_app_secmat_flash[m_enocean_dev_cnt].key[0],
                       p_evt->params.secmat.p_key, PTM215B_COMM_PACKET_KEY_SIZE);
    
                app_data_store_try();
    
                m_app_secmat[m_enocean_dev_cnt].p_seq =  &m_app_secmat_flash[m_enocean_dev_cnt].seq;
                m_app_secmat[m_enocean_dev_cnt].p_ble_gap_addr = &m_app_secmat_flash[m_enocean_dev_cnt].ble_gap_addr[0];
                m_app_secmat[m_enocean_dev_cnt].p_key = &m_app_secmat_flash[m_enocean_dev_cnt].key[0];
                enocean_secmat_add(&m_app_secmat[m_enocean_dev_cnt]);
    
                m_enocean_dev_cnt++;
    
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_PROV);
            }
            else
            {
                __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Cannot add new device. Max number of supported devices: %d\n", MAX_ENOCEAN_DEVICES_SUPPORTED);
            }
        }
    }

    This callback calls the app_switch_debounce function, which uses the first & second generic on/off client models to send a generic_onoff_client_set call to the even or odd group address:

    static void app_switch_debounce(enocean_switch_status_t * p_status, uint8_t index)
    {
        uint32_t timestamp = timer_now();
        uint32_t status = NRF_ERROR_INTERNAL;
        generic_onoff_set_params_t set_params;
        model_transition_t transition_params;
        static uint8_t tid = 0;
    
        set_params.tid = tid++;
        transition_params.delay_ms = APP_CONFIG_ONOFF_DELAY_MS;
        transition_params.transition_time_ms = APP_CONFIG_ONOFF_TRANSITION_TIME_MS;
    
        if (p_status->action == PRESS_ACTION)
        {
            /* Change state on the unicast server address using 1st on/off client */
            if (p_status->a0 && timer_diff(timestamp, m_switch_state[index].a0_ts) > SWITCH_DEBOUNCE_INTERVAL_US)
            {
                m_switch_state[index].a0_ts = timestamp;
                set_params.on_off = APP_STATE_ON;
                hal_led_pin_set(BSP_LED_0, set_params.on_off);
                status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
            }
            else if (p_status->a1 && timer_diff(timestamp, m_switch_state[index].a1_ts) > SWITCH_DEBOUNCE_INTERVAL_US)
            {
                m_switch_state[index].a1_ts = timestamp;
                set_params.on_off = APP_STATE_OFF;
                hal_led_pin_set(BSP_LED_0, set_params.on_off);
                status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
            }
    
            if (status == NRF_SUCCESS)
            {
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: Client[0]: ONOFF SET %d\n", set_params.on_off);
            }
            status = NRF_ERROR_INTERNAL;
    
            /* Change state on the nodes subscribed to the Odd group address using 2nd on/off client */
            if (p_status->b0 && timer_diff(timestamp, m_switch_state[index].b0_ts) > SWITCH_DEBOUNCE_INTERVAL_US)
            {
                m_switch_state[index].b0_ts = timestamp;
                set_params.on_off = APP_STATE_ON;
                hal_led_pin_set(BSP_LED_1, set_params.on_off);
                status = generic_onoff_client_set_unack(&m_clients[1], &set_params, &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
            }
            else if (p_status->b1 && timer_diff(timestamp, m_switch_state[index].b1_ts) > SWITCH_DEBOUNCE_INTERVAL_US)
            {
                m_switch_state[index].b1_ts = timestamp;
                set_params.on_off = APP_STATE_OFF;
                hal_led_pin_set(BSP_LED_1, set_params.on_off);
                status = generic_onoff_client_set_unack(&m_clients[1], &set_params, &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
            }
    
            if (status == NRF_SUCCESS)
            {
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: Client[1]: ONOFF SET %d\n", set_params.on_off);
            }
        }
    }

    These clients are defined in the line:

    static generic_onoff_client_t m_clients[LIGHT_SWITCH_CLIENTS];

    The client models are initialized in the models_init_cb() function, but it is the provisioner that configures the on/off client instances on the translator switch example, as explained in the documentation:

    "The provisioner configures the On/Off client model instances on the client board to control various servers as follows:

    • The Button A0 turns ON LED 1 on the servers with Odd addresses.
    • The Button A1 turns OFF LED 1 on the servers with Odd addresses.
    • The Button B0 turns ON LED 1 on the servers with Even addresses.
    • The Button B1 turns OFF LED 1 on the servers with Even addresses."

    Have you taken a look at the node_setup.c file in the light switch provisioner example? I would recommend taking a look at these two cases:

            case NODE_SETUP_CONFIG_PUBLICATION_ONOFF_SERVER:
            {
                config_publication_state_t pubstate = {0};
                pubstate.element_address = m_current_node_addr;
                pubstate.publish_address.type = NRF_MESH_ADDRESS_TYPE_UNICAST;
                if ((m_current_node_addr % 2) == 0)
                {
                    pubstate.publish_address.value = UNPROV_START_ADDRESS + ELEMENT_IDX_ONOFF_CLIENT2;
                }
                else
                {
                    pubstate.publish_address.value = UNPROV_START_ADDRESS + ELEMENT_IDX_ONOFF_CLIENT1;
                }
                pubstate.appkey_index = m_appkey_idx;
                pubstate.frendship_credential_flag = false;
                pubstate.publish_ttl = (SERVER_NODE_COUNT > NRF_MESH_TTL_MAX ? NRF_MESH_TTL_MAX : SERVER_NODE_COUNT);
                pubstate.publish_period.step_num = 0;
                pubstate.publish_period.step_res = ACCESS_PUBLISH_RESOLUTION_100MS;
                pubstate.retransmit_count = 1;
                pubstate.retransmit_interval = 0;
                pubstate.model_id.company_id = m_server_model_id.company_id;
                pubstate.model_id.model_id = m_server_model_id.model_id;
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Set: 0x%04x server pub addr: 0x%04x\n", m_server_model_id.model_id, pubstate.publish_address.value);
                retry_on_fail(config_client_model_publication_set(&pubstate));
    
                static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS};
                expected_status_set(CONFIG_OPCODE_MODEL_PUBLICATION_STATUS, ARRAY_SIZE(exp_status), exp_status);
                break;
            }
    
            /* Configure subscription address for the On/Off server */
            case NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER:
            {
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Adding subscription\n");
                uint16_t element_address = m_current_node_addr;
                nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_INVALID, 0, NULL};
                address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
                if (m_current_node_addr % 0x02)
                {
                    address.value  = GROUP_ADDRESS_ODD;
                }
                else
                {
                    address.value  = GROUP_ADDRESS_EVEN;
                }
                access_model_id_t model_id;
                model_id.company_id = m_server_model_id.company_id;
                model_id.model_id = m_server_model_id.model_id;
                retry_on_fail(config_client_model_subscription_add(element_address, address, model_id));
    
                static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS};
                expected_status_set(CONFIG_OPCODE_MODEL_SUBSCRIPTION_STATUS, ARRAY_SIZE(exp_status), exp_status);
                break;
            }

    Kind Regards,

    Bjørn

Reply Children
No Data
Related