diff --git a/README.md b/README.md
index de2dbbf..4f459fa 100644
--- a/README.md
+++ b/README.md
@@ -72,6 +72,29 @@ Get current connection status.
}
```
+### GET /api/devices
+List available Jura devices.
+
+**Response:**
+```json
+{
+ "success": true,
+ "count": 3,
+ "devices": [
+ {
+ "address": "AA:BB:CC:DD:EE:01",
+ "name": "Jura Coffee Maker",
+ "type": "jura"
+ },
+ {
+ "address": "AA:BB:CC:DD:EE:02",
+ "name": "Jura Coffee Maker",
+ "type": "jura"
+ }
+ ]
+}
+```
+
### POST /api/connect
Connect to a Jura device.
@@ -154,6 +177,11 @@ Get information about the connected device.
### Using curl
+List available devices:
+```bash
+curl http://localhost:8080/api/devices
+```
+
Connect to device:
```bash
curl -X POST http://localhost:8080/api/connect \
@@ -176,6 +204,11 @@ curl http://localhost:8080/api/status
### Using JavaScript/Fetch
```javascript
+// List available devices
+fetch('http://localhost:8080/api/devices')
+ .then(res => res.json())
+ .then(data => console.log(data));
+
// Connect to device
fetch('http://localhost:8080/api/connect', {
method: 'POST',
diff --git a/example-client.html b/example-client.html
index b5ef96e..378be3c 100644
--- a/example-client.html
+++ b/example-client.html
@@ -66,6 +66,7 @@
☕ Jura Coffee Maker API Client
Connection
+
@@ -119,6 +120,11 @@ Custom Command
}
}
+ async function listDevices() {
+ const result = await apiCall('/api/devices');
+ document.getElementById('connectionResponse').textContent = JSON.stringify(result, null, 2);
+ }
+
async function connect() {
const deviceAddress = document.getElementById('deviceAddress').value;
const result = await apiCall('/api/connect', 'POST', { device_address: deviceAddress });
diff --git a/src/api_server.cpp b/src/api_server.cpp
index 4c97238..ead0bc1 100644
--- a/src/api_server.cpp
+++ b/src/api_server.cpp
@@ -43,6 +43,25 @@ ApiServer::ApiServer(int port)
res.set_content(response.dump(), "application/json");
});
+ // List devices endpoint
+ pImpl->server->Get("/api/devices", [this, setCorsHeaders](const httplib::Request&, httplib::Response& res) {
+ try {
+ json response = controller_->listDevices();
+ setCorsHeaders(res);
+ res.set_content(response.dump(), "application/json");
+ } catch (const std::exception& e) {
+ json response = {
+ {"success", false},
+ {"error", e.what()},
+ {"devices", json::array()},
+ {"count", 0}
+ };
+ setCorsHeaders(res);
+ res.status = 500;
+ res.set_content(response.dump(), "application/json");
+ }
+ });
+
// Connect to device endpoint
pImpl->server->Post("/api/connect", [this, setCorsHeaders](const httplib::Request& req, httplib::Response& res) {
try {
@@ -172,6 +191,11 @@ ApiServer::ApiServer(int port)
{"method", "GET"},
{"description", "Get current connection status"}
},
+ {
+ {"path", "/api/devices"},
+ {"method", "GET"},
+ {"description", "List available Jura devices"}
+ },
{
{"path", "/api/connect"},
{"method", "POST"},
diff --git a/src/jura_controller.cpp b/src/jura_controller.cpp
index 9d153f3..e9eb528 100644
--- a/src/jura_controller.cpp
+++ b/src/jura_controller.cpp
@@ -34,6 +34,38 @@ bool JuraController::isConnected() const {
return pImpl->protocol->isConnected();
}
+nlohmann::json JuraController::listDevices() {
+ nlohmann::json result;
+
+ try {
+ std::vector devices = pImpl->protocol->listDevices();
+
+ // Filter to only include Jura devices
+ // In a real implementation, this would check device names,
+ // service UUIDs, or other characteristics to identify Jura devices
+ nlohmann::json deviceList = nlohmann::json::array();
+
+ for (const auto& deviceAddress : devices) {
+ nlohmann::json device;
+ device["address"] = deviceAddress;
+ device["name"] = "Jura Coffee Maker"; // In production, query actual device name
+ device["type"] = "jura";
+ deviceList.push_back(device);
+ }
+
+ result["success"] = true;
+ result["devices"] = deviceList;
+ result["count"] = deviceList.size();
+ } catch (const std::exception& e) {
+ result["success"] = false;
+ result["error"] = e.what();
+ result["devices"] = nlohmann::json::array();
+ result["count"] = 0;
+ }
+
+ return result;
+}
+
nlohmann::json JuraController::getStatus() {
nlohmann::json status;
status["connected"] = pImpl->protocol->isConnected();
diff --git a/src/jura_controller.h b/src/jura_controller.h
index f952814..3dfb48c 100644
--- a/src/jura_controller.h
+++ b/src/jura_controller.h
@@ -18,6 +18,9 @@ class JuraController {
bool connect(const std::string& device_address);
bool disconnect();
bool isConnected() const;
+
+ // Device discovery
+ nlohmann::json listDevices();
// Coffee maker commands
nlohmann::json getStatus();
diff --git a/src/jura_protocol.cpp b/src/jura_protocol.cpp
index 73dd8e4..739c237 100644
--- a/src/jura_protocol.cpp
+++ b/src/jura_protocol.cpp
@@ -75,6 +75,30 @@ bool JuraProtocol::isConnected() const {
return connected_;
}
+std::vector JuraProtocol::listDevices() {
+ // TODO: Actual device scanning using protocol-bt-cpp
+ // This would use BLE scanning to discover nearby Bluetooth devices
+ // and filter for devices that match Jura device characteristics
+
+ std::cout << "Scanning for Jura devices..." << std::endl;
+
+ // Simulate device discovery
+ // In production, this would:
+ // 1. Scan for BLE devices
+ // 2. Filter by service UUIDs or device names matching Jura devices
+ // 3. Return list of device addresses
+
+ std::vector devices = {
+ "AA:BB:CC:DD:EE:01", // Simulated Jura device 1
+ "AA:BB:CC:DD:EE:02", // Simulated Jura device 2
+ "AA:BB:CC:DD:EE:03" // Simulated Jura device 3
+ };
+
+ std::cout << "Found " << devices.size() << " Jura device(s)" << std::endl;
+
+ return devices;
+}
+
std::string JuraProtocol::sendCommand(const std::string& command) {
if (!connected_) {
return "ERROR: Not connected";
diff --git a/src/jura_protocol.h b/src/jura_protocol.h
index a4f255d..d17b75e 100644
--- a/src/jura_protocol.h
+++ b/src/jura_protocol.h
@@ -20,6 +20,9 @@ class JuraProtocol {
bool connectDevice(const std::string& device_address);
bool disconnectDevice();
bool isConnected() const;
+
+ // Device discovery
+ std::vector listDevices();
// Protocol commands
std::string sendCommand(const std::string& command);
diff --git a/test-api.sh b/test-api.sh
index f1234c7..91fccdc 100755
--- a/test-api.sh
+++ b/test-api.sh
@@ -40,6 +40,7 @@ test_endpoint() {
test_endpoint "Health Check" "GET" "/health" ""
test_endpoint "API Documentation" "GET" "/api" ""
test_endpoint "Initial Status" "GET" "/api/status" ""
+test_endpoint "List Devices" "GET" "/api/devices" ""
test_endpoint "Connect to Device" "POST" "/api/connect" '{"device_address":"AA:BB:CC:DD:EE:FF"}'
test_endpoint "Status After Connection" "GET" "/api/status" ""
test_endpoint "Device Info" "GET" "/api/device-info" ""