diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp
index 8f1c3a9cd55cdb4b75e5cd223d0b7b60a9c32d2e..8d1b46c75208ecba8f0ff6edde83f73e7836e6d0 100644
--- a/applications/vision/src/main.cpp
+++ b/applications/vision/src/main.cpp
@@ -135,14 +135,12 @@ static void run(ftl::Configurable *root) {
 		}
 	}
 
-	Source *source = nullptr;
-	source = ftl::create<Source>(root, "source", net);
 	if (file != "") {
-		//source->set("uri", file);
 		ftl::URI uri(file);
-		uri.to_json(source->getConfig());
-		source->set("uri", uri.getBaseURI());
+		uri.to_json(root->getConfig()["source"]);
 	}
+	Source *source = nullptr;
+	source = ftl::create<Source>(root, "source", net);
 	
 	ftl::stream::Sender *sender = ftl::create<ftl::stream::Sender>(root, "sender");
 	ftl::stream::Net *outstream = ftl::create<ftl::stream::Net>(root, "stream", net);
diff --git a/components/common/cpp/src/uri.cpp b/components/common/cpp/src/uri.cpp
index 71b6e195d401f55c53b054c80820daa063c62b17..fdb8e046ca4a5d13652a4acc208bb9b5ba3bbed8 100644
--- a/components/common/cpp/src/uri.cpp
+++ b/components/common/cpp/src/uri.cpp
@@ -2,7 +2,7 @@
 #include <nlohmann/json.hpp>
 // #include <filesystem>  TODO When available
 #include <cstdlib>
-//#include <loguru.hpp>
+#include <loguru.hpp>
 
 #ifndef WIN32
 #include <unistd.h>
@@ -210,14 +210,18 @@ void URI::to_json(nlohmann::json &json) {
 		size_t pos = 0;
 		size_t lpos = 0;
 		while ((pos = i.first.find('/', lpos)) != std::string::npos) {
-			current = &((*current)[i.first.substr(lpos, pos-lpos)]);
+			std::string subobj = i.first.substr(lpos, pos-lpos);
+			current = &((*current)[subobj]);
 			lpos = pos+1;
 		}
+
+		std::string obj = i.first.substr(lpos);
+
 		auto p = nlohmann::json::parse(i.second, nullptr, false);
 		if (!p.is_discarded()) {
-			(*current)[i.first.substr(lpos)] = p;
+			(*current)[obj] = p;
 		} else {
-			(*current)[i.first.substr(lpos)] = i.second;
+			(*current)[obj] = i.second;
 		}
 	}
 }
diff --git a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
index 7bec885a7d6276faaf92a0094a598845b82a1cf7..2cdb05277081cc745e6dff28e1bbfa1e56e92a46 100644
--- a/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
+++ b/components/rgbd-sources/src/sources/stereovideo/pylon.cpp
@@ -11,6 +11,8 @@
 
 #include <opencv2/imgproc.hpp>
 
+#include <nlohmann/json.hpp>
+
 using ftl::rgbd::detail::PylonDevice;
 using std::string;
 using ftl::codecs::Channel;
@@ -26,22 +28,45 @@ PylonDevice::PylonDevice(nlohmann::json &config)
 	Pylon::DeviceInfoList_t devices;
 	inst.EnumerateDevices(devices);
 
+	int dev_left_num = 0;
+	std::string dev_left;
+
+	if (getConfig()["device_left"].is_number()) {
+		dev_left = std::to_string(value("device_left",0));
+	} else {
+		dev_left = value("device_left", std::string("default"));
+	}
+
+	LOG(INFO) << "DEVICE LEFT: " << dev_left;
+
 	if (devices.size() == 0) {
 		LOG(ERROR) << "No Pylon devices attached";
 		return;
 	} else {
+		int i=0;
 		for (auto d : devices) {
-			LOG(INFO) << " - found Pylon device - " << d.GetFullName() << "(" << d.GetModelName() << ")";
+			if (std::string(d.GetSerialNumber()) == dev_left) {
+				dev_left_num = i;
+			}
+
+			if (dev_left_num == i) {
+				LOG(INFO) << " - found Pylon device - " << d.GetSerialNumber() << "(" << d.GetModelName() << ") [primary]";
+			} else {
+				LOG(INFO) << " - found Pylon device - " << d.GetSerialNumber() << "(" << d.GetModelName() << ")";
+			}
+
+			++i;
 		}
 	}
 
 	try {
-    	lcam_ = new CBaslerUniversalInstantCamera( CTlFactory::GetInstance().CreateDevice(devices[0]));
+    	lcam_ = new CBaslerUniversalInstantCamera( CTlFactory::GetInstance().CreateDevice(devices[dev_left_num]));
 		lcam_->RegisterConfiguration( new Pylon::CSoftwareTriggerConfiguration, Pylon::RegistrationMode_ReplaceAll, Pylon::Cleanup_Delete);
 		lcam_->Open();
 
 		if (devices.size() >= 2) {
-			rcam_ = new CBaslerUniversalInstantCamera( CTlFactory::GetInstance().CreateDevice(devices[1]));
+			int dev_right = (dev_left_num == 0) ? 1 : 0;
+			rcam_ = new CBaslerUniversalInstantCamera( CTlFactory::GetInstance().CreateDevice(devices[dev_right]));
 			rcam_->RegisterConfiguration( new Pylon::CSoftwareTriggerConfiguration, Pylon::RegistrationMode_ReplaceAll, Pylon::Cleanup_Delete);
 			rcam_->Open();
 		}