diff --git a/doc/mesh-api.txt b/doc/mesh-api.txt
index 23a9587..30b7452 100644
--- a/doc/mesh-api.txt
+++ b/doc/mesh-api.txt
A 16-bit Company ID as defined by the
Bluetooth SIG
+ array{variant} Subscriptions
+
+ Addresses the model is subscribed to.
+
+ Each address is provided either as
+ uint16 for group addresses, or
+ as array{byte} for virtual labels.
+
PossibleErrors:
org.bluez.mesh.Error.InvalidArguments
org.bluez.mesh.Error.NotFound,
A 16-bit Bluetooth-assigned Company Identifier of the
vendor as defined by Bluetooth SIG
+ array{variant} Subscriptions
+
+ Addresses the model is subscribed to.
+
+ Each address is provided either as uint16 for group
+ addresses, or as array{byte} for virtual labels.
+
Properties:
uint8 Index [read-only]
diff --git a/mesh/model.c b/mesh/model.c
index a0c6836..57a63c5 100644
--- a/mesh/model.c
+++ b/mesh/model.c
l_dbus_send(dbus, msg);
}
+static void append_dict_subs_array(struct l_dbus_message_builder *builder,
+ struct l_queue *subs,
+ struct l_queue *virts,
+ const char *key)
+{
+ const struct l_queue_entry *entry;
+
+ l_dbus_message_builder_enter_dict(builder, "sv");
+ l_dbus_message_builder_append_basic(builder, 's', key);
+ l_dbus_message_builder_enter_variant(builder, "av");
+ l_dbus_message_builder_enter_array(builder, "v");
+
+ if (!subs)
+ goto virts;
+
+ for (entry = l_queue_get_entries(subs); entry; entry = entry->next) {
+ uint16_t grp = L_PTR_TO_UINT(entry->data);
+
+ l_dbus_message_builder_enter_variant(builder, "q");
+ l_dbus_message_builder_append_basic(builder, 'q', &grp);
+ l_dbus_message_builder_leave_variant(builder);
+ }
+
+virts:
+ if (!virts)
+ goto done;
+
+ for (entry = l_queue_get_entries(virts); entry; entry = entry->next) {
+ const struct mesh_virtual *virt = entry->data;
+
+ l_dbus_message_builder_enter_variant(builder, "ay");
+ dbus_append_byte_array(builder, virt->label,
+ sizeof(virt->label));
+ l_dbus_message_builder_leave_variant(builder);
+
+ }
+
+done:
+ l_dbus_message_builder_leave_array(builder);
+ l_dbus_message_builder_leave_variant(builder);
+ l_dbus_message_builder_leave_dict(builder);
+}
+
+static void config_update_model_subscriptions(struct mesh_node *node,
+ struct mesh_model *mod)
+{
+ struct l_dbus *dbus = dbus_get_bus();
+ struct l_dbus_message *msg;
+ struct l_dbus_message_builder *builder;
+
+ msg = create_config_update_msg(node, mod->ele_idx, mod->id,
+ &builder);
+ if (!msg)
+ return;
+
+ append_dict_subs_array(builder, mod->subs, mod->virtuals,
+ "Subscriptions");
+
+ l_dbus_message_builder_leave_array(builder);
+ l_dbus_message_builder_finalize(builder);
+ l_dbus_message_builder_destroy(builder);
+ l_dbus_send(dbus, msg);
+}
+
static void forward_model(void *a, void *b)
{
struct mesh_model *mod = a;
if (!mod)
return status;
- return add_sub(node_get_net(node), mod, group, b_virt, dst);
+ status = add_sub(node_get_net(node), mod, group, b_virt, dst);
+
+ if (status != MESH_STATUS_SUCCESS)
+ return status;
+
+ if (!mod->cbs)
+ /* External models */
+ config_update_model_subscriptions(node, mod);
+
+ return MESH_STATUS_SUCCESS;
}
int mesh_model_sub_ovr(struct mesh_node *node, uint16_t addr, uint32_t id,
}
}
- status = mesh_model_sub_add(node, addr, id, group, b_virt, dst);
+ status = add_sub(node_get_net(node), mod, group, b_virt, dst);
if (status != MESH_STATUS_SUCCESS) {
/* Adding new group failed, so revert to old lists */
l_queue_destroy(virtuals, unref_virt);
}
+ if (!mod->cbs)
+ /* External models */
+ config_update_model_subscriptions(node, mod);
+
return status;
}
if (l_queue_remove(mod->subs, L_UINT_TO_PTR(grp)))
mesh_net_dst_unreg(node_get_net(node), grp);
+ if (!mod->cbs)
+ /* External models */
+ config_update_model_subscriptions(node, mod);
+
return MESH_STATUS_SUCCESS;
}
l_queue_clear(mod->subs, NULL);
l_queue_clear(mod->virtuals, unref_virt);
+ if (!mod->cbs)
+ /* External models */
+ config_update_model_subscriptions(node, mod);
+
return MESH_STATUS_SUCCESS;
}
&period);
}
+ if (l_queue_length(mod->subs) || l_queue_length(mod->virtuals))
+ append_dict_subs_array(builder, mod->subs, mod->virtuals,
+ "Subscriptions");
+
l_dbus_message_builder_leave_array(builder);
l_dbus_message_builder_leave_struct(builder);
}
diff --git a/test/test-join b/test/test-join
index fb7b0d6..6dfb2e8 100644
--- a/test/test-join
+++ b/test/test-join
print('Model publication period ', end='')
print(self.pub_period, end='')
print(' ms')
+ if 'Subscriptions' in config:
+ self.print_subscriptions(config.get('Subscriptions'))
+
+ def print_subscriptions(self, subscriptions):
+ print('Model subscriptions ', end='')
+ for sub in subscriptions:
+ if isinstance(sub, int):
+ print('%04x' % sub, end=' ')
+
+ if isinstance(sub, list):
+ label = uuid.UUID(bytes=b''.join(sub))
+ print(label, end=' ')
+ print()
class OnOffServer(Model):
def __init__(self, model_id):
diff --git a/test/test-mesh b/test/test-mesh
index c67bb65..5777fce 100755
--- a/test/test-mesh
+++ b/test/test-mesh
from threading import Timer
import time
+import uuid
try:
from gi.repository import GLib
print('Model publication period ', end='')
print(self.pub_period, end='')
print(' ms')
-
- def print_bindings(self):
- print(set_cyan('Model'), set_cyan('%03x' % self.model_id),
- set_cyan('is bound to: '))
-
- if len(self.bindings) == 0:
- print(set_cyan('** None **'))
- return
-
- for b in self.bindings:
- print(set_green('%03x' % b) + ' ')
+ if 'Subscriptions' in config:
+ print('Model subscriptions ', end='')
+ self.print_subscriptions(config.get('Subscriptions'))
+ print()
+
+ def print_subscriptions(self, subscriptions):
+ for sub in subscriptions:
+ if isinstance(sub, int):
+ print('%04x' % sub, end=' ')
+
+ if isinstance(sub, list):
+ label = uuid.UUID(bytes=b''.join(sub))
+ print(label, end=' ')
########################
# On Off Server Model