diff --git a/examples/bps.cxx b/examples/bps.cxx
index 13e657f..c19b547 100644
--- a/examples/bps.cxx
+++ b/examples/bps.cxx
@@ -1,7 +1,7 @@
 #include <pza/core/client.hxx>
 #include <pza/core/core.hxx>
 #include <pza/interfaces/ammeter.hxx>
-#include <pza/interfaces/bps_chan_ctrl.hxx>
+#include <pza/interfaces/bpc.hxx>
 #include <pza/interfaces/voltmeter.hxx>
 
 static const std::string addr = "localhost";
@@ -35,7 +35,7 @@ int main()
 		return -1;
 	}
 
-	auto ctrl = cli->get_interface<pza::itf::bps_chan_ctrl>("default", "Panduza_FakeBps", "channel", 0, "ctrl");
+	auto ctrl = cli->get_interface<pza::itf::bpc>("default", "Panduza_FakeBps", "channel", 0, "ctrl");
 	if (!ctrl) {
 		spdlog::error("ctrl not found");
 		return -1;
@@ -55,7 +55,9 @@ int main()
 
 	am->register_measure_callback([&]() { spdlog::info("current: {}", am->get_measure()); });
 
-	while (true)
-		;
+	cli->disconnect();
+
+	//while (true)
+	//	;
 	return 0;
 }
diff --git a/include/pza/core/device.hxx b/include/pza/core/device.hxx
index 83828ed..a08ddf0 100644
--- a/include/pza/core/device.hxx
+++ b/include/pza/core/device.hxx
@@ -62,6 +62,8 @@ public:
 
 	[[nodiscard]] std::set<std::string> get_interface_groups() const;
 
+	[[nodiscard]] size_t get_interface_groups_count() const;
+
 	[[nodiscard]] std::vector<itf_base::s_ptr> get_interfaces() const;
 
 private:
diff --git a/include/pza/core/interface.hxx b/include/pza/core/interface.hxx
index 5463c03..b0f19e5 100644
--- a/include/pza/core/interface.hxx
+++ b/include/pza/core/interface.hxx
@@ -11,10 +11,17 @@
 struct itf_impl;
 class mqtt_service;
 class attribute;
-struct itf_info;
 
 namespace pza
 {
+struct itf_info
+{
+	std::string bench;
+	std::string device_name;
+	std::string name;
+	std::string type;
+};
+
 // Can't use the name "interface" because it's a reserved keyford for Windows in C++
 class itf_base
 {
diff --git a/include/pza/interfaces/bps_chan_ctrl.hxx b/include/pza/interfaces/bpc.hxx
similarity index 59%
rename from include/pza/interfaces/bps_chan_ctrl.hxx
rename to include/pza/interfaces/bpc.hxx
index 3347164..320daed 100644
--- a/include/pza/interfaces/bps_chan_ctrl.hxx
+++ b/include/pza/interfaces/bpc.hxx
@@ -4,19 +4,19 @@
 
 namespace pza::itf
 {
-class bps_chan_ctrl : public itf_base
+class bpc : public itf_base
 {
 public:
-	using s_ptr = std::shared_ptr<bps_chan_ctrl>;
-	using u_ptr = std::unique_ptr<bps_chan_ctrl>;
-	using w_ptr = std::weak_ptr<bps_chan_ctrl>;
+	using s_ptr = std::shared_ptr<bpc>;
+	using u_ptr = std::unique_ptr<bpc>;
+	using w_ptr = std::weak_ptr<bpc>;
 
-	explicit bps_chan_ctrl(mqtt_service *mqtt, itf_info &info);
-	bps_chan_ctrl(const bps_chan_ctrl &) = delete;
-	bps_chan_ctrl(bps_chan_ctrl &&) = delete;
-	bps_chan_ctrl &operator=(const bps_chan_ctrl &) = delete;
-	bps_chan_ctrl &operator=(bps_chan_ctrl &&) = delete;
-	~bps_chan_ctrl() override;
+	explicit bpc(mqtt_service *mqtt, itf_info &info);
+	bpc(const bpc &) = delete;
+	bpc(bpc &&) = delete;
+	bpc &operator=(const bpc &) = delete;
+	bpc &operator=(bpc &&) = delete;
+	~bpc() override;
 
 	int set_voltage(double volts);
 	int set_current(double amps);
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index e44163d..4ada899 100644
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -21,7 +21,7 @@ target_sources(${LIBRARY_NAME}
     interfaces/meter.cxx
     interfaces/voltmeter.cxx
     interfaces/ammeter.cxx
-    interfaces/bps_chan_ctrl.cxx
+    interfaces/bpc.cxx
 
     ${CMAKE_CURRENT_BINARY_DIR}/version.cxx
 )
diff --git a/source/core/client.cxx b/source/core/client.cxx
index 1d980e4..993ac5f 100644
--- a/source/core/client.cxx
+++ b/source/core/client.cxx
@@ -37,7 +37,7 @@ struct client_impl : mqtt_service {
 	int disconnect();
 	bool is_connected() const
 	{
-		return (_paho_client->is_connected());
+		return _paho_client->is_connected();
 	}
 
 	const std::string &get_addr() const
@@ -157,12 +157,15 @@ int client_impl::connect()
 	connOpts.set_keep_alive_interval(interval);
 	connOpts.set_clean_session(true);
 
-	if (_paho_client->connect(connOpts)->wait_for(std::chrono::milliseconds(_conn_timeout)) == false) {
-		spdlog::error("failed to connect to client: {}", _id);
+	try {
+		_paho_client->connect(connOpts)->wait_for(std::chrono::milliseconds(_conn_timeout));
+	}
+	catch (const mqtt::exception &exc) {
+		spdlog::error("Client {} failed to connect on {}:{}", _id, _addr, _port);
 		return -1;
 	}
 
-	spdlog::info("connected to {}", _addr);
+	spdlog::info("connected to {}:{}", _addr, _port);
 	return 0;
 }
 
@@ -170,8 +173,11 @@ int client_impl::disconnect()
 {
 	spdlog::debug("Attempting to disconnect from {}...", _addr);
 
-	if (_paho_client->disconnect()->wait_for(std::chrono::milliseconds(_conn_timeout)) == false) {
-		spdlog::error("failed to disconnect from client: {}", _id);
+	try {
+		_paho_client->disconnect()->wait_for(std::chrono::milliseconds(_conn_timeout));
+	}
+	catch (const mqtt::exception &exc) {
+		spdlog::error("Client {} failed to disconnect on {}:{}", _id, _addr, _port);
 		return -1;
 	}
 	spdlog::info("disconnected from {}", _addr);
@@ -190,8 +196,11 @@ int client_impl::publish(const std::string &topic, const std::string &payload)
 
 int client_impl::publish(mqtt::const_message_ptr msg)
 {
-	if (_paho_client->publish(msg)->wait_for(std::chrono::milliseconds(msg_timeout_default_ms)) == false) {
-		spdlog::error("failed to publish from client: {}", _id);
+	try {
+		_paho_client->publish(msg)->wait_for(std::chrono::milliseconds(msg_timeout_default_ms));
+	}
+	catch (const mqtt::exception &exc) {
+		spdlog::error("Client {} failed to publish", _id);
 		return -1;
 	}
 	spdlog::trace("published message {} to {}", msg->get_payload_str(), msg->get_topic());
@@ -204,11 +213,15 @@ int client_impl::subscribe(const std::string &topic, const std::function<void(mq
 
 	t = topic::regexify_topic(topic);
 	_listeners[t] = cb;
-	if (_paho_client->subscribe(topic, 0)->wait_for(std::chrono::seconds(_conn_timeout)) == false) {
-		spdlog::error("failed to subscribe to topic: {} on client {}", topic, _id);
+	try {
+		_paho_client->subscribe(topic, 0)->wait_for(std::chrono::seconds(_conn_timeout));
+	}
+	catch (const mqtt::exception &exc) {
+		spdlog::error("Client {} failed to subscribe to topic: {}", _id, topic);
 		_listeners.erase(t);
 		return -1;
 	}
+
 	spdlog::trace("subscribed to topic: {}", topic);
 	return 0;
 }
@@ -217,8 +230,11 @@ int client_impl::unsubscribe(const std::string &topic)
 {
 	std::string t;
 
-	if (_paho_client->unsubscribe(topic)->wait_for(std::chrono::seconds(_conn_timeout)) == false) {
-		spdlog::error("failed to unsubscribe from topic: {} on client {}", topic, _id);
+	try {
+		_paho_client->unsubscribe(topic)->wait_for(std::chrono::seconds(_conn_timeout));
+	}
+	catch (const mqtt::exception &exc) {
+		spdlog::error("Client {} failed to unsubscribe from topic: {}", _id, topic);
 		return -1;
 	}
 	spdlog::trace("unsubscribed from topic: {}", topic);
@@ -554,3 +570,16 @@ itf_base::s_ptr client::get_interface(const std::string &group, const std::strin
 		return nullptr;
 	return dev->get_interface(interface_name);
 }
+
+std::vector<itf_base::s_ptr> client::get_interfaces() const
+{
+	auto dev = _impl->get_devices();
+	std::vector<itf_base::s_ptr> ret;
+
+	for (auto const &elem : dev) {
+		auto itf = elem->get_interfaces();
+		ret.insert(ret.end(), itf.begin(), itf.end());
+	}
+
+	return ret;
+}
diff --git a/source/core/device.cxx b/source/core/device.cxx
index 5a97fbf..442b1f7 100644
--- a/source/core/device.cxx
+++ b/source/core/device.cxx
@@ -58,13 +58,15 @@ struct device_impl {
 	std::vector<itf_base::s_ptr> get_interfaces_in_group(const std::string &group, unsigned int index) const;
 	std::set<std::string> get_interface_groups() const;
 
+	size_t get_interface_groups_count() const;
+
 	std::vector<itf_base::s_ptr> get_interfaces() const;
 
 	struct device_info info;
 	std::unordered_map<std::string, std::string> interfaces_scanned;
 	itf::device::s_ptr device_interface = nullptr;
 
-	std::unordered_map<std::string, itf_base::s_ptr> interfaces;
+	std::map<std::string, itf_base::s_ptr> interfaces;
 };
 
 device_impl::device_impl(mqtt_service *mqtt, const struct device_info &info)
@@ -178,6 +180,11 @@ std::vector<itf_base::s_ptr> device_impl::get_interfaces() const
 	return vec;
 }
 
+size_t device_impl::get_interface_groups_count() const
+{
+	return get_interface_groups().size();
+}
+
 device::device(mqtt_service *mqtt, struct device_info &info)
     : _impl(std::make_unique<device_impl>(mqtt, info))
 {
@@ -281,3 +288,8 @@ std::vector<itf_base::s_ptr> device::get_interfaces() const
 {
 	return _impl->get_interfaces();
 }
+
+size_t device::get_interface_groups_count() const
+{
+	return _impl->get_interface_groups_count();
+}
diff --git a/source/core/interface.cxx b/source/core/interface.cxx
index 515e90a..722f165 100644
--- a/source/core/interface.cxx
+++ b/source/core/interface.cxx
@@ -16,7 +16,7 @@ static constexpr unsigned int attributes_timeout = 2;
 
 itf_impl::itf_impl(mqtt_service *mqtt, itf_info &info)
     : info(info),
-      topic_base("pza/" + info.group + "/" + info.device_name + "/" + info.name),
+      topic_base("pza/" + info.bench + "/" + info.device_name + "/" + info.name),
       topic_cmd(topic_base + "/cmds/set"),
       mqtt(mqtt)
 {
diff --git a/source/core/interface.hxx b/source/core/interface.hxx
index 8a2fd75..3ba6c69 100644
--- a/source/core/interface.hxx
+++ b/source/core/interface.hxx
@@ -10,13 +10,6 @@
 
 using namespace pza;
 
-struct itf_info {
-	std::string group;
-	std::string device_name;
-	std::string name;
-	std::string type;
-};
-
 struct itf_impl {
 	explicit itf_impl(mqtt_service *mqtt, itf_info &info);
 
diff --git a/source/core/interface_factory.cxx b/source/core/interface_factory.cxx
index dfb0a14..983f60b 100644
--- a/source/core/interface_factory.cxx
+++ b/source/core/interface_factory.cxx
@@ -3,7 +3,7 @@
 #include <pza/core/device.hxx>
 
 #include <pza/interfaces/ammeter.hxx>
-#include <pza/interfaces/bps_chan_ctrl.hxx>
+#include <pza/interfaces/bpc.hxx>
 #include <pza/interfaces/device.hxx>
 #include <pza/interfaces/platform.hxx>
 #include <pza/interfaces/voltmeter.hxx>
@@ -18,7 +18,7 @@ static const std::unordered_map<std::string, interface_factory::factory_function
     {"platform", allocate_interface<itf::platform>},
     {"ammeter", allocate_interface<itf::ammeter>},
     {"voltmeter", allocate_interface<itf::voltmeter>},
-    {"bpc", allocate_interface<itf::bps_chan_ctrl>}};
+    {"bpc", allocate_interface<itf::bpc>}};
 
 itf_base::s_ptr interface_factory::create_interface(mqtt_service *mqtt, const std::string &group,
 						    const std::string &device_name, const std::string &name,
@@ -27,7 +27,7 @@ itf_base::s_ptr interface_factory::create_interface(mqtt_service *mqtt, const st
 	itf_info info;
 
 	info.name = name;
-	info.group = group;
+	info.bench = group;
 	info.device_name = device_name;
 	info.type = type;
 
diff --git a/source/interfaces/bps_chan_ctrl.cxx b/source/interfaces/bpc.cxx
similarity index 66%
rename from source/interfaces/bps_chan_ctrl.cxx
rename to source/interfaces/bpc.cxx
index 5be7ac1..23901f0 100644
--- a/source/interfaces/bps_chan_ctrl.cxx
+++ b/source/interfaces/bpc.cxx
@@ -1,10 +1,10 @@
-#include <pza/interfaces/bps_chan_ctrl.hxx>
+#include <pza/interfaces/bpc.hxx>
 
 #include "../core/interface.hxx"
 
 using namespace pza::itf;
 
-bps_chan_ctrl::bps_chan_ctrl(mqtt_service *mqtt, itf_info &info)
+bpc::bpc(mqtt_service *mqtt, itf_info &info)
     : itf_base(mqtt, info)
 {
 	_enable = std::make_shared<attribute>("enable");
@@ -26,15 +26,15 @@ bps_chan_ctrl::bps_chan_ctrl(mqtt_service *mqtt, itf_info &info)
 	_impl->register_attributes({_enable, _voltage, _current});
 }
 
-bps_chan_ctrl::~bps_chan_ctrl() = default;
+bpc::~bpc() = default;
 
-int bps_chan_ctrl::set_voltage(double volts)
+int bpc::set_voltage(double volts)
 {
 	auto min = _voltage->get_field<double>("min");
 	auto max = _voltage->get_field<double>("max");
 
 	if (volts < min || volts > max) {
-		spdlog::error("bps_chan_ctrl::set_voltage: voltage out of "
+		spdlog::error("bpc::set_voltage: voltage out of "
 			      "range, min: {}, max: {}, value: {}",
 			      min, max, volts);
 		return -1;
@@ -42,13 +42,13 @@ int bps_chan_ctrl::set_voltage(double volts)
 	return _voltage->set_field<double>("value", volts);
 }
 
-int bps_chan_ctrl::set_current(double amps)
+int bpc::set_current(double amps)
 {
 	auto min = _current->get_field<double>("min");
 	auto max = _current->get_field<double>("max");
 
 	if (amps < min || amps > max) {
-		spdlog::error("bps_chan_ctrl::set_current: current out of "
+		spdlog::error("bpc::set_current: current out of "
 			      "range, min: {}, max: {}, value: {}",
 			      min, max, amps);
 		return -1;
@@ -56,62 +56,62 @@ int bps_chan_ctrl::set_current(double amps)
 	return _current->set_field<double>("value", amps);
 }
 
-int bps_chan_ctrl::set_enable(bool enable)
+int bpc::set_enable(bool enable)
 {
 	return _enable->set_field<bool>("value", enable);
 }
 
-bool bps_chan_ctrl::get_enable()
+bool bpc::get_enable()
 {
 	return _enable->get_field<bool>("value");
 }
 
-double bps_chan_ctrl::get_min_voltage()
+double bpc::get_min_voltage()
 {
 	return _voltage->get_field<double>("min");
 }
 
-double bps_chan_ctrl::get_max_voltage()
+double bpc::get_max_voltage()
 {
 	return _voltage->get_field<double>("max");
 }
 
-double bps_chan_ctrl::get_min_current()
+double bpc::get_min_current()
 {
 	return _current->get_field<double>("min");
 }
 
-double bps_chan_ctrl::get_max_current()
+double bpc::get_max_current()
 {
 	return _current->get_field<double>("max");
 }
 
-double bps_chan_ctrl::get_preset_voltage()
+double bpc::get_preset_voltage()
 {
 	return _voltage->get_field<double>("value");
 }
 
-double bps_chan_ctrl::get_preset_current()
+double bpc::get_preset_current()
 {
 	return _current->get_field<double>("value");
 }
 
-unsigned int bps_chan_ctrl::get_num_decimals_voltage()
+unsigned int bpc::get_num_decimals_voltage()
 {
 	return _voltage->get_field<unsigned int>("decimals");
 }
 
-unsigned int bps_chan_ctrl::get_num_decimals_current()
+unsigned int bpc::get_num_decimals_current()
 {
 	return _current->get_field<unsigned int>("decimals");
 }
 
-void bps_chan_ctrl::register_enable_callback(const std::function<void()> &callback)
+void bpc::register_enable_callback(const std::function<void()> &callback)
 {
 	_enable->register_callback(callback);
 }
 
-void bps_chan_ctrl::remove_enable_callback(const std::function<void()> &callback)
+void bpc::remove_enable_callback(const std::function<void()> &callback)
 {
 	_enable->remove_callback(callback);
 }