/// <summary> /// Creates a new HomieColor from an RGB string. /// </summary> public static HomieColor FromRgbString(string rgbString) { HomieColor returnColor; if (ValidatePayload(rgbString, ColorFormat.Rgb)) { returnColor = new HomieColor(); var colorParts = rgbString.Split(','); returnColor.RedValue = int.Parse(colorParts[0]); returnColor.GreenValue = int.Parse(colorParts[1]); returnColor.BlueValue = int.Parse(colorParts[2]); } else { returnColor = new HomieColor(); } return(returnColor); }
private void SetValue(HomieColor valueToSet) { switch (Type) { case PropertyType.Parameter: case PropertyType.Command: if (_colorFormat == ColorFormat.Rgb) { _rawValue = valueToSet.ToRgbString(); } else { _rawValue = valueToSet.ToHsvString(); } _parentDevice.InternalPropertyPublish($"{_propertyId}/set", _rawValue, false); break; case PropertyType.State: throw new InvalidOperationException(); } }
protected override bool ValidatePayload(string payloadToValidate) { var areNumbersGood = HomieColor.ValidatePayload(payloadToValidate, _colorFormat); return(areNumbersGood); }
/// <summary> /// Creates a new HomieColor from an HSV string. /// </summary> public static HomieColor FromHsvString(string hsvString) { HomieColor returnColor; if (ValidatePayload(hsvString, ColorFormat.Hsv)) { returnColor = new HomieColor(); var colorParts = hsvString.Split(','); var hue = int.Parse(colorParts[0]); var saturation = int.Parse(colorParts[1]) / 100.0; var value = int.Parse(colorParts[2]) / 100.0; // Took conversion from Wikipedia https://en.wikipedia.org/wiki/HSL_and_HSV var chroma = saturation * value; var hPrime = hue / 60.0; var x = chroma * (1 - Math.Abs(hPrime % 2 - 1)); var redPrime = 0.0; var greenPrime = 0.0; var bluePrime = 0.0; if (hPrime <= 1) { redPrime = chroma; greenPrime = x; bluePrime = 0; } else if (hPrime <= 2) { redPrime = x; greenPrime = chroma; bluePrime = 0; } else if (hPrime <= 3) { redPrime = 0; greenPrime = chroma; bluePrime = x; } else if (hPrime <= 4) { redPrime = 0; greenPrime = x; bluePrime = chroma; } else if (hPrime <= 5) { redPrime = x; greenPrime = 0; bluePrime = chroma; } else if (hPrime <= 6) { redPrime = chroma; greenPrime = 0; bluePrime = x; } var m = value - chroma; returnColor.RedValue = (redPrime + m) * 255; returnColor.GreenValue = (greenPrime + m) * 255; returnColor.BlueValue = (bluePrime + m) * 255; } else { returnColor = new HomieColor(); } return(returnColor); }
public bool ValidateAndFix(ref ArrayList errorList, ref ArrayList warningList) { var isOk = true; if ((PropertyType == PropertyType.Command) && (InitialValue != "")) { warningList.Add($"{NodeId}/{PropertyId} property type is Command, but it has initial value set. Clearing it."); InitialValue = ""; } var isNotCommand = PropertyType != PropertyType.Command; switch (DataType) { case DataType.String: // String type has pretty much no restriction to attributes content. break; case DataType.Integer: case DataType.Float: // Trying to convert integer to float. Later, float validation will simply run on this converted property. if (DataType == DataType.Integer) { if (isNotCommand && (Helpers.IsInteger(InitialValue) == false)) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, which is not a valid initial value for integer data type. Skipping this property entirely."); isOk = false; } if (isOk) { warningList.Add($"{NodeId}/{PropertyId} is originally of type integer, but it will now be converted to float."); Tags.Add("Precision", "0"); DataType = DataType.Float; } } if (isNotCommand && (Helpers.IsFloat(InitialValue) == false)) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, which is not a valid initial value for float data type. Skipping this property entirely."); isOk = false; } break; case DataType.Boolean: case DataType.Enum: // Trying to convert boolean type to enum. Later, enum validation will simply run on this converted property. if (DataType == DataType.Boolean) { if (isNotCommand && (Helpers.TryParseBool(InitialValue, out _) == false)) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, which is not a valid initial value for boolean data type. Skipping this property entirely."); isOk = false; } if (isOk) { warningList.Add($"{NodeId}/{PropertyId} is originally of type boolean, but it will now be converted to enum."); Format = "false,true"; DataType = DataType.Enum; if (Unit != "") { warningList.Add($"{NodeId}/{PropertyId}/$unit attribute is {Unit}. Should be empty for boolean data type. Clearing it."); Unit = ""; } } } // From here, the save procedure will run on both enum and (former) boolean properties. if (Format == "") { errorList.Add($"{NodeId}/{PropertyId}/$format attribute is empty, which is not valid for enum data type. Skipping this property entirely."); isOk = false; } var options = Format.Split(','); if (isOk) { if (options.Length < 2) { errorList.Add($"{NodeId}/{PropertyId}/$format attribute contains less than two option. Skipping this property entirely."); isOk = false; } } if (isOk) { var isInitialValueCorrect = false; foreach (var option in options) { if (InitialValue == option) { isInitialValueCorrect = true; } } if (isNotCommand && (isInitialValueCorrect == false)) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, while it should be one of {Format}. Skipping this property entirely."); isOk = false; } } break; case DataType.Color: if (Format == "") { errorList.Add($"{NodeId}/{PropertyId}/$format attribute is empty, which is not valid for color data type. Skipping this property entirely."); isOk = false; } if (isOk) { if (Helpers.TryParseHomieColorFormat(Format, out var colorFormat) == false) { errorList.Add($"{NodeId}/{PropertyId}/$format attribute is {Format}, which is not valid for color data type. Skipping this property entirely."); isOk = false; } else if (isNotCommand) { if (HomieColor.ValidatePayload(InitialValue, colorFormat) == false) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, which is not valid for color format {colorFormat}. Skipping this property entirely."); isOk = false; } } } break; case DataType.DateTime: if (isNotCommand && (Helpers.TryParseDateTime(InitialValue, out var _) == false)) { errorList.Add($"{NodeId}/{PropertyId} is set to {InitialValue}, which is not a valid initial value for datetime data type. Skipping this property entirely."); isOk = false; } if (Unit != "") { warningList.Add($"{NodeId}/{PropertyId}/$unit attribute is {Unit}. Should be empty for datetime data type. Clearing it."); Unit = ""; } if (Format != "") { warningList.Add($"{NodeId}/{PropertyId}/$format attribute is {Unit}. Should be empty for datetime data type. Clearing it."); Format = ""; } break; case DataType.Duration: errorList.Add($"{NodeId}/{PropertyId} is of type {DataType}, but this is not currently supported by YAHI. Skipping this property entirely."); isOk = false; break; } return(isOk); }