mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Cololight Improvements (#1120)
* Avoid issue with long running identify calls * Strip provides number of LEDs now * Consider that Strip was cut by user
This commit is contained in:
		| @@ -470,6 +470,8 @@ async function requestLedDeviceProperties(type, params) | ||||
|  | ||||
| function requestLedDeviceIdentification(type, params) | ||||
| { | ||||
| 	sendToHyperion("leddevice", "identify", '"ledDeviceType": "'+type+'","params": '+JSON.stringify(params)+''); | ||||
|     //sendToHyperion("leddevice", "identify", '"ledDeviceType": "'+type+'","params": '+JSON.stringify(params)+''); | ||||
|     let data = { ledDeviceType: type, params: params }; | ||||
|     return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000)); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -826,9 +826,17 @@ async function getProperties_hue_bridge(hostAddress, username, resourceFilter) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_hue_device(hostAddress, username, id) { | ||||
| async function identify_hue_device(hostAddress, username, id) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { host: hostAddress, user: username, lightId: id }; | ||||
|   requestLedDeviceIdentification("philipshue", params); | ||||
|   const res = await requestLedDeviceIdentification('philipshue', params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   }  | ||||
| } | ||||
|  | ||||
| function getHueIPs() { | ||||
| @@ -1289,9 +1297,17 @@ async function getProperties_wled(hostAddress, resourceFilter) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_wled(hostAddress) { | ||||
| async function identify_wled(hostAddress) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { host: hostAddress }; | ||||
|   requestLedDeviceIdentification("wled", params); | ||||
|   const res = await requestLedDeviceIdentification('wled', params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   } | ||||
| } | ||||
|  | ||||
| //**************************** | ||||
| @@ -1538,9 +1554,17 @@ async function getProperties_yeelight(hostname, port) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_yeelight_device(hostname, port) { | ||||
| async function identify_yeelight_device(hostname, port) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { hostname: hostname, port: port }; | ||||
|   requestLedDeviceIdentification("yeelight", params); | ||||
|   const res = await requestLedDeviceIdentification("yeelight", params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   } | ||||
| } | ||||
|  | ||||
| //**************************** | ||||
| @@ -1774,9 +1798,17 @@ function assign_atmoorb_lights() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_atmoorb_device(orbId) { | ||||
| async function identify_atmoorb_device(orbId) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { id: orbId }; | ||||
|   requestLedDeviceIdentification("atmoorb", params); | ||||
|   const res = await requestLedDeviceIdentification("atmoorb", params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   } | ||||
| } | ||||
|  | ||||
| //**************************** | ||||
| @@ -1823,9 +1855,17 @@ async function getProperties_nanoleaf(hostAddress, authToken, resourceFilter) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_nanoleaf(hostAddress, authToken) { | ||||
| async function identify_nanoleaf(hostAddress, authToken) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { host: hostAddress, token: authToken }; | ||||
|   requestLedDeviceIdentification("nanoleaf", params); | ||||
|   const res = await requestLedDeviceIdentification('nanoleaf', params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   } | ||||
| } | ||||
|  | ||||
| //**************************** | ||||
| @@ -1890,15 +1930,13 @@ function beginWizardCololight() { | ||||
|       d.host = lights[selectedLightId].ip; | ||||
|     } | ||||
|  | ||||
|     var coloLightProperties = lights[selectedLightId].props; | ||||
|     var coloLightProperties = lights[selectedLightId].props.properties; | ||||
|     if (Object.keys(coloLightProperties).length === 0) { | ||||
|       alert($.i18n('wiz_cololight_noprops')); | ||||
|       d.hardwareLedCount = 1; | ||||
|     } else { | ||||
|       if (coloLightProperties.ledCount > 0) { | ||||
|     } | ||||
|     else { | ||||
|         d.hardwareLedCount = coloLightProperties.ledCount; | ||||
|       } else if (coloLightProperties.modelType === "Strip") | ||||
|         d.hardwareLedCount = 120; | ||||
|     } | ||||
|  | ||||
|     d.colorOrder = conf_editor.getEditor("root.generalOptions.colorOrder").getValue(); | ||||
| @@ -2011,9 +2049,17 @@ async function getProperties_cololight(ip) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| function identify_cololight_device(hostAddress) { | ||||
| async function identify_cololight_device(hostAddress) { | ||||
|  | ||||
|   // Take care that new record cannot be save during background process | ||||
|   $('#btn_wiz_save').attr('disabled', true); | ||||
|  | ||||
|   let params = { host: hostAddress }; | ||||
|   requestLedDeviceIdentification("cololight", params); | ||||
|   const res = await requestLedDeviceIdentification('cololight', params); | ||||
|  | ||||
|   if (!window.readOnlyMode) { | ||||
|     $('#btn_wiz_save').attr('disabled', false);   | ||||
|   } | ||||
| } | ||||
|  | ||||
| //**************************** | ||||
|   | ||||
| @@ -17,6 +17,8 @@ const bool verbose3 = false; | ||||
|  | ||||
| const char CONFIG_HW_LED_COUNT[] = "hardwareLedCount"; | ||||
|  | ||||
| const int COLOLIGHT_BEADS_PER_MODULE = 19; | ||||
|  | ||||
| // Cololight discovery service | ||||
|  | ||||
| const int API_DEFAULT_PORT = 8900; | ||||
| @@ -24,7 +26,7 @@ const int API_DEFAULT_PORT = 8900; | ||||
| const char DISCOVERY_ADDRESS[] = "255.255.255.255"; | ||||
| const quint16 DISCOVERY_PORT = 12345; | ||||
| const char DISCOVERY_MESSAGE[] = "Z-SEARCH * \r\n"; | ||||
| constexpr std::chrono::milliseconds DEFAULT_DISCOVERY_TIMEOUT{ 5000 }; | ||||
| constexpr std::chrono::milliseconds DEFAULT_DISCOVERY_TIMEOUT{ 2000 }; | ||||
| constexpr std::chrono::milliseconds DEFAULT_READ_TIMEOUT{ 1000 }; | ||||
| constexpr std::chrono::milliseconds DEFAULT_IDENTIFY_TIME{ 2000 }; | ||||
|  | ||||
| @@ -34,16 +36,12 @@ const char COLOLIGHT_MAC[] = "sn"; | ||||
| const char COLOLIGHT_NAME[] = "name"; | ||||
|  | ||||
| const char COLOLIGHT_MODEL_IDENTIFIER[] = "OD_WE_QUAN"; | ||||
|  | ||||
| const int COLOLIGHT_BEADS_PER_MODULE = 19; | ||||
| const int COLOLIGHT_MIN_STRIP_SEGMENT_SIZE = 30; | ||||
|  | ||||
| } //End of constants | ||||
|  | ||||
| LedDeviceCololight::LedDeviceCololight(const QJsonObject& deviceConfig) | ||||
| 	: ProviderUdp(deviceConfig) | ||||
| 	  , _modelType(-1) | ||||
| 	  , _ledLayoutType(STRIP_LAYOUT) | ||||
| 	  , _ledLayoutType(-1) | ||||
| 	  , _ledBeadCount(0) | ||||
| 	  , _distance(0) | ||||
| 	  , _sequenceNumber(1) | ||||
| @@ -94,11 +92,11 @@ bool LedDeviceCololight::initLedsConfiguration() | ||||
| 		QString modelTypeText; | ||||
|  | ||||
| 		switch (_modelType) { | ||||
| 		case 0: | ||||
| 		case STRIP: | ||||
| 			modelTypeText = "Strip"; | ||||
| 			_ledLayoutType = STRIP_LAYOUT; | ||||
| 			break; | ||||
| 		case 1: | ||||
| 		case PLUS: | ||||
| 			_ledLayoutType = MODLUE_LAYOUT; | ||||
| 			modelTypeText = "Plus"; | ||||
| 			break; | ||||
| @@ -116,33 +114,24 @@ bool LedDeviceCololight::initLedsConfiguration() | ||||
| 			setLedCount(_devConfig[CONFIG_HW_LED_COUNT].toInt(0)); | ||||
| 		} | ||||
|  | ||||
| 		if (_modelType == STRIP && (getLedCount() % COLOLIGHT_MIN_STRIP_SEGMENT_SIZE != 0)) | ||||
| 		Debug(_log, "LedCount     : %d", getLedCount()); | ||||
|  | ||||
| 		int configuredLedCount = _devConfig["currentLedCount"].toInt(1); | ||||
|  | ||||
| 		if (getLedCount() < configuredLedCount) | ||||
| 		{ | ||||
| 			QString errorReason = QString("Hardware LED count must be multiple of %1 for Cololight Strip!") | ||||
| 									  .arg(COLOLIGHT_MIN_STRIP_SEGMENT_SIZE); | ||||
| 			QString errorReason = QString("Not enough LEDs [%1] for configured LEDs in layout [%2] found!") | ||||
| 									  .arg(getLedCount()) | ||||
| 									  .arg(configuredLedCount); | ||||
| 			this->setInError(errorReason); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			Debug(_log, "LedCount     : %d", getLedCount()); | ||||
|  | ||||
| 			int configuredLedCount = _devConfig["currentLedCount"].toInt(1); | ||||
|  | ||||
| 			if (getLedCount() < configuredLedCount) | ||||
| 			if (getLedCount() > configuredLedCount) | ||||
| 			{ | ||||
| 				QString errorReason = QString("Not enough LEDs [%1] for configured LEDs in layout [%2] found!") | ||||
| 										  .arg(getLedCount()) | ||||
| 										  .arg(configuredLedCount); | ||||
| 				this->setInError(errorReason); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				if (getLedCount() > configuredLedCount) | ||||
| 				{ | ||||
| 					Info(_log, "%s: More LEDs [%d] than configured LEDs in layout [%d].", QSTRING_CSTR(this->getActiveDeviceType()), getLedCount(), configuredLedCount); | ||||
| 				} | ||||
| 				isInitOK = true; | ||||
| 				Info(_log, "%s: More LEDs [%d] than configured LEDs in layout [%d].", QSTRING_CSTR(this->getActiveDeviceType()), getLedCount(), configuredLedCount); | ||||
| 			} | ||||
| 			isInitOK = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -204,22 +193,35 @@ bool LedDeviceCololight::getInfo() | ||||
| 			if (ledNum != 0xFFFF) | ||||
| 			{ | ||||
| 				_ledBeadCount = ledNum; | ||||
| 				// Cololight types are not identifyable currently | ||||
| 				// Work under the assumption that modules (Cololight Plus) have a number of beads and a Colologht Strip does not have a multiple of beads | ||||
| 				// The assumption will not hold true, if a user cuts the Strip to a multiple of beads... | ||||
| 				if (ledNum % COLOLIGHT_BEADS_PER_MODULE == 0) | ||||
| 				{ | ||||
| 					_modelType = MODLUE_LAYOUT; | ||||
| 					_modelType = PLUS; | ||||
| 					_ledLayoutType = MODLUE_LAYOUT; | ||||
| 					_distance = ledNum / COLOLIGHT_BEADS_PER_MODULE; | ||||
| 					setLedCount(_distance); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					_modelType = STRIP; | ||||
| 					_ledLayoutType = STRIP_LAYOUT; | ||||
| 					_distance = 0; | ||||
| 					setLedCount(ledNum); | ||||
| 				} | ||||
| 				isCmdOK = true; | ||||
| 				Debug(_log, "#LEDs found [0x%x], [%u], distance [%d]", _ledBeadCount, _ledBeadCount, _distance); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				_modelType = STRIP; | ||||
| 				_modelType = -1; | ||||
| 				_ledLayoutType = -1; | ||||
| 				_distance = 0; | ||||
| 				setLedCount(0); | ||||
| 				isCmdOK = false; | ||||
| 				Error(_log, "Number of LEDs cannot be resolved"); | ||||
| 			} | ||||
|  | ||||
| 			Debug(_log, "#LEDs found [0x%x], [%u], distance [%d]", _ledBeadCount, _ledBeadCount, _distance); | ||||
|  | ||||
| 			isCmdOK = true; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -545,20 +547,15 @@ bool LedDeviceCololight::powerOff() | ||||
| 	return off; | ||||
| } | ||||
|  | ||||
| QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/) | ||||
| QJsonArray LedDeviceCololight::discover() | ||||
| { | ||||
| 	QJsonObject devicesDiscovered; | ||||
| 	devicesDiscovered.insert("ledDeviceType", _activeDeviceType); | ||||
|  | ||||
| 	QJsonArray deviceList; | ||||
|  | ||||
| 	QUdpSocket udpSocket; | ||||
|  | ||||
| 	udpSocket.writeDatagram(QString(DISCOVERY_MESSAGE).toUtf8(), QHostAddress(DISCOVERY_ADDRESS), DISCOVERY_PORT); | ||||
|  | ||||
| 	if (udpSocket.waitForReadyRead(DEFAULT_DISCOVERY_TIMEOUT.count())) | ||||
| 	{ | ||||
| 		while (udpSocket.waitForReadyRead(500)) | ||||
| 		while (udpSocket.waitForReadyRead(200)) | ||||
| 		{ | ||||
| 			QByteArray datagram; | ||||
|  | ||||
| @@ -602,6 +599,7 @@ QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	QJsonArray deviceList; | ||||
| 	QMap<QString, QMap <QString, QString>>::iterator i; | ||||
| 	for (i = _services.begin(); i != _services.end(); ++i) | ||||
| 	{ | ||||
| @@ -647,9 +645,23 @@ QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/) | ||||
|  | ||||
| 		deviceList << obj; | ||||
| 	} | ||||
| 	return deviceList; | ||||
| } | ||||
|  | ||||
| QJsonObject LedDeviceCololight::discover(const QJsonObject& /*params*/) | ||||
| { | ||||
| 	QJsonObject devicesDiscovered; | ||||
| 	devicesDiscovered.insert("ledDeviceType", _activeDeviceType); | ||||
|  | ||||
| 	QString discoveryMethod("ssdp"); | ||||
| 	QJsonArray deviceList; | ||||
|  | ||||
| 	deviceList = discover(); | ||||
|  | ||||
| 	devicesDiscovered.insert("discoveryMethod", discoveryMethod); | ||||
| 	devicesDiscovered.insert("devices", deviceList); | ||||
| 	DebugIf(verbose, _log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); | ||||
|  | ||||
| 	//Debug(_log, "devicesDiscovered: [%s]", QString(QJsonDocument(devicesDiscovered).toJson(QJsonDocument::Compact)).toUtf8().constData()); | ||||
|  | ||||
| 	return devicesDiscovered; | ||||
| } | ||||
| @@ -662,6 +674,7 @@ QJsonObject LedDeviceCololight::getProperties(const QJsonObject& params) | ||||
| 	QString apiHostname = params["host"].toString(""); | ||||
| 	quint16 apiPort = static_cast<quint16>(params["port"].toInt(API_DEFAULT_PORT)); | ||||
|  | ||||
| 	QJsonObject propertiesDetails; | ||||
| 	if (!apiHostname.isEmpty()) | ||||
| 	{ | ||||
| 		QJsonObject deviceConfig; | ||||
| @@ -675,21 +688,26 @@ QJsonObject LedDeviceCololight::getProperties(const QJsonObject& params) | ||||
| 				QString modelTypeText; | ||||
|  | ||||
| 				switch (_modelType) { | ||||
| 				case 1: | ||||
| 				case STRIP: | ||||
| 					modelTypeText = "Strip"; | ||||
| 					break; | ||||
| 				case PLUS: | ||||
| 					modelTypeText = "Plus"; | ||||
| 					break; | ||||
| 				default: | ||||
| 					modelTypeText = "Strip"; | ||||
| 					break; | ||||
| 				} | ||||
| 				properties.insert("modelType", modelTypeText); | ||||
| 				properties.insert("ledCount", static_cast<int>(getLedCount())); | ||||
| 				properties.insert("ledBeadCount", _ledBeadCount); | ||||
| 				properties.insert("distance", _distance); | ||||
| 				propertiesDetails.insert("modelType", modelTypeText); | ||||
| 				propertiesDetails.insert("ledCount", static_cast<int>(getLedCount())); | ||||
| 				propertiesDetails.insert("ledBeadCount", _ledBeadCount); | ||||
| 				propertiesDetails.insert("distance", _distance); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	properties.insert("properties", propertiesDetails); | ||||
|  | ||||
| 	DebugIf(verbose, _log, "properties: [%s]", QString(QJsonDocument(properties).toJson(QJsonDocument::Compact)).toUtf8().constData()); | ||||
|  | ||||
| 	return properties; | ||||
|   | ||||
| @@ -284,6 +284,14 @@ private: | ||||
| 	/// | ||||
| 	bool readResponse(QByteArray& response); | ||||
|  | ||||
| 	/// | ||||
| 	/// @brief Discover Cololight devices available (for configuration). | ||||
| 	/// Cololight specific UDP Broadcast discovery | ||||
| 	/// | ||||
| 	/// @return A JSON structure holding a list of devices found | ||||
| 	/// | ||||
| 	QJsonArray discover(); | ||||
|  | ||||
| 	// Cololight model, e.g. CololightPlus, CololightStrip | ||||
| 	int _modelType; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user