From bdc10744fb338ae197692713a0b48a7ccc36f566 Mon Sep 17 00:00:00 2001 From: JF Date: Sun, 26 Apr 2020 10:25:59 +0200 Subject: Add Nimble in libs directory --- .../apps/blemesh_models_example_1/README.md | 79 +++ .../apps/blemesh_models_example_1/pkg.yml | 34 + .../apps/blemesh_models_example_1/src/main.c | 709 +++++++++++++++++++++ .../apps/blemesh_models_example_1/syscfg.yml | 38 ++ 4 files changed, 860 insertions(+) create mode 100644 src/libs/mynewt-nimble/apps/blemesh_models_example_1/README.md create mode 100644 src/libs/mynewt-nimble/apps/blemesh_models_example_1/pkg.yml create mode 100644 src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c create mode 100644 src/libs/mynewt-nimble/apps/blemesh_models_example_1/syscfg.yml (limited to 'src/libs/mynewt-nimble/apps/blemesh_models_example_1') diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/README.md b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/README.md new file mode 100644 index 00000000..fde49536 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/README.md @@ -0,0 +1,79 @@ +### Bluetooth: Mesh OnOff Model + + +#### Overview + +This is a simple application demonstrating a Bluetooth mesh multi-element node. +Each element has a mesh onoff client and server +model which controls one of the 4 sets of buttons and LEDs . + +Prior to provisioning, an unprovisioned beacon is broadcast that contains +a UUID. Each button controls the state of its +corresponding LED and does not initiate any mesh activity. + +The models for button 1 and LED 1 are in the node's root element. +The 3 remaining button/LED pairs are in elements 1 through 3. +Assuming the provisioner assigns 0x100 to the root element, +the secondary elements will appear at 0x101, 0x102 and 0x103. + +After provisioning, the button clients must +be configured to publish and the LED servers to subscribe. + +If a LED server is provided with a publish address, it will +also publish its status on an onoff state change. + +If a button is pressed only once within a 1 second interval, it sends an +"on" message. If it is pressed more than once, it +sends an "off" message. The buttons are quite noisy and are debounced in +the button_pressed() interrupt handler. An interrupt within 250ms of the +previous is discarded. This might seem a little clumsy, but the alternative of +using one button for "on" and another for "off" would reduce the number +of onoff clients from 4 to 2. + +#### Requirements +************ + +This sample has been tested on the Nordic nRF52840-PDK board, but would +likely also run on the nrf52_pca10040 board. + +#### Building and Running +******************** + +Prior to provisioning, each button controls its corresponding LED as one +would expect with an actual switch. + +Provisioning is done using the BlueZ meshctl utility. Below is an example that +binds button 2 and LED 1 to application key 1. It then configures button 2 +to publish to group 0xc000 and LED 1 to subscribe to that group. + +``` +discover-unprovisioned on +provision +menu config +target 0100 +appkey-add 1 +bind 0 1 1000 # bind appkey 1 to LED server on element 0 (unicast 0100) +sub-add 0100 c000 1000 # add subscription to group address c000 to the LED server +bind 1 1 1001 # bind appkey 1 to button 2 on element 1 (unicast 0101) +pub-set 0101 c000 1 0 0 1001 # publish button 2 to group address c000 +``` + +The meshctl utility maintains a persistent JSON database containing +the mesh configuration. As additional nodes (boards) are provisioned, it +assigns sequential unicast addresses based on the number of elements +supported by the node. This example supports 4 elements per node. + +The first or root element of the node contains models for configuration, +health, and onoff. The secondary elements only +have models for onoff. The meshctl target for configuration must be the +root element's unicast address as it is the only one that has a +configuration server model. + +If meshctl is gracefully exited, it can be restarted and reconnected to +network 0x0. + +The meshctl utility also supports a onoff model client that can be used to +change the state of any LED that is bound to application key 0x1. +This is done by setting the target to the unicast address of the element +that has that LED's model and issuing the onoff command. +Group addresses are not supported. diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/pkg.yml b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/pkg.yml new file mode 100644 index 00000000..451f37a1 --- /dev/null +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/pkg.yml @@ -0,0 +1,34 @@ +# 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. +# +pkg.name: apps/blemesh_models_example_1 +pkg.type: app +pkg.description: Sample application for BLE Mesh node with on/off model on nRF52840pdk +pkg.author: "MichaƂ Narajowski " +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - "@apache-mynewt-core/kernel/os" + - "@apache-mynewt-core/sys/console/full" + - "@apache-mynewt-core/sys/log/full" + - "@apache-mynewt-core/sys/stats/full" + - nimble/controller + - nimble/host + - nimble/host/services/gap + - nimble/host/services/gatt + - nimble/transport/ram diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c new file mode 100644 index 00000000..ef398c9f --- /dev/null +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/src/main.c @@ -0,0 +1,709 @@ +/* main.c - Application main entry point */ + +/* + * 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. + */ + +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This application is specific to the Nordic nRF52840-PDK board. + * + * It supports the 4 buttons and 4 LEDs as mesh clients and servers. + * + * Prior to provisioning, a button inverts the state of the + * corresponding LED. + * + * Button and LED 1 are in the root node. + * The 3 remaining button/LED pairs are in element 1 through 3. + * Assuming the provisioner assigns 0x100 to the root node, + * the secondary elements will appear at 0x101, 0x102 and 0x103. + * + * It's anticipated that after provisioning, the button clients would + * be configured to publish and the LED servers to subscribe. + * + * If a LED server is provided with a publish address, it will + * also publish its status on a state change. + * + * Messages from a button to its corresponding LED are ignored as + * the LED's state has already been changed locally by the button client. + * + * The buttons are debounced at a nominal 250ms. That value can be + * changed as needed. + * + */ + +#include "os/mynewt.h" +#include "bsp/bsp.h" +#include "console/console.h" +#include "hal/hal_gpio.h" +#include "host/ble_hs.h" +#include "mesh/glue.h" +#include "mesh/mesh.h" + +#define CID_RUNTIME 0x05C3 + +/* Model Operation Codes */ +#define BT_MESH_MODEL_OP_GEN_ONOFF_GET BT_MESH_MODEL_OP_2(0x82, 0x01) +#define BT_MESH_MODEL_OP_GEN_ONOFF_SET BT_MESH_MODEL_OP_2(0x82, 0x02) +#define BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK BT_MESH_MODEL_OP_2(0x82, 0x03) +#define BT_MESH_MODEL_OP_GEN_ONOFF_STATUS BT_MESH_MODEL_OP_2(0x82, 0x04) + +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf); + +static void gen_onoff_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf); + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf); + +static void gen_onoff_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf); + +/* + * Server Configuration Declaration + */ + +static struct bt_mesh_cfg_srv cfg_srv = { + .relay = BT_MESH_RELAY_DISABLED, + .beacon = BT_MESH_BEACON_ENABLED, +#if defined(CONFIG_BT_MESH_FRIEND) + .frnd = BT_MESH_FRIEND_ENABLED, +#else + .frnd = BT_MESH_FRIEND_NOT_SUPPORTED, +#endif +#if defined(CONFIG_BT_MESH_GATT_PROXY) + .gatt_proxy = BT_MESH_GATT_PROXY_ENABLED, +#else + .gatt_proxy = BT_MESH_GATT_PROXY_NOT_SUPPORTED, +#endif + .default_ttl = 7, + + /* 3 transmissions with 20ms interval */ + .net_transmit = BT_MESH_TRANSMIT(2, 20), + .relay_retransmit = BT_MESH_TRANSMIT(2, 20), +}; + +/* + * Client Configuration Declaration + */ + +static struct bt_mesh_cfg_cli cfg_cli = { +}; + +/* + * Health Server Declaration + */ + +static struct bt_mesh_health_srv health_srv = { +}; + +/* + * Publication Declarations + * + * The publication messages are initialized to the + * the size of the opcode + content + * + * For publication, the message must be in static or global as + * it is re-transmitted several times. This occurs + * after the function that called bt_mesh_model_publish() has + * exited and the stack is no longer valid. + * + * Note that the additional 4 bytes for the AppMIC is not needed + * because it is added to a stack variable at the time a + * transmission occurs. + * + */ + +static struct bt_mesh_model_pub health_pub; +static struct bt_mesh_model_pub gen_onoff_pub_srv; +static struct bt_mesh_model_pub gen_onoff_pub_cli; +static struct bt_mesh_model_pub gen_onoff_pub_srv_s_0; +static struct bt_mesh_model_pub gen_onoff_pub_cli_s_0; +static struct bt_mesh_model_pub gen_onoff_pub_srv_s_1; +static struct bt_mesh_model_pub gen_onoff_pub_cli_s_1; +static struct bt_mesh_model_pub gen_onoff_pub_srv_s_2; +static struct bt_mesh_model_pub gen_onoff_pub_cli_s_2; + +static struct os_mbuf *bt_mesh_pub_msg_health_pub; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_0; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_0; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_1; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_1; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_srv_s_2; +static struct os_mbuf *bt_mesh_pub_msg_gen_onoff_pub_cli_s_2; + +void init_pub(void) +{ + bt_mesh_pub_msg_health_pub = NET_BUF_SIMPLE(1 + 3 + 0); + bt_mesh_pub_msg_gen_onoff_pub_srv = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_cli = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_srv_s_0 = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_cli_s_0 = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_srv_s_1 = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_cli_s_1 = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_srv_s_2 = NET_BUF_SIMPLE(2 + 2); + bt_mesh_pub_msg_gen_onoff_pub_cli_s_2 = NET_BUF_SIMPLE(2 + 2); + + health_pub.msg = bt_mesh_pub_msg_health_pub; + gen_onoff_pub_srv.msg = bt_mesh_pub_msg_gen_onoff_pub_srv; + gen_onoff_pub_cli.msg = bt_mesh_pub_msg_gen_onoff_pub_cli; + gen_onoff_pub_srv_s_0.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_0; + gen_onoff_pub_cli_s_0.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_0; + gen_onoff_pub_srv_s_1.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_1; + gen_onoff_pub_cli_s_1.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_1; + gen_onoff_pub_srv_s_2.msg = bt_mesh_pub_msg_gen_onoff_pub_srv_s_2; + gen_onoff_pub_cli_s_2.msg = bt_mesh_pub_msg_gen_onoff_pub_cli_s_2; +} + +/* + * Models in an element must have unique op codes. + * + * The mesh stack dispatches a message to the first model in an element + * that is also bound to an app key and supports the op code in the + * received message. + * + */ + +/* + * OnOff Model Server Op Dispatch Table + * + */ + +static const struct bt_mesh_model_op gen_onoff_srv_op[] = { + { BT_MESH_MODEL_OP_GEN_ONOFF_GET, 0, gen_onoff_get }, + { BT_MESH_MODEL_OP_GEN_ONOFF_SET, 2, gen_onoff_set }, + { BT_MESH_MODEL_OP_GEN_ONOFF_SET_UNACK, 2, gen_onoff_set_unack }, + BT_MESH_MODEL_OP_END, +}; + +/* + * OnOff Model Client Op Dispatch Table + */ + +static const struct bt_mesh_model_op gen_onoff_cli_op[] = { + { BT_MESH_MODEL_OP_GEN_ONOFF_STATUS, 1, gen_onoff_status }, + BT_MESH_MODEL_OP_END, +}; + +struct onoff_state { + u8_t current; + u8_t previous; + u8_t led_gpio_pin; +}; + +/* + * Declare and Initialize Element Contexts + * Change to select different GPIO output pins + */ + +static struct onoff_state onoff_state_arr[] = { + { .led_gpio_pin = LED_1 }, + { .led_gpio_pin = LED_2 }, + { .led_gpio_pin = LED_3 }, + { .led_gpio_pin = LED_4 }, +}; + +/* + * + * Element Model Declarations + * + * Element 0 Root Models + */ + +static struct bt_mesh_model root_models[] = { + BT_MESH_MODEL_CFG_SRV(&cfg_srv), + BT_MESH_MODEL_CFG_CLI(&cfg_cli), + BT_MESH_MODEL_HEALTH_SRV(&health_srv, &health_pub), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, + &gen_onoff_pub_srv, &onoff_state_arr[0]), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, + &gen_onoff_pub_cli, &onoff_state_arr[0]), +}; + +/* + * Element 1 Models + */ + +static struct bt_mesh_model secondary_0_models[] = { + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, + &gen_onoff_pub_srv_s_0, &onoff_state_arr[1]), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, + &gen_onoff_pub_cli_s_0, &onoff_state_arr[1]), +}; + +/* + * Element 2 Models + */ + +static struct bt_mesh_model secondary_1_models[] = { + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, + &gen_onoff_pub_srv_s_1, &onoff_state_arr[2]), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, + &gen_onoff_pub_cli_s_1, &onoff_state_arr[2]), +}; + +/* + * Element 3 Models + */ + +static struct bt_mesh_model secondary_2_models[] = { + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_SRV, gen_onoff_srv_op, + &gen_onoff_pub_srv_s_2, &onoff_state_arr[3]), + BT_MESH_MODEL(BT_MESH_MODEL_ID_GEN_ONOFF_CLI, gen_onoff_cli_op, + &gen_onoff_pub_cli_s_2, &onoff_state_arr[3]), +}; + +/* + * Button to Client Model Assignments + */ + +struct bt_mesh_model *mod_cli_sw[] = { + &root_models[4], + &secondary_0_models[1], + &secondary_1_models[1], + &secondary_2_models[1], +}; + +/* + * LED to Server Model Assigmnents + */ + +struct bt_mesh_model *mod_srv_sw[] = { + &root_models[3], + &secondary_0_models[0], + &secondary_1_models[0], + &secondary_2_models[0], +}; + +/* + * Root and Secondary Element Declarations + */ + +static struct bt_mesh_elem elements[] = { + BT_MESH_ELEM(0, root_models, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(0, secondary_0_models, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(0, secondary_1_models, BT_MESH_MODEL_NONE), + BT_MESH_ELEM(0, secondary_2_models, BT_MESH_MODEL_NONE), +}; + +static const struct bt_mesh_comp comp = { + .cid = CID_RUNTIME, + .elem = elements, + .elem_count = ARRAY_SIZE(elements), +}; + +struct sw { + u8_t sw_num; + u8_t onoff_state; + struct os_callout button_work; + struct os_callout button_timer; +}; + + +static u8_t button_press_cnt; +static struct sw sw; + +static u8_t trans_id; +static u32_t time, last_time; +static u16_t primary_addr; +static u16_t primary_net_idx; + +/* + * Generic OnOff Model Server Message Handlers + * + * Mesh Model Specification 3.1.1 + * + */ + +static void gen_onoff_get(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct os_mbuf *msg = NET_BUF_SIMPLE(2 + 1 + 4); + struct onoff_state *state = model->user_data; + + BT_INFO("addr 0x%04x onoff 0x%02x", + bt_mesh_model_elem(model)->addr, state->current); + bt_mesh_model_msg_init(msg, BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); + net_buf_simple_add_u8(msg, state->current); + + if (bt_mesh_model_send(model, ctx, msg, NULL, NULL)) { + BT_ERR("Unable to send On Off Status response"); + } + + os_mbuf_free_chain(msg); +} + +static void gen_onoff_set_unack(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + struct os_mbuf *msg = model->pub->msg; + struct onoff_state *state = model->user_data; + int err; + + state->current = net_buf_simple_pull_u8(buf); + BT_INFO("addr 0x%02x state 0x%02x", + bt_mesh_model_elem(model)->addr, state->current); + + /* Pin set low turns on LED's on the nrf52840-pca10056 board */ + hal_gpio_write(state->led_gpio_pin, + state->current ? 0 : 1); + + /* + * If a server has a publish address, it is required to + * publish status on a state change + * + * See Mesh Profile Specification 3.7.6.1.2 + * + * Only publish if there is an assigned address + */ + + if (state->previous != state->current && + model->pub->addr != BT_MESH_ADDR_UNASSIGNED) { + BT_INFO("publish last 0x%02x cur 0x%02x", + state->previous, + state->current); + state->previous = state->current; + bt_mesh_model_msg_init(msg, + BT_MESH_MODEL_OP_GEN_ONOFF_STATUS); + net_buf_simple_add_u8(msg, state->current); + err = bt_mesh_model_publish(model); + if (err) { + BT_ERR("bt_mesh_model_publish err %d", err); + } + } +} + +static void gen_onoff_set(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + BT_INFO(""); + + gen_onoff_set_unack(model, ctx, buf); + gen_onoff_get(model, ctx, buf); +} + +static void gen_onoff_status(struct bt_mesh_model *model, + struct bt_mesh_msg_ctx *ctx, + struct os_mbuf *buf) +{ + u8_t state; + + state = net_buf_simple_pull_u8(buf); + + BT_INFO("Node 0x%04x OnOff status from 0x%04x with state 0x%02x", + bt_mesh_model_elem(model)->addr, ctx->addr, state); +} + +static int output_number(bt_mesh_output_action_t action, u32_t number) +{ + BT_INFO("OOB Number %u", number); + return 0; +} + +static int output_string(const char *str) +{ + BT_INFO("OOB String %s", str); + return 0; +} + +static void prov_complete(u16_t net_idx, u16_t addr) +{ + BT_INFO("provisioning complete for net_idx 0x%04x addr 0x%04x", + net_idx, addr); + primary_addr = addr; + primary_net_idx = net_idx; +} + +static void prov_reset(void) +{ + bt_mesh_prov_enable(BT_MESH_PROV_ADV | BT_MESH_PROV_GATT); +} + +static u8_t dev_uuid[16] = MYNEWT_VAL(BLE_MESH_DEV_UUID); + +#define BUTTON_DEBOUNCE_DELAY_MS 250 + +/* + * Map GPIO pins to button number + * Change to select different GPIO input pins + */ + +static uint8_t pin_to_sw(int pin_pos) +{ + switch (pin_pos) { + case BUTTON_1: return 0; + case BUTTON_2: return 1; + case BUTTON_3: return 2; + case BUTTON_4: return 3; + default:break; + } + + BT_ERR("No match for GPIO pin 0x%08x", pin_pos); + return 0; +} + +static void button_pressed(struct os_event *ev) +{ + int pin_pos = (int ) ev->ev_arg; + /* + * One button press within a 1 second interval sends an on message + * More than one button press sends an off message + */ + + time = k_uptime_get_32(); + + /* debounce the switch */ + if (time < last_time + BUTTON_DEBOUNCE_DELAY_MS) { + last_time = time; + return; + } + + if (button_press_cnt == 0) { + os_callout_reset(&sw.button_timer, os_time_ms_to_ticks32(K_SECONDS(1))); + } + + BT_INFO("button_press_cnt 0x%02x", button_press_cnt); + button_press_cnt++; + + /* The variable pin_pos is the pin position in the GPIO register, + * not the pin number. It's assumed that only one bit is set. + */ + + sw.sw_num = pin_to_sw(pin_pos); + last_time = time; +} + +/* + * Button Count Timer Worker + */ + +static void button_cnt_timer(struct os_event *work) +{ + struct sw *button_sw = work->ev_arg; + + button_sw->onoff_state = button_press_cnt == 1 ? 1 : 0; + BT_INFO("button_press_cnt 0x%02x onoff_state 0x%02x", + button_press_cnt, button_sw->onoff_state); + button_press_cnt = 0; + os_callout_reset(&sw.button_work, 0); +} + +/* + * Button Pressed Worker Task + */ + +static void button_pressed_worker(struct os_event *work) +{ + struct os_mbuf *msg = NET_BUF_SIMPLE(1); + struct bt_mesh_model *mod_cli, *mod_srv; + struct bt_mesh_model_pub *pub_cli, *pub_srv; + struct sw *sw = work->ev_arg; + u8_t sw_idx = sw->sw_num; + int err; + + mod_cli = mod_cli_sw[sw_idx]; + pub_cli = mod_cli->pub; + + mod_srv = mod_srv_sw[sw_idx]; + pub_srv = mod_srv->pub; + (void)pub_srv; + + /* If unprovisioned, just call the set function. + * The intent is to have switch-like behavior + * prior to provisioning. Once provisioned, + * the button and its corresponding led are no longer + * associated and act independently. So, if a button is to + * control its associated led after provisioning, the button + * must be configured to either publish to the led's unicast + * address or a group to which the led is subscribed. + */ + + if (primary_addr == BT_MESH_ADDR_UNASSIGNED) { + struct bt_mesh_msg_ctx ctx = { + .addr = sw_idx + primary_addr, + }; + + /* This is a dummy message sufficient + * for the led server + */ + + net_buf_simple_add_u8(msg, sw->onoff_state); + gen_onoff_set_unack(mod_srv, &ctx, msg); + goto done; + } + + if (pub_cli->addr == BT_MESH_ADDR_UNASSIGNED) { + goto done; + } + + BT_INFO("publish to 0x%04x onoff 0x%04x sw_idx 0x%04x", + pub_cli->addr, sw->onoff_state, sw_idx); + bt_mesh_model_msg_init(pub_cli->msg, + BT_MESH_MODEL_OP_GEN_ONOFF_SET); + net_buf_simple_add_u8(pub_cli->msg, sw->onoff_state); + net_buf_simple_add_u8(pub_cli->msg, trans_id++); + err = bt_mesh_model_publish(mod_cli); + if (err) { + BT_ERR("bt_mesh_model_publish err %d", err); + } + +done: + os_mbuf_free_chain(msg); +} + +/* Disable OOB security for SILabs Android app */ + +static const struct bt_mesh_prov prov = { + .uuid = dev_uuid, +#if 1 + .output_size = 6, + .output_actions = (BT_MESH_DISPLAY_NUMBER | BT_MESH_DISPLAY_STRING), + .output_number = output_number, + .output_string = output_string, +#else +.output_size = 0, + .output_actions = 0, + .output_number = 0, +#endif + .complete = prov_complete, + .reset = prov_reset, +}; + +void init_led(u8_t dev) +{ + hal_gpio_init_out(onoff_state_arr[dev].led_gpio_pin, 1); +} + +static struct os_event button_event; + +static void +gpio_irq_handler(void *arg) +{ + button_event.ev_arg = arg; + os_eventq_put(os_eventq_dflt_get(), &button_event); +} + +void init_button(int button) +{ + button_event.ev_cb = button_pressed; + + hal_gpio_irq_init(button, gpio_irq_handler, (void *)button, + HAL_GPIO_TRIG_FALLING, HAL_GPIO_PULL_UP); + hal_gpio_irq_enable(button); +} + +static void +blemesh_on_reset(int reason) +{ + BLE_HS_LOG(ERROR, "Resetting state; reason=%d\n", reason); +} + +static void +blemesh_on_sync(void) +{ + int err; + ble_addr_t addr; + + console_printf("Bluetooth initialized\n"); + + /* Use NRPA */ + err = ble_hs_id_gen_rnd(1, &addr); + assert(err == 0); + err = ble_hs_id_set_rnd(addr.val); + assert(err == 0); + + err = bt_mesh_init(addr.type, &prov, &comp); + if (err) { + console_printf("Initializing mesh failed (err %d)\n", err); + return; + } + + if (IS_ENABLED(CONFIG_SETTINGS)) { + settings_load(); + } + + if (bt_mesh_is_provisioned()) { + console_printf("Mesh network restored from flash\n"); + } + + bt_mesh_prov_enable(BT_MESH_PROV_GATT | BT_MESH_PROV_ADV); + + console_printf("Mesh initialized\n"); +} + +int main(void) +{ +#ifdef ARCH_sim + mcu_sim_parse_args(argc, argv); +#endif + + /* Initialize OS */ + sysinit(); + + BT_INFO("Initializing..."); + + /* Initialize the button debouncer */ + last_time = k_uptime_get_32(); + + /* Initialize button worker task*/ + os_callout_init(&sw.button_work, os_eventq_dflt_get(), + button_pressed_worker, &sw); + + /* Initialize button count timer */ + os_callout_init(&sw.button_timer, os_eventq_dflt_get(), + button_cnt_timer, &sw); + + /* Initialize LED's */ + init_led(0); + init_led(1); + init_led(2); + init_led(3); + + init_button(BUTTON_1); + init_button(BUTTON_2); + init_button(BUTTON_3); + init_button(BUTTON_4); + + init_pub(); + + /* Initialize the NimBLE host configuration. */ + ble_hs_cfg.reset_cb = blemesh_on_reset; + ble_hs_cfg.sync_cb = blemesh_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; + + while (1) { + os_eventq_run(os_eventq_dflt_get()); + } + + return 0; +} diff --git a/src/libs/mynewt-nimble/apps/blemesh_models_example_1/syscfg.yml b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/syscfg.yml new file mode 100644 index 00000000..969753fe --- /dev/null +++ b/src/libs/mynewt-nimble/apps/blemesh_models_example_1/syscfg.yml @@ -0,0 +1,38 @@ +# 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. +# + +syscfg.vals: + # Set log level to info (disable debug logging). + LOG_LEVEL: 1 + + # Default task settings + OS_MAIN_STACK_SIZE: 768 + + # SMP is not supported in this app, so disable smp-over-shell. + SHELL_MGMT: 0 + + MSYS_1_BLOCK_COUNT: 48 + + BLE_MESH: 1 + BLE_MESH_CFG_CLI: 1 + BLE_MESH_DEV_UUID: "((uint8_t[16]){0xdd, 0xdd, 0})" + BLE_MESH_SETTINGS: 0 + CONFIG_NFFS: 0 + + BLE_MESH_ADV_BUF_COUNT: 20 + BLE_MESH_TX_SEG_MAX: 6 -- cgit v1.2.3