2019-11-18 13:54:28

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 0/6] Add features and fix some undesired behaviour of meshctl

From: Daniele <[email protected]>

The followings extend the features of meshctl, adding:
* The Subscription Delete message to the configuration client
(as per Mesh Profile 4.3.2.21)
* The Generic OnOff Set Unacknowledged message to the onoff
client model
* Generic Level Client Model, limited to the following messages:
- generic level get and set
- generic level set unacknowledged
- generic level status
* Generic Power OnOff Client except the Generic OnPowerUp Set
Unacknowledged message
They also contains two fixes:
* The first one cames up when more than a client model is added
to the local node. The received status messages are forwarded
to all clients and they needs to be filtered within each client
in order to avoid wrong reports on the bt shell
* The second one replaces a return statment within the onoff
client model with a warning message when the user selects an
unknown target address. For example it happens when the user
tries to send messages to a group address due to the fact that
such addresses are not stored whitn the json database.

Daniele (6):
tools/mesh: Add onoff set unack message to onoff client model
tools/mesh: Fix status messages processing
tools/mesh: Fix unwanted return in onoff client model
tools/mesh: Add subscription delete message to config client model
tools/mesh: Add generic level model support
tools/mesh: Add generic power onoff client model

Makefile.tools | 4 +-
tools/mesh/config-client.c | 40 +++++
tools/mesh/level-model.c | 298 +++++++++++++++++++++++++++++++++++
tools/mesh/level-model.h | 34 ++++
tools/mesh/local_node.json | 10 +-
tools/mesh/node.c | 11 ++
tools/mesh/onoff-model.c | 52 ++++--
tools/mesh/onpowerup-model.c | 262 ++++++++++++++++++++++++++++++
tools/mesh/onpowerup-model.h | 34 ++++
tools/meshctl.c | 8 +
10 files changed, 734 insertions(+), 19 deletions(-)
create mode 100644 tools/mesh/level-model.c
create mode 100644 tools/mesh/level-model.h
create mode 100644 tools/mesh/onpowerup-model.c
create mode 100644 tools/mesh/onpowerup-model.h

--
2.20.1


2019-11-18 13:54:28

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 4/6] tools/mesh: Add subscription delete message to config client model

From: Daniele <[email protected]>

---
tools/mesh/config-client.c | 40 ++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)

diff --git a/tools/mesh/config-client.c b/tools/mesh/config-client.c
index df2643622..bff38e7a3 100644
--- a/tools/mesh/config-client.c
+++ b/tools/mesh/config-client.c
@@ -1042,6 +1042,44 @@ static void cmd_sub_get(int argc, char *argv[])
return bt_shell_noninteractive_quit(EXIT_SUCCESS);
}

+static void cmd_sub_del(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ int parm_cnt;
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ n = mesh_opcode_set(OP_CONFIG_MODEL_SUB_DELETE, msg);
+
+ parm_cnt = read_input_parameters(argc, argv);
+ if (parm_cnt != 3) {
+ bt_shell_printf("Bad arguments: %s\n", argv[1]);
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ /* Per Mesh Profile 4.3.2.19 */
+ /* Element Address */
+ put_le16(parms[0], msg + n);
+ n += 2;
+ /* Subscription Address */
+ put_le16(parms[1], msg + n);
+ n += 2;
+ /* SIG Model ID */
+ put_le16(parms[2], msg + n);
+ n += 2;
+
+ if (!config_send(msg, n)) {
+ bt_shell_printf("Failed to send \"ADD SUBSCRIPTION\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
static void cmd_mod_appidx_get(int argc, char *argv[])
{
uint16_t n;
@@ -1237,6 +1275,8 @@ static const struct bt_shell_menu cfg_menu = {
cmd_sub_add, "Add subscription"},
{"sub-get", "<ele_addr> <model id>",
cmd_sub_get, "Get subscription"},
+ {"sub-del", "<ele_addr> <sub_addr> <model id>",
+ cmd_sub_del, "Delete subscription"},
{"node-reset", NULL, cmd_node_reset,
"Reset a node and remove it from network"},
{} },
--
2.20.1

2019-11-18 13:54:28

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 1/6] tools/mesh: Add onoff set unack message to onoff client model

From: Daniele <[email protected]>

---
tools/mesh/onoff-model.c | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/tools/mesh/onoff-model.c b/tools/mesh/onoff-model.c
index b52afe2c8..6236e1fea 100644
--- a/tools/mesh/onoff-model.c
+++ b/tools/mesh/onoff-model.c
@@ -238,6 +238,8 @@ static void cmd_set(int argc, char *argv[])
uint16_t n;
uint8_t msg[32];
struct mesh_node *node;
+ int np;
+ uint32_t opcode;

if (IS_UNASSIGNED(target)) {
bt_shell_printf("Destination not set\n");
@@ -249,13 +251,22 @@ static void cmd_set(int argc, char *argv[])
if (!node)
return;

- if ((read_input_parameters(argc, argv) != 1) &&
- parms[0] != 0 && parms[0] != 1) {
- bt_shell_printf("Bad arguments: Expecting \"0\" or \"1\"\n");
- return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ np = read_input_parameters(argc, argv);
+ if ((np != 1) && (np != 2) &&
+ parms[0] != 0 && parms[0] != 1 &&
+ parms[1] != 0 && parms[1] != 1) {
+ bt_shell_printf("Bad arguments: Expecting \"0\" or \"1\" "
+ "and an optional \"0\" or \"1\" as unack\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if( (np==2) && parms[1] ){
+ opcode = OP_GENERIC_ONOFF_SET_UNACK;
+ }else{
+ opcode = OP_GENERIC_ONOFF_SET;
}

- n = mesh_opcode_set(OP_GENERIC_ONOFF_SET, msg);
+ n = mesh_opcode_set(opcode, msg);
msg[n++] = parms[0];
msg[n++] = trans_id++;

@@ -275,7 +286,7 @@ static const struct bt_shell_menu onoff_menu = {
"Set node to configure"},
{"get", NULL, cmd_get_status,
"Get ON/OFF status"},
- {"onoff", "<0/1>", cmd_set,
+ {"onoff", "<0/1> [unack]", cmd_set,
"Send \"SET ON/OFF\" command"},
{} },
};
--
2.20.1

2019-11-18 13:54:41

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 5/6] tools/mesh: Add generic level model support

From: Daniele <[email protected]>

---
Makefile.tools | 3 +-
tools/mesh/level-model.c | 298 +++++++++++++++++++++++++++++++++++++
tools/mesh/level-model.h | 34 +++++
tools/mesh/local_node.json | 6 +-
tools/meshctl.c | 4 +
5 files changed, 343 insertions(+), 2 deletions(-)
create mode 100644 tools/mesh/level-model.c
create mode 100644 tools/mesh/level-model.h

diff --git a/Makefile.tools b/Makefile.tools
index 7ce05b7ef..9c0cdedb8 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -316,7 +316,8 @@ tools_meshctl_SOURCES = tools/meshctl.c \
tools/mesh/prov-db.h tools/mesh/prov-db.c \
tools/mesh/config-model.h tools/mesh/config-client.c \
tools/mesh/config-server.c \
- tools/mesh/onoff-model.h tools/mesh/onoff-model.c
+ tools/mesh/onoff-model.h tools/mesh/onoff-model.c \
+ tools/mesh/level-model.h tools/mesh/level-model.c
tools_meshctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
lib/libbluetooth-internal.la \
$(GLIB_LIBS) $(DBUS_LIBS) -ljson-c -lreadline
diff --git a/tools/mesh/level-model.c b/tools/mesh/level-model.c
new file mode 100644
index 000000000..03a0d24c6
--- /dev/null
+++ b/tools/mesh/level-model.c
@@ -0,0 +1,298 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/uio.h>
+#include <wordexp.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <glib.h>
+
+#include "src/shared/shell.h"
+#include "src/shared/util.h"
+#include "tools/mesh/mesh-net.h"
+#include "tools/mesh/keys.h"
+#include "tools/mesh/net.h"
+#include "tools/mesh/node.h"
+#include "tools/mesh/prov-db.h"
+#include "tools/mesh/util.h"
+#include "tools/mesh/level-model.h"
+
+static uint8_t trans_id;
+static uint16_t level_app_idx = APP_IDX_INVALID;
+static int client_bind(uint16_t app_idx, int action)
+{
+ if (action == ACTION_ADD) {
+ if (level_app_idx != APP_IDX_INVALID) {
+ return MESH_STATUS_INSUFF_RESOURCES;
+ } else {
+ level_app_idx = app_idx;
+ bt_shell_printf("Level client model: new binding"
+ " %4.4x\n", app_idx);
+ }
+ } else {
+ if (level_app_idx == app_idx)
+ level_app_idx = APP_IDX_INVALID;
+ }
+ return MESH_STATUS_SUCCESS;
+}
+static void print_remaining_time(uint8_t remaining_time)
+{
+ uint8_t step = (remaining_time & 0xc0) >> 6;
+ uint8_t count = remaining_time & 0x3f;
+ int secs = 0, msecs = 0, minutes = 0, hours = 0;
+ switch (step) {
+ case 0:
+ msecs = 100 * count;
+ secs = msecs / 1000;
+ msecs -= (secs * 1000);
+ break;
+ case 1:
+ secs = 1 * count;
+ minutes = secs / 60;
+ secs -= (minutes * 60);
+ break;
+ case 2:
+ secs = 10 * count;
+ minutes = secs / 60;
+ secs -= (minutes * 60);
+ break;
+ case 3:
+ minutes = 10 * count;
+ hours = minutes / 60;
+ minutes -= (hours * 60);
+ break;
+ default:
+ break;
+ }
+ bt_shell_printf("\n\t\tRemaining time: %d hrs %d mins %d secs %d"
+ " msecs\n", hours, minutes, secs, msecs);
+}
+static bool client_msg_recvd(uint16_t src, uint8_t *data,
+ uint16_t len, void *user_data)
+{
+ uint32_t opcode;
+ int n;
+ uint8_t *p;
+ int16_t lev;
+ char s[128];
+
+ if (mesh_opcode_get(data, len, &opcode, &n)) {
+ len -= n;
+ data += n;
+ } else
+ return false;
+
+ switch (opcode & ~OP_UNRELIABLE) {
+ default:
+ return false;
+ case OP_GENERIC_LEVEL_STATUS:
+ bt_shell_printf("Level Model Message received (%d) opcode %x\n",
+ len, opcode);
+ print_byte_array("\t",data, len);
+
+ if (len != 2 && len != 4 && len != 5)
+ break;
+ lev = 0;
+ p = (uint8_t *)&lev;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ p[0] = data[0];
+ p[1] = data[1];
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ p[1] = data[0];
+ p[0] = data[1];
+#else
+#error "Unknown byte order"
+#error Processor endianness unknown!
+#endif
+ sprintf(s, "Node %4.4x: Level Status present = %d",
+ src, lev);
+ if (len >= 4) {
+ lev = (int16_t)(((uint16_t)data[3] << 8) | (uint16_t)data[2]);
+ sprintf(s, ", target = %d",
+ lev);
+ }
+ bt_shell_printf("%s\n", s);
+ if(len == 5){
+ print_remaining_time(data[4]);
+ }
+ break;
+ }
+ return true;
+}
+static uint32_t target;
+static int32_t parms[8];
+static uint32_t read_input_parameters(int argc, char *argv[])
+{
+ uint32_t i;
+ if (!argc)
+ return 0;
+ --argc;
+ ++argv;
+ if (!argc || argv[0][0] == '\0')
+ return 0;
+ for (i = 0; i < sizeof(parms)/sizeof(parms[0]) && i < (unsigned) argc;
+ i++) {
+ if(sscanf(argv[i], "%d", &parms[i]) <= 0)
+ break;
+ }
+ return i;
+}
+static void cmd_set_node(int argc, char *argv[])
+{
+ uint32_t dst;
+ char *end;
+ dst = strtol(argv[1], &end, 16);
+ if (end != (argv[1] + 4)) {
+ bt_shell_printf("Bad unicast address %s: "
+ "expected format 4 digit hex\n", argv[1]);
+ target = UNASSIGNED_ADDRESS;
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ } else {
+ bt_shell_printf("Controlling Level for node %4.4x\n", dst);
+ target = dst;
+ set_menu_prompt("Level", argv[1]);
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ }
+}
+static bool send_cmd(uint8_t *buf, uint16_t len)
+{
+ struct mesh_node *node = node_get_local_node();
+ uint8_t ttl;
+ if(!node)
+ return false;
+ ttl = node_get_default_ttl(node);
+ return net_access_layer_send(ttl, node_get_primary(node),
+ target, level_app_idx, buf, len);
+}
+static void cmd_get_status(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ struct mesh_node *node;
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+ node = node_find_by_addr(target);
+
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }
+
+ n = mesh_opcode_set(OP_GENERIC_LEVEL_GET, msg);
+ if (!send_cmd(msg, n)) {
+ bt_shell_printf("Failed to send \"GENERIC LEVEL GET\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+static void cmd_set(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ struct mesh_node *node;
+ uint8_t *p;
+ int np;
+ uint32_t opcode;
+ int16_t level;
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+ node = node_find_by_addr(target);
+
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }
+
+ np = read_input_parameters(argc, argv);
+ if ((np != 1) && (np != 2) &&
+ parms[0] < -32768 && parms[0] > 32767 &&
+ parms[1] != 0 && parms[1] != 1) {
+ bt_shell_printf("Bad arguments: Expecting an integer "
+ "-32768 to 32767 and an optional 0 or 1 as unack\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ if( (np==2) && parms[1] ){
+ opcode = OP_GENERIC_LEVEL_SET_UNACK;
+ }else{
+ opcode = OP_GENERIC_LEVEL_SET;
+ }
+
+ n = mesh_opcode_set(opcode, msg);
+ level = (int16_t)parms[0];
+ p = (uint8_t *)&level;
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+ msg[n++] = p[0];
+ msg[n++] = p[1];
+#elif __BYTE_ORDER == __BIG_ENDIAN
+ msg[n++] = p[1];
+ msg[n++] = p[0];
+#else
+#error "Unknown byte order"
+#error Processor endianness unknown!
+#endif
+ msg[n++] = trans_id++;
+ if (!send_cmd(msg, n)) {
+ bt_shell_printf("Failed to send \"GENERIC LEVEL SET\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+static const struct bt_shell_menu level_menu = {
+ .name = "level",
+ .desc = "Level Model Submenu",
+ .entries = {
+ {"target", "<unicast>", cmd_set_node,
+ "Set node to configure"},
+ {"get", NULL, cmd_get_status,
+ "Get Level status"},
+ {"level", "<-32768/+32767> [unack]", cmd_set,
+ "Send \"SET Level\" command"},
+ {} },
+};
+static struct mesh_model_ops client_cbs = {
+ client_msg_recvd,
+ client_bind,
+ NULL,
+ NULL
+};
+bool level_client_init(uint8_t ele)
+{
+ if (!node_local_model_register(ele, GENERIC_LEVEL_CLIENT_MODEL_ID,
+ &client_cbs, NULL))
+ return false;
+ bt_shell_add_submenu(&level_menu);
+ return true;
+}
diff --git a/tools/mesh/level-model.h b/tools/mesh/level-model.h
new file mode 100644
index 000000000..80c08f14a
--- /dev/null
+++ b/tools/mesh/level-model.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#define GENERIC_LEVEL_SERVER_MODEL_ID 0x1002
+#define GENERIC_LEVEL_CLIENT_MODEL_ID 0x1003
+#define OP_GENERIC_LEVEL_GET 0x8205
+#define OP_GENERIC_LEVEL_SET 0x8206
+#define OP_GENERIC_LEVEL_SET_UNACK 0x8207
+#define OP_GENERIC_LEVEL_STATUS 0x8208
+#define OP_GENERIC_DELTA_SET 0x8209
+#define OP_GENERIC_DELTA_SET_UNACK 0x820A
+#define OP_GENERIC_MOVE_SET 0x820B
+#define OP_GENERIC_MOVE_SET_UNACK 0x820C
+void level_set_node(const char *args);
+bool level_client_init(uint8_t ele);
diff --git a/tools/mesh/local_node.json b/tools/mesh/local_node.json
index 5ffa7ada1..462cd815d 100644
--- a/tools/mesh/local_node.json
+++ b/tools/mesh/local_node.json
@@ -36,7 +36,7 @@
{
"elementIndex": 0,
"location": "0001",
- "models": ["0000", "0001", "1001"]
+ "models": ["0000", "0001", "1001", "1003"]
}
]
},
@@ -52,6 +52,10 @@
{
"modelId": "1001",
"bind": [1]
+ },
+ {
+ "modelId": "1003",
+ "bind": [1]
}
]
}
diff --git a/tools/meshctl.c b/tools/meshctl.c
index 6b6f10882..656575a94 100644
--- a/tools/meshctl.c
+++ b/tools/meshctl.c
@@ -59,6 +59,7 @@
#include "mesh/prov-db.h"
#include "mesh/config-model.h"
#include "mesh/onoff-model.h"
+#include "mesh/level-model.h"

/* String display constants */
#define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF
@@ -2010,6 +2011,9 @@ int main(int argc, char *argv[])
if (!onoff_client_init(PRIMARY_ELEMENT_IDX))
g_printerr("Failed to initialize mesh generic On/Off client\n");

+ if (!level_client_init(PRIMARY_ELEMENT_IDX))
+ g_printerr("Failed to initialize mesh generic level client\n");
+
status = bt_shell_run();

g_dbus_client_unref(client);
--
2.20.1

2019-11-18 13:57:06

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 2/6] tools/mesh: Fix status messages processing

From: Daniele <[email protected]>

The status messages was processed and displayed even if they do
not belong to the present model. This fix ensure that the status
messages are processed only if they have the correct opcode.
---
tools/mesh/node.c | 11 +++++++++++
tools/mesh/onoff-model.c | 19 ++++++++++++-------
2 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/tools/mesh/node.c b/tools/mesh/node.c
index d23315ce4..3171ef01a 100644
--- a/tools/mesh/node.c
+++ b/tools/mesh/node.c
@@ -475,6 +475,8 @@ static bool deliver_model_data(struct mesh_element* element, uint16_t src,
uint16_t app_idx, uint8_t *data, uint16_t len)
{
GList *l;
+ uint32_t opcode;
+ int n;

for(l = element->models; l; l = l->next) {
struct mesh_model *model = l->data;
@@ -487,6 +489,15 @@ static bool deliver_model_data(struct mesh_element* element, uint16_t src,
return true;
}

+ if (mesh_opcode_get(data, len, &opcode, &n)) {
+ len -= n;
+ data += n;
+ } else
+ return false;
+ bt_shell_printf("Unknown Model Message received (%d) opcode %x\n",
+ len, opcode);
+ print_byte_array("\t",data, len);
+
return false;
}

diff --git a/tools/mesh/onoff-model.c b/tools/mesh/onoff-model.c
index 6236e1fea..a6baeb0c5 100644
--- a/tools/mesh/onoff-model.c
+++ b/tools/mesh/onoff-model.c
@@ -111,6 +111,7 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
{
uint32_t opcode;
int n;
+ char s[128];

if (mesh_opcode_get(data, len, &opcode, &n)) {
len -= n;
@@ -127,18 +128,22 @@ static bool client_msg_recvd(uint16_t src, uint8_t *data,
return false;

case OP_GENERIC_ONOFF_STATUS:
+ bt_shell_printf("On Off Model Message received (%d) opcode %x\n",
+ len, opcode);
+ print_byte_array("\t",data, len);
if (len != 1 && len != 3)
break;

- bt_shell_printf("Node %4.4x: Off Status present = %s",
- src, data[0] ? "ON" : "OFF");
-
+ sprintf(s, "Node %4.4x: On Off Status present = %s",
+ src, data[0] ? "ON" : "OFF");
if (len == 3) {
- bt_shell_printf(", target = %s",
- data[1] ? "ON" : "OFF");
+ sprintf(s, ", target = %s",
+ data[1] ? "ON" : "OFF");
+ bt_shell_printf("%s\n", s);
print_remaining_time(data[2]);
- } else
- bt_shell_printf("\n");
+ }else
+ bt_shell_printf("%s\n", s);
+
break;
}

--
2.20.1

2019-11-18 13:57:06

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 3/6] tools/mesh: Fix unwanted return in onoff client model

From: Daniele <[email protected]>

Replaced the return statement with a warning message in case of
transmission or reception of messages coming from unknown addresses
(such as group addresses)
---
tools/mesh/onoff-model.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/tools/mesh/onoff-model.c b/tools/mesh/onoff-model.c
index a6baeb0c5..8199e32bd 100644
--- a/tools/mesh/onoff-model.c
+++ b/tools/mesh/onoff-model.c
@@ -225,8 +225,9 @@ static void cmd_get_status(int argc, char *argv[])

node = node_find_by_addr(target);

- if (!node)
- return;
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }

n = mesh_opcode_set(OP_GENERIC_ONOFF_GET, msg);

@@ -253,8 +254,9 @@ static void cmd_set(int argc, char *argv[])

node = node_find_by_addr(target);

- if (!node)
- return;
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }

np = read_input_parameters(argc, argv);
if ((np != 1) && (np != 2) &&
--
2.20.1

2019-11-18 13:57:06

by Daniele Biagetti

[permalink] [raw]
Subject: [PATCH 6/6] tools/mesh: Add generic power onoff client model

From: Daniele <[email protected]>

---
Makefile.tools | 3 +-
tools/mesh/local_node.json | 6 +-
tools/mesh/onpowerup-model.c | 262 +++++++++++++++++++++++++++++++++++
tools/mesh/onpowerup-model.h | 34 +++++
tools/meshctl.c | 4 +
5 files changed, 307 insertions(+), 2 deletions(-)
create mode 100644 tools/mesh/onpowerup-model.c
create mode 100644 tools/mesh/onpowerup-model.h

diff --git a/Makefile.tools b/Makefile.tools
index 9c0cdedb8..c4dd2b388 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -317,7 +317,8 @@ tools_meshctl_SOURCES = tools/meshctl.c \
tools/mesh/config-model.h tools/mesh/config-client.c \
tools/mesh/config-server.c \
tools/mesh/onoff-model.h tools/mesh/onoff-model.c \
- tools/mesh/level-model.h tools/mesh/level-model.c
+ tools/mesh/level-model.h tools/mesh/level-model.c \
+ tools/mesh/onpowerup-model.h tools/mesh/onpowerup-model.c
tools_meshctl_LDADD = gdbus/libgdbus-internal.la src/libshared-glib.la \
lib/libbluetooth-internal.la \
$(GLIB_LIBS) $(DBUS_LIBS) -ljson-c -lreadline
diff --git a/tools/mesh/local_node.json b/tools/mesh/local_node.json
index 462cd815d..2c332eb1c 100644
--- a/tools/mesh/local_node.json
+++ b/tools/mesh/local_node.json
@@ -36,7 +36,7 @@
{
"elementIndex": 0,
"location": "0001",
- "models": ["0000", "0001", "1001", "1003"]
+ "models": ["0000", "0001", "1001", "1003", "1008"]
}
]
},
@@ -56,6 +56,10 @@
{
"modelId": "1003",
"bind": [1]
+ },
+ {
+ "modelId": "1008",
+ "bind": [1]
}
]
}
diff --git a/tools/mesh/onpowerup-model.c b/tools/mesh/onpowerup-model.c
new file mode 100644
index 000000000..0d582bffe
--- /dev/null
+++ b/tools/mesh/onpowerup-model.c
@@ -0,0 +1,262 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <sys/uio.h>
+#include <wordexp.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+#include <glib.h>
+
+#include "src/shared/shell.h"
+#include "src/shared/util.h"
+#include "tools/mesh/mesh-net.h"
+#include "tools/mesh/keys.h"
+#include "tools/mesh/net.h"
+#include "tools/mesh/node.h"
+#include "tools/mesh/prov-db.h"
+#include "tools/mesh/util.h"
+#include "tools/mesh/onpowerup-model.h"
+
+static uint8_t trans_id;
+static uint16_t power_onoff_app_idx = APP_IDX_INVALID;
+
+static int client_bind(uint16_t app_idx, int action)
+{
+ if (action == ACTION_ADD) {
+ if (power_onoff_app_idx != APP_IDX_INVALID) {
+ return MESH_STATUS_INSUFF_RESOURCES;
+ } else {
+ power_onoff_app_idx = app_idx;
+ bt_shell_printf("OnPowerUp client model: new binding"
+ " %4.4x\n", app_idx);
+ }
+ } else {
+ if (power_onoff_app_idx == app_idx)
+ power_onoff_app_idx = APP_IDX_INVALID;
+ }
+ return MESH_STATUS_SUCCESS;
+}
+
+static bool client_msg_recvd(uint16_t src, uint8_t *data,
+ uint16_t len, void *user_data)
+{
+ uint32_t opcode;
+ int n;
+ char s[10];
+
+ if (mesh_opcode_get(data, len, &opcode, &n)) {
+ len -= n;
+ data += n;
+ } else
+ return false;
+
+ switch (opcode & ~OP_UNRELIABLE) {
+ default:
+ return false;
+
+ case OP_GENERIC_POWER_ONOFF_STATUS:
+ bt_shell_printf("OnPowerUp Model Message received (%d) opcode %x\n",
+ len, opcode);
+ print_byte_array("\t",data, len);
+ if (len != 1)
+ break;
+ if(data[0] == 0){
+ sprintf(s, "%s", "OFF");
+ }else if(data[0] == 1){
+ sprintf(s, "%s", "ON");
+ }else if(data[0] == 2){
+ sprintf(s, "%s", "RESUME");
+ }else{
+ sprintf(s, "%s", "?UNKNOWN");
+ }
+ bt_shell_printf("Node %4.4x: OnPowerUp Status present = %s\n", src, s);
+ break;
+ }
+ return true;
+}
+
+
+static uint32_t target;
+static uint32_t parms[8];
+
+static uint32_t read_input_parameters(int argc, char *argv[])
+{
+ uint32_t i;
+
+ if (!argc)
+ return 0;
+
+ --argc;
+ ++argv;
+
+ if (!argc || argv[0][0] == '\0')
+ return 0;
+
+ memset(parms, 0xff, sizeof(parms));
+
+ for (i = 0; i < sizeof(parms)/sizeof(parms[0]) && i < (unsigned) argc;
+ i++) {
+ sscanf(argv[i], "%x", &parms[i]);
+ if (parms[i] == 0xffffffff)
+ break;
+ }
+
+ return i;
+}
+
+static void cmd_set_node(int argc, char *argv[])
+{
+ uint32_t dst;
+ char *end;
+
+ dst = strtol(argv[1], &end, 16);
+ if (end != (argv[1] + 4)) {
+ bt_shell_printf("Bad unicast address %s: "
+ "expected format 4 digit hex\n", argv[1]);
+ target = UNASSIGNED_ADDRESS;
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ } else {
+ bt_shell_printf("Controlling OnPowerUp for node %4.4x\n", dst);
+ target = dst;
+ set_menu_prompt("OnPowerUp", argv[1]);
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+ }
+}
+
+static bool send_cmd(uint8_t *buf, uint16_t len)
+{
+ struct mesh_node *node = node_get_local_node();
+ uint8_t ttl;
+
+ if(!node)
+ return false;
+
+ ttl = node_get_default_ttl(node);
+
+ return net_access_layer_send(ttl, node_get_primary(node),
+ target, power_onoff_app_idx, buf, len);
+}
+
+static void cmd_get_status(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ struct mesh_node *node;
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ node = node_find_by_addr(target);
+
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }
+
+ n = mesh_opcode_set(OP_GENERIC_POWER_ONOFF_GET, msg);
+
+ if (!send_cmd(msg, n)) {
+ bt_shell_printf("Failed to send \"GENERIC POWER ONOFF GET\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static void cmd_set(int argc, char *argv[])
+{
+ uint16_t n;
+ uint8_t msg[32];
+ struct mesh_node *node;
+
+ if (IS_UNASSIGNED(target)) {
+ bt_shell_printf("Destination not set\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ node = node_find_by_addr(target);
+
+ if (!node){
+ bt_shell_printf("Warning: node %4.4x not found in database\n",target);
+ }
+
+ if ((read_input_parameters(argc, argv) != 1) &&
+ parms[0] != 0 && parms[0] != 1 && parms[0] != 2) {
+ bt_shell_printf("Bad arguments: Expecting \"0\" or \"1\" or \"2\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ n = mesh_opcode_set(OP_GENERIC_POWER_ONOFF_SET, msg);
+ msg[n++] = parms[0];
+ msg[n++] = trans_id++;
+
+ if (!send_cmd(msg, n)) {
+ bt_shell_printf("Failed to send \"GENERIC POWER ONOFF SET\"\n");
+ return bt_shell_noninteractive_quit(EXIT_FAILURE);
+ }
+
+ return bt_shell_noninteractive_quit(EXIT_SUCCESS);
+}
+
+static const struct bt_shell_menu power_onoff_menu = {
+ .name = "power_onoff",
+ .desc = "Power OnOff (OnPowerUp) Model Submenu",
+ .entries = {
+ {"target", "<unicast>", cmd_set_node,
+ "Set node to configure"},
+ {"get", NULL, cmd_get_status,
+ "Get OnPowerUp status"},
+ {"set", "<0/1/2>", cmd_set,
+ "Set OnPowerUp status (OFF/ON/RESTORE)"},
+ {} },
+};
+
+static struct mesh_model_ops client_cbs = {
+ client_msg_recvd,
+ client_bind,
+ NULL,
+ NULL
+};
+
+bool power_onoff_client_init(uint8_t ele)
+{
+ if (!node_local_model_register(ele, GENERIC_POWER_ONOFF_CLIENT_MODEL_ID,
+ &client_cbs, NULL))
+ return false;
+
+ bt_shell_add_submenu(&power_onoff_menu);
+
+ return true;
+}
diff --git a/tools/mesh/onpowerup-model.h b/tools/mesh/onpowerup-model.h
new file mode 100644
index 000000000..bc9b514ff
--- /dev/null
+++ b/tools/mesh/onpowerup-model.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2017 Intel Corporation. All rights reserved.
+ *
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#define GENERIC_POWER_ONOFF_SERVER_MODEL_ID 0x1006
+#define GENERIC_POWER_ONOFF_SETUP_SERVER_MODEL_ID 0x1007
+#define GENERIC_POWER_ONOFF_CLIENT_MODEL_ID 0x1008
+
+#define OP_GENERIC_POWER_ONOFF_GET 0x8211
+#define OP_GENERIC_POWER_ONOFF_STATUS 0x8212
+#define OP_GENERIC_POWER_ONOFF_SET 0x8213
+#define OP_GENERIC_POWER_ONOFF_SET_UNACK 0x8214
+
+void power_onoff_set_node(const char *args);
+bool power_onoff_client_init(uint8_t ele);
diff --git a/tools/meshctl.c b/tools/meshctl.c
index 656575a94..3ca82bf81 100644
--- a/tools/meshctl.c
+++ b/tools/meshctl.c
@@ -60,6 +60,7 @@
#include "mesh/config-model.h"
#include "mesh/onoff-model.h"
#include "mesh/level-model.h"
+#include "mesh/onpowerup-model.h"

/* String display constants */
#define COLORED_NEW COLOR_GREEN "NEW" COLOR_OFF
@@ -2014,6 +2015,9 @@ int main(int argc, char *argv[])
if (!level_client_init(PRIMARY_ELEMENT_IDX))
g_printerr("Failed to initialize mesh generic level client\n");

+ if (!power_onoff_client_init(PRIMARY_ELEMENT_IDX))
+ g_printerr("Failed to initialize mesh generic power On/Off client\n");
+
status = bt_shell_run();

g_dbus_client_unref(client);
--
2.20.1

2019-11-19 07:35:13

by Stotland, Inga

[permalink] [raw]
Subject: Re: [PATCH 0/6] Add features and fix some undesired behaviour of meshctl

Hi Daniele,

On Mon, 2019-11-18 at 14:43 +0100, Daniele Biagetti wrote:
> From: Daniele <
> [email protected]
> >
>
> The followings extend the features of meshctl, adding:
> * The Subscription Delete message to the configuration client
> (as per Mesh Profile 4.3.2.21)
> * The Generic OnOff Set Unacknowledged message to the onoff
> client model
> * Generic Level Client Model, limited to the following messages:
> - generic level get and set
> - generic level set unacknowledged
> - generic level status
> * Generic Power OnOff Client except the Generic OnPowerUp Set
> Unacknowledged message
> They also contains two fixes:
> * The first one cames up when more than a client model is added
> to the local node. The received status messages are forwarded
> to all clients and they needs to be filtered within each client
> in order to avoid wrong reports on the bt shell
> * The second one replaces a return statment within the onoff
> client model with a warning message when the user selects an
> unknown target address. For example it happens when the user
> tries to send messages to a group address due to the fact that
> such addresses are not stored whitn the json database.
>
> Daniele (6):
> tools/mesh: Add onoff set unack message to onoff client model
> tools/mesh: Fix status messages processing
> tools/mesh: Fix unwanted return in onoff client model
> tools/mesh: Add subscription delete message to config client model
> tools/mesh: Add generic level model support
> tools/mesh: Add generic power onoff client model
>
> Makefile.tools | 4 +-
> tools/mesh/config-client.c | 40 +++++
> tools/mesh/level-model.c | 298
> +++++++++++++++++++++++++++++++++++
> tools/mesh/level-model.h | 34 ++++
> tools/mesh/local_node.json | 10 +-
> tools/mesh/node.c | 11 ++
> tools/mesh/onoff-model.c | 52 ++++--
> tools/mesh/onpowerup-model.c | 262 ++++++++++++++++++++++++++++++
> tools/mesh/onpowerup-model.h | 34 ++++
> tools/meshctl.c | 8 +
> 10 files changed, 734 insertions(+), 19 deletions(-)
> create mode 100644 tools/mesh/level-model.c
> create mode 100644 tools/mesh/level-model.h
> create mode 100644 tools/mesh/onpowerup-model.c
> create mode 100644 tools/mesh/onpowerup-model.h
>
>

It looks like the patches are not generated against the tip of the
BlueZ tree. The meshctl specific files are now residing in tools/mesh-
gatt directory. You would need to update the BlueZ source and
regenerate the patches.

Best regards,
Inga