mirror of
https://github.com/bluekitchen/btstack.git
synced 2025-03-01 19:13:44 +00:00
mesh: add all missing foundation operations defines, handle foundation model publication get/set messages
This commit is contained in:
parent
473970ab1a
commit
619f4f6a3a
395
test/mesh/mesh.c
395
test/mesh/mesh.c
@ -138,6 +138,7 @@ static void mesh_load_app_keys(void){
|
||||
|
||||
void mesh_store_app_key(uint16_t appkey_index, uint8_t aid, const uint8_t * application_key){
|
||||
printf("Store AppKey: AppKey Index 0x%06x, AID %02x: ", appkey_index, aid);
|
||||
printf_hexdump(application_key, 16);
|
||||
uint8_t data[2+1+16];
|
||||
little_endian_store_16(data, 0, appkey_index);
|
||||
data[2] = aid;
|
||||
@ -583,10 +584,20 @@ static void stdin_process(char cmd){
|
||||
|
||||
// Foundation Model Operations
|
||||
#define MESH_FOUNDATION_OPERATION_APPKEY_ADD 0x00
|
||||
#define MESH_FOUNDATION_OPERATION_APP_KEY_UPDATE 0x01
|
||||
#define MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_STATUS 0x02
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET 0x03
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_CURRENT_STATUS 0x04
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_STATUS 0x05
|
||||
#define MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS 0x06
|
||||
#define MESH_FOUNDATION_OPERATION_APPKEY_DEL 0x8000
|
||||
#define MESH_FOUNDATION_OPERATION_APPKEY_GET 0x8001
|
||||
#define MESH_FOUNDATION_OPERATION_APPKEY_LIST 0x8002
|
||||
#define MESH_FOUNDATION_OPERATION_APPKEY_STATUS 0x8003
|
||||
|
||||
#define MESH_FOUNDATION_OPERATION_ATTENTION_GET 0x8004
|
||||
#define MESH_FOUNDATION_OPERATION_ATTENTION_SET 0x8005
|
||||
#define MESH_FOUNDATION_OPERATION_ATTENTION_SET_UNACKNOWLEDGED 0x8006
|
||||
#define MESH_FOUNDATION_OPERATION_ATTENTION_STATUS 0x8007
|
||||
#define MESH_FOUNDATION_OPERATION_COMPOSITION_DATA_GET 0x8008
|
||||
#define MESH_FOUNDATION_OPERATION_BEACON_GET 0x8009
|
||||
#define MESH_FOUNDATION_OPERATION_BEACON_SET 0x800a
|
||||
@ -594,11 +605,15 @@ static void stdin_process(char cmd){
|
||||
#define MESH_FOUNDATION_OPERATION_DEFAULT_TTL_GET 0x800c
|
||||
#define MESH_FOUNDATION_OPERATION_DEFAULT_TTL_SET 0x800d
|
||||
#define MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS 0x800e
|
||||
|
||||
#define MESH_FOUNDATION_OPERATION_FRIEND_GET 0x800f
|
||||
#define MESH_FOUNDATION_OPERATION_FRIEND_SET 0x8010
|
||||
#define MESH_FOUNDATION_OPERATION_FRIEND_STATUS 0x8011
|
||||
#define MESH_FOUNDATION_OPERATION_GATT_PROXY_GET 0x8012
|
||||
#define MESH_FOUNDATION_OPERATION_GATT_PROXY_SET 0x8013
|
||||
#define MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS 0x8014
|
||||
|
||||
#define MESH_FOUNDATION_OPERATION_KEY_REFRESH_PAHSE_GET 0x8015
|
||||
#define MESH_FOUNDATION_OPERATION_KEY_REFRESH_PAHSE_SET 0x8016
|
||||
#define MESH_FOUNDATION_OPERATION_KEY_REFRESH_PAHSE_STATUS 0x8017
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET 0x8018
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS 0x8019
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET 0x801a
|
||||
@ -616,7 +631,21 @@ static void stdin_process(char cmd){
|
||||
#define MESH_FOUNDATION_OPERATION_RELAY_GET 0x8026
|
||||
#define MESH_FOUNDATION_OPERATION_RELAY_SET 0x8027
|
||||
#define MESH_FOUNDATION_OPERATION_RELAY_STATUS 0x8028
|
||||
|
||||
#define MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_GET 0x8029
|
||||
#define MESH_FOUNDATION_OPERATION_SIG_MODEL_SUBSCRIPTION_LIST 0x802a
|
||||
#define MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_GET 0x802b
|
||||
#define MESH_FOUNDATION_OPERATION_VENDOR_MODEL_SUBSCRIPTION_LIST 0x802c
|
||||
#define MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_GET 0x802d
|
||||
#define MESH_FOUNDATION_OPERATION_LOW_POWER_NODE_POLL_TIMEOUT_STATUS 0x802e
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_CLEAR 0x802f
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_CLEAR_UNACKNOWLEDGED 0x8030
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_GET 0x8031
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_TEST 0x8032
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_FAULT_TEST_UNACKNOWLEDGED 0x8033
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_GET 0x8034
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET 0x8035
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_SET_UNACKNOWLEDGED 0x8036
|
||||
#define MESH_FOUNDATION_OPERATION_HEALTH_PERIOD_STATUS 0x8037
|
||||
#define MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_GET 0x8038
|
||||
#define MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET 0x8039
|
||||
#define MESH_FOUNDATION_OPERATION_HEARTBEAT_SUBSCRIPTION_GET 0x803a
|
||||
@ -625,9 +654,85 @@ static void stdin_process(char cmd){
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_APP_BIND 0x803d
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS 0x803e
|
||||
#define MESH_FOUNDATION_OPERATION_MODEL_APP_UNBIND 0x803f
|
||||
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_ADD 0x8040
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_DEL 0x8041
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_GET 0x8042
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_LIST 0x8043
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_STATUS 0x8044
|
||||
#define MESH_FOUNDATION_OPERATION_NETKEY_UPDATE 0x8045
|
||||
#define MESH_FOUNDATION_OPERATION_NODE_IDENTITY_GET 0x8046
|
||||
#define MESH_FOUNDATION_OPERATION_NODE_IDENTITY_SET 0x8047
|
||||
#define MESH_FOUNDATION_OPERATION_NODE_IDENTITY_STATUS 0x8048
|
||||
#define MESH_FOUNDATION_OPERATION_NODE_RESET 0x8049
|
||||
#define MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS 0x804a
|
||||
#define MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_GET 0x804b
|
||||
#define MESH_FOUNDATION_OPERATION_SIG_MODEL_APP_LIST 0x804c
|
||||
#define MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_GET 0x804d
|
||||
#define MESH_FOUNDATION_OPERATION_VENDOR_MODEL_APP_LIST 0x804e
|
||||
|
||||
// Foundation Models Status Codes
|
||||
#define MEHSH_FOUNDATION_STATUS_SUCCESS 0x00
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_ADDRESS 0x01
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_MODEL 0x02
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_APPKEY_INDEX 0x03
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX 0x04
|
||||
#define MEHSH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES 0x05
|
||||
#define MEHSH_FOUNDATION_STATUS_KEY_INDEX_ALREADY_STORED 0x06
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_PUBLISH_PARAMETER 0x07
|
||||
#define MEHSH_FOUNDATION_STATUS_NOT_A_SUBSCRIPTION_MODEL 0x08
|
||||
#define MEHSH_FOUNDATION_STATUS_STORAGE_FAILURE 0x09
|
||||
#define MEHSH_FOUNDATION_STATUS_FEATURE_NOT_SUPPORTED 0x0a
|
||||
#define MEHSH_FOUNDATION_STATUS_CANNOT_UPDATE 0x0b
|
||||
#define MEHSH_FOUNDATION_STATUS_CANNOT_REMOVE 0x0c
|
||||
#define MEHSH_FOUNDATION_STATUS_CANNOT_BIND 0x0d
|
||||
#define MEHSH_FOUNDATION_STATUS_TEMPORARILY_UNABLE_TO_CHANGE_STATE 0x0e
|
||||
#define MEHSH_FOUNDATION_STATUS_CANNOT_SET 0x0f
|
||||
#define MEHSH_FOUNDATION_STATUS_UNSPECIFIED_ERROR 0x10
|
||||
#define MEHSH_FOUNDATION_STATUS_INVALID_BINDING 0x11
|
||||
|
||||
// Foundatiopn Message
|
||||
|
||||
typedef struct {
|
||||
uint32_t opcode;
|
||||
const char * format;
|
||||
} mesh_access_message_t;
|
||||
|
||||
const mesh_access_message_t mesh_foundation_config_beacon_status = {
|
||||
MESH_FOUNDATION_OPERATION_BEACON_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_default_ttl_status = {
|
||||
MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_gatt_proxy_status = {
|
||||
MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_relay_status = {
|
||||
MESH_FOUNDATION_OPERATION_RELAY_STATUS, "11"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status_sig = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "12221112"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status_vendor = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "12221114"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_subscription_status = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, "1222"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_appkey_status = {
|
||||
MESH_FOUNDATION_OPERATION_APPKEY_STATUS, "13"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, "1222"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_node_reset_status = {
|
||||
MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS, ""
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_heartbeat_publication_status = {
|
||||
MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS, "1211122"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_network_transmit_status = {
|
||||
MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS, "11"
|
||||
};
|
||||
|
||||
// message builder
|
||||
static int mesh_access_setup_opcode(uint8_t * buffer, uint32_t opcode){
|
||||
@ -678,7 +783,7 @@ static int mesh_access_get_opcode(uint8_t * buffer, uint16_t buffer_size, uint32
|
||||
if (buffer[0] == 0x7f) return 0;
|
||||
*opcode = buffer[0];
|
||||
*opcode_size = 1;
|
||||
return 0;
|
||||
return 1;
|
||||
case 2:
|
||||
if (buffer_size < 2) return 0;
|
||||
*opcode = big_endian_read_16(buffer, 0);
|
||||
@ -701,12 +806,6 @@ static int mesh_access_transport_get_opcode(mesh_transport_pdu_t * transport_pdu
|
||||
// access message template
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t opcode;
|
||||
const char * format;
|
||||
} mesh_access_message_t;
|
||||
|
||||
|
||||
static mesh_transport_pdu_t * mesh_access_setup_transport_message(const mesh_access_message_t * template, ...){
|
||||
mesh_transport_pdu_t * transport_pdu = mesh_access_transport_init(template->opcode);
|
||||
if (!transport_pdu) return NULL;
|
||||
@ -730,11 +829,11 @@ static mesh_transport_pdu_t * mesh_access_setup_transport_message(const mesh_acc
|
||||
break;
|
||||
case '3':
|
||||
longword = va_arg(argptr, uint32_t);
|
||||
mesh_access_transport_add_uint16( transport_pdu, longword);
|
||||
mesh_access_transport_add_uint24( transport_pdu, longword);
|
||||
break;
|
||||
case '4':
|
||||
longword = va_arg(argptr, uint32_t);
|
||||
mesh_access_transport_add_uint16( transport_pdu, longword);
|
||||
mesh_access_transport_add_uint32( transport_pdu, longword);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -746,45 +845,6 @@ static mesh_transport_pdu_t * mesh_access_setup_transport_message(const mesh_acc
|
||||
return transport_pdu;
|
||||
}
|
||||
|
||||
// Foundatiopn
|
||||
|
||||
const mesh_access_message_t mesh_foundation_config_beacon_status = {
|
||||
MESH_FOUNDATION_OPERATION_BEACON_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_default_ttl_status = {
|
||||
MESH_FOUNDATION_OPERATION_DEFAULT_TTL_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_gatt_proxy_status = {
|
||||
MESH_FOUNDATION_OPERATION_GATT_PROXY_STATUS, "1"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_relay_status = {
|
||||
MESH_FOUNDATION_OPERATION_RELAY_STATUS, "11"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status_sig = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "12221112"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status_vendor = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_STATUS, "12221114"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_subscription_status = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_STATUS, "1222"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_appkey_status = {
|
||||
MESH_FOUNDATION_OPERATION_APPKEY_STATUS, "13"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_model_app_status = {
|
||||
MESH_FOUNDATION_OPERATION_MODEL_APP_STATUS, "1222"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_node_reset_status = {
|
||||
MESH_FOUNDATION_OPERATION_NODE_RESET_STATUS, ""
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_heartbeat_publication_status = {
|
||||
MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_STATUS, "1211122"
|
||||
};
|
||||
const mesh_access_message_t mesh_foundation_config_network_transmit_status = {
|
||||
MESH_FOUNDATION_OPERATION_NETWORK_TRANSMIT_STATUS, "11"
|
||||
};
|
||||
|
||||
#define MESH_TTL_MAX 0x7f
|
||||
|
||||
static uint8_t mesh_foundation_gatt_proxy = 0;
|
||||
@ -1168,26 +1228,113 @@ static void config_model_app_bind_handler(mesh_model_t *mesh_model, mesh_transpo
|
||||
config_model_app_status(mesh_transport_src(transport_pdu), 0, element_address, app_key_index, model_identifier);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t address;
|
||||
uint16_t appkey_index;
|
||||
uint8_t friendship_credential_flag;
|
||||
uint8_t period;
|
||||
uint8_t ttl;
|
||||
uint8_t retransmit;
|
||||
} mesh_publication_model_t;
|
||||
|
||||
static void config_model_publication_status_sig(mesh_model_t * mesh_model, uint32_t model_id, uint16_t dest, uint8_t status, mesh_publication_model_t * publication_model){
|
||||
// setup message
|
||||
uint16_t app_key_index_and_credential_flag = (publication_model->friendship_credential_flag << 12) | publication_model->appkey_index;
|
||||
mesh_transport_pdu_t * transport_pdu = mesh_access_setup_transport_message(&mesh_foundation_config_model_app_status_sig, status, primary_element_address, publication_model->address, app_key_index_and_credential_flag,
|
||||
publication_model->ttl, publication_model->period, publication_model->retransmit, model_id);
|
||||
if (!transport_pdu) return;
|
||||
|
||||
// send as segmented access pdu
|
||||
uint16_t src = primary_element_address;
|
||||
uint8_t ttl = mesh_foundation_default_ttl_get();
|
||||
uint16_t netkey_index = 0;
|
||||
uint16_t appkey_index = MESH_DEVICE_KEY_INDEX;
|
||||
mesh_upper_transport_setup_segmented_access_pdu_header(transport_pdu, netkey_index, appkey_index, ttl, src, dest, 0);
|
||||
mesh_upper_transport_send_segmented_access_pdu(transport_pdu);
|
||||
}
|
||||
|
||||
static void config_model_publication_status_vendor(mesh_model_t * mesh_model, uint32_t model_id, uint16_t dest, uint8_t status, mesh_publication_model_t * publication_model){
|
||||
// setup message
|
||||
uint16_t app_key_index_and_credential_flag = (publication_model->friendship_credential_flag << 12) | publication_model->appkey_index;
|
||||
mesh_transport_pdu_t * transport_pdu = mesh_access_setup_transport_message(&mesh_foundation_config_model_app_status_vendor, status, primary_element_address, publication_model->address, app_key_index_and_credential_flag,
|
||||
publication_model->ttl, publication_model->period, publication_model->retransmit, model_id);
|
||||
if (!transport_pdu) return;
|
||||
|
||||
// send as segmented access pdu
|
||||
uint16_t src = primary_element_address;
|
||||
uint8_t ttl = mesh_foundation_default_ttl_get();
|
||||
uint16_t netkey_index = 0;
|
||||
uint16_t appkey_index = MESH_DEVICE_KEY_INDEX;
|
||||
mesh_upper_transport_setup_segmented_access_pdu_header(transport_pdu, netkey_index, appkey_index, ttl, src, dest, 0);
|
||||
mesh_upper_transport_send_segmented_access_pdu(transport_pdu);
|
||||
}
|
||||
|
||||
// TODO: link to model
|
||||
static mesh_publication_model_t publication_model;
|
||||
static uint32_t model_id;
|
||||
static uint16_t model_id_len;
|
||||
static uint8_t model_publication_label_uuid[16];
|
||||
static uint16_t model_publication_dest;
|
||||
static btstack_crypto_aes128_cmac_t model_publication_request;
|
||||
|
||||
static void
|
||||
config_model_publication_virtual_address_add_handler(mesh_model_t *mesh_model, mesh_transport_pdu_t *transport_pdu_incoming) {
|
||||
config_model_publication_set_handler(mesh_model_t *mesh_model, mesh_transport_pdu_t *transport_pdu_incoming) {
|
||||
|
||||
// ElementAddress - Address of the element - should be us
|
||||
uint16_t element_address = little_endian_read_16(transport_pdu_incoming->data, 1);
|
||||
if (transport_pdu_incoming->len == 13){
|
||||
// Vendor Model ID
|
||||
model_id_len = 4;
|
||||
model_id = little_endian_read_32(transport_pdu_incoming->data, 10);
|
||||
} else {
|
||||
// SIG Model ID
|
||||
model_id_len = 2;
|
||||
model_id = little_endian_read_16(transport_pdu_incoming->data, 10);
|
||||
}
|
||||
|
||||
// TODO: find model for element_address and model_id
|
||||
|
||||
// TODO: validate params
|
||||
// PublishAddress, 16 bit
|
||||
publication_model.address = little_endian_read_16(transport_pdu_incoming->data, 3);
|
||||
if (publication_model.address == MESH_ADDRESS_UNSASSIGNED){
|
||||
memset(&publication_model, 0, sizeof(publication_model));
|
||||
} else {
|
||||
// AppKeyIndex (12), CredentialFlag (1), RFU (3)
|
||||
uint16_t temp = little_endian_read_16(transport_pdu_incoming->data, 5);
|
||||
publication_model.appkey_index = temp & 0x0fff;
|
||||
publication_model.friendship_credential_flag = (temp >> 12) & 1;
|
||||
publication_model.ttl = transport_pdu_incoming->data[7];
|
||||
publication_model.period = transport_pdu_incoming->data[8];
|
||||
publication_model.retransmit = transport_pdu_incoming->data[9];
|
||||
}
|
||||
|
||||
// send status
|
||||
uint8_t status = 0;
|
||||
if (model_id_len == 2){
|
||||
config_model_publication_status_sig(mesh_model, model_id, mesh_transport_src(transport_pdu_incoming), status, &publication_model);
|
||||
} else {
|
||||
config_model_publication_status_vendor(mesh_model, model_id, mesh_transport_src(transport_pdu_incoming), status, &publication_model);
|
||||
}
|
||||
}
|
||||
static void config_model_publication_virtual_address_set_hash(void *arg){
|
||||
mesh_model_t *mesh_model = (mesh_model_t*) arg;
|
||||
uint8_t status = 0;
|
||||
printf("Virtual Address Hash: %04x\n", publication_model.address);
|
||||
if (model_id_len == 2){
|
||||
config_model_publication_status_sig(mesh_model, model_id, model_publication_dest, status, &publication_model);
|
||||
} else {
|
||||
config_model_publication_status_vendor(mesh_model, model_id, model_publication_dest, status, &publication_model);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
config_model_publication_virtual_address_set_handler(mesh_model_t *mesh_model,
|
||||
mesh_transport_pdu_t *transport_pdu_incoming) {
|
||||
|
||||
// ElementAddress - Address of the element - should be us
|
||||
uint16_t element_address = little_endian_read_16(transport_pdu_incoming->data, 2);
|
||||
// PublishAddress, 128 bit
|
||||
// uint8_t * label_uuid = &transport_pdu->data[4];
|
||||
// AppKeyIndex (12), CredentialFlag (1), RFU (3)
|
||||
uint16_t temp = little_endian_read_16(transport_pdu_incoming->data, 20);
|
||||
uint16_t app_key_index = temp & 0x0fff;
|
||||
uint8_t credential_flag = (temp >> 12) & 1;
|
||||
// PublishTTL
|
||||
uint8_t publish_ttl = transport_pdu_incoming->data[22];
|
||||
// PublishPeriod
|
||||
uint8_t publish_period = transport_pdu_incoming->data[23];
|
||||
// PublishRetransmitCount(3), PublishRetransmitCount(5)
|
||||
uint8_t publish_transmit_count = transport_pdu_incoming->data[24] & 0x07;
|
||||
uint8_t publish_retransmit_iterval_steps = transport_pdu_incoming->data[24] >> 3;
|
||||
uint8_t model_id_len;
|
||||
uint32_t model_id;
|
||||
|
||||
if (transport_pdu_incoming->len == 29){
|
||||
// Vendor Model ID
|
||||
model_id_len = 4;
|
||||
@ -1198,33 +1345,58 @@ config_model_publication_virtual_address_add_handler(mesh_model_t *mesh_model, m
|
||||
model_id = little_endian_read_16(transport_pdu_incoming->data, 25);
|
||||
}
|
||||
|
||||
// TODO: calculate publish address from label uuid
|
||||
uint16_t publish_address = 0x1234;
|
||||
uint8_t status = 0;
|
||||
// TODO: find model for element_address and model_id
|
||||
|
||||
// setup message
|
||||
const mesh_access_message_t * message;
|
||||
if (model_id_len == 2){
|
||||
message = &mesh_foundation_config_model_app_status_sig;
|
||||
} else {
|
||||
message = &mesh_foundation_config_model_app_status_vendor;
|
||||
}
|
||||
uint16_t app_key_index_and_credential_flag = (credential_flag << 12) | app_key_index;
|
||||
uint8_t publish_retransmit = (publish_retransmit_iterval_steps << 3) | publish_transmit_count;
|
||||
mesh_transport_pdu_t * transport_pdu = mesh_access_setup_transport_message(message, status, element_address, publish_address, app_key_index_and_credential_flag,
|
||||
publish_ttl, publish_period, publish_retransmit, model_id);
|
||||
if (!transport_pdu) return;
|
||||
// TODO: validate params
|
||||
|
||||
// send as segmented access pdu
|
||||
uint16_t src = primary_element_address;
|
||||
uint16_t dest = mesh_transport_src(transport_pdu);
|
||||
uint8_t ttl = mesh_foundation_default_ttl_get();
|
||||
uint16_t netkey_index = 0;
|
||||
uint16_t appkey_index = MESH_DEVICE_KEY_INDEX;
|
||||
mesh_upper_transport_setup_segmented_access_pdu_header(transport_pdu, netkey_index, appkey_index, ttl, src, dest, 0);
|
||||
mesh_upper_transport_send_segmented_access_pdu(transport_pdu);
|
||||
// PublishAddress, 128 bit - offset 4
|
||||
|
||||
// AppKeyIndex (12), CredentialFlag (1), RFU (3)
|
||||
uint16_t temp = little_endian_read_16(transport_pdu_incoming->data, 20);
|
||||
publication_model.appkey_index = temp & 0x0fff;
|
||||
publication_model.friendship_credential_flag = (temp >> 12) & 1;
|
||||
publication_model.ttl = transport_pdu_incoming->data[22];
|
||||
publication_model.period = transport_pdu_incoming->data[23];
|
||||
publication_model.retransmit = transport_pdu_incoming->data[24];
|
||||
|
||||
// TODO: don't use globals
|
||||
// reverse_128(&transport_pdu_incoming->data[4], model_publication_label_uuid);
|
||||
memcpy(model_publication_label_uuid, &transport_pdu_incoming->data[4], 16);
|
||||
|
||||
model_publication_dest = mesh_transport_src(transport_pdu_incoming);
|
||||
mesh_virtual_address(&model_publication_request, model_publication_label_uuid, &publication_model.address, &config_model_publication_virtual_address_set_hash, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
config_model_publication_get_handler(mesh_model_t *mesh_model, mesh_transport_pdu_t *transport_pdu_incoming) {
|
||||
|
||||
// ElementAddress - Address of the element - should be us
|
||||
uint16_t element_address = little_endian_read_16(transport_pdu_incoming->data, 2);
|
||||
|
||||
// Model ID
|
||||
uint8_t model_id_len;
|
||||
uint32_t model_id;
|
||||
if (transport_pdu_incoming->len == 8){
|
||||
// Vendor Model ID
|
||||
model_id_len = 4;
|
||||
model_id = little_endian_read_32(transport_pdu_incoming->data, 4);
|
||||
} else {
|
||||
// SIG Model ID
|
||||
model_id_len = 2;
|
||||
model_id = little_endian_read_16(transport_pdu_incoming->data, 4);
|
||||
}
|
||||
|
||||
// TODO: find model for element_address and model_id
|
||||
|
||||
uint8_t status = 0;
|
||||
if (model_id_len == 2){
|
||||
config_model_publication_status_sig(mesh_model, model_id, mesh_transport_src(transport_pdu_incoming), status, &publication_model);
|
||||
} else {
|
||||
config_model_publication_status_vendor(mesh_model, model_id, mesh_transport_src(transport_pdu_incoming), status, &publication_model);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Heartbeat Publication
|
||||
#define MESH_HEARTBEAT_FEATURES_SUPPORTED_MASK 0x000f
|
||||
|
||||
@ -1377,10 +1549,12 @@ static mesh_operation_t mesh_configuration_server_model_operations[] = {
|
||||
{ MESH_FOUNDATION_OPERATION_RELAY_GET, 0, config_relay_get_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_RELAY_SET, 1, config_relay_set_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_SUBSCRIPTION_VIRTUAL_ADDRESS_ADD, 20, config_model_subscription_virtual_address_add_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, 24, config_model_publication_virtual_address_add_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_SET, 11, config_model_publication_set_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_VIRTUAL_ADDRESS_SET, 25, config_model_publication_virtual_address_set_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_PUBLICATION_GET, 4, config_model_publication_get_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_MODEL_APP_BIND, 6, config_model_app_bind_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_GET, 0, config_heartbeat_publication_get_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET, 5, config_heartbeat_publication_set_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_HEARTBEAT_PUBLICATION_SET, 9, config_heartbeat_publication_set_handler},
|
||||
{ MESH_FOUNDATION_OPERATION_NODE_RESET, 0, config_node_reset_handler},
|
||||
{ 0, 0, NULL}
|
||||
};
|
||||
@ -1389,6 +1563,7 @@ static void mesh_segmented_message_handler(mesh_transport_pdu_t *transport_pdu){
|
||||
// get opcode and size
|
||||
uint32_t opcode = 0;
|
||||
uint16_t opcode_size = 0;
|
||||
|
||||
int ok = mesh_access_transport_get_opcode(transport_pdu, &opcode, &opcode_size);
|
||||
if (!ok) return;
|
||||
|
||||
@ -1400,9 +1575,33 @@ static void mesh_segmented_message_handler(mesh_transport_pdu_t *transport_pdu){
|
||||
mesh_operation_t * operation;
|
||||
for (operation = mesh_configuration_server_model_operations; operation->handler != NULL ; operation++){
|
||||
if (operation->opcode != opcode) continue;
|
||||
if ((opcode_size + operation->minimum_length) > transport_pdu->len) break;
|
||||
if ((opcode_size + operation->minimum_length) > transport_pdu->len) continue;
|
||||
operation->handler(model, transport_pdu);
|
||||
return;
|
||||
}
|
||||
printf("Message not handled\n");
|
||||
}
|
||||
|
||||
static btstack_crypto_aes128_cmac_t salt_request;
|
||||
static uint8_t label_uuid[16];
|
||||
static uint8_t salt_hash[16];
|
||||
static uint16_t virtual_address_hash;
|
||||
|
||||
static void salt_complete(void * arg){
|
||||
int i;
|
||||
printf("uint8_t salt[16] = { ");
|
||||
for (i=0;i<16;i++){
|
||||
printf("0x%02x, ", salt_hash[i]);
|
||||
}
|
||||
printf("};\n");
|
||||
}
|
||||
|
||||
static uint8_t mesh_salt_vtad[] = { 0xce, 0xf7, 0xfa, 0x9d, 0xc4, 0x7b, 0xaf, 0x5d, 0xaa, 0xee, 0xd1, 0x94, 0x06, 0x09, 0x4f, 0x37, };
|
||||
|
||||
static void virtual_address_complete(void * arg){
|
||||
printf("Label UUID: ");
|
||||
printf_hexdump(label_uuid, 16);
|
||||
printf("Virtual Address %04x\n", virtual_address_hash);
|
||||
}
|
||||
|
||||
int btstack_main(void);
|
||||
@ -1439,10 +1638,14 @@ int btstack_main(void)
|
||||
mesh_upper_transport_register_segemented_message_handler(&mesh_segmented_message_handler);
|
||||
|
||||
// PTS Virtual Address Label UUID - without Config Model, PTS uses our device uuid
|
||||
uint8_t label_uuid[16];
|
||||
btstack_parse_hex("001BDC0810210B0E0A0C000B0E0A0C00", 16, label_uuid);
|
||||
pts_proxy_dst = mesh_virtual_address_register(label_uuid, 0x9779);
|
||||
|
||||
// calc s1('vtad')
|
||||
// btstack_crypto_aes128_cmac_zero(&salt_request, 4, (const uint8_t *) "vtad", salt_hash, salt_complete, NULL);
|
||||
|
||||
// calc virtual address hash
|
||||
// mesh_virtual_address(&salt_request, label_uuid, &virtual_address_hash, virtual_address_complete, NULL);
|
||||
|
||||
//
|
||||
btstack_parse_hex(pts_device_uuid_string, 16, pts_device_uuid);
|
||||
|
Loading…
x
Reference in New Issue
Block a user