public ControlResponse Control(ControlRequest alexaRequest) { //IPremiseObject PremiseServer.HomeObject, rootObject; var response = new ControlResponse(); #region CheckRequest if ((alexaRequest == null) || (alexaRequest.header == null) || (alexaRequest.header.payloadVersion != "2")) { response.header.@namespace = Faults.Namespace; response.header.name = Faults.UnexpectedInformationReceivedError; response.payload.exception = new ExceptionResponsePayload { faultingParameter = "alexaRequest" }; return(response); } #endregion CheckRequest #region BuildResponse try { response.header.messageId = alexaRequest.header.messageId; response.header.@namespace = alexaRequest.header.@namespace; response.header.name = alexaRequest.header.name.Replace("Request", "Confirmation"); } catch (Exception) { response.header.@namespace = Faults.Namespace; response.header.name = Faults.UnexpectedInformationReceivedError; response.payload.exception = new ExceptionResponsePayload { faultingParameter = "alexaRequest.header.name" }; return(response); } #endregion BuildResponse //SYSClient client = new SYSClient(); #region ConnectToPremise if (PremiseServer.HomeObject == null) { response.header.@namespace = Faults.Namespace; response.header.name = Faults.DependentServiceUnavailableError; response.payload.exception = new ExceptionResponsePayload { dependentServiceName = "Premise Server" }; return(response); } #endregion ConnectToPremise try { if (!CheckAccessToken(alexaRequest.payload.accessToken).GetAwaiter().GetResult()) { response.header.@namespace = Faults.Namespace; response.header.name = Faults.InvalidAccessTokenError; response.payload.exception = new ExceptionResponsePayload(); return(response); } InformLastContact("ControlRequest:" + alexaRequest.payload.appliance.additionalApplianceDetails.path).GetAwaiter().GetResult(); // check request types ControlRequestType requestType = ControlRequestType.Unknown; DeviceType deviceType = DeviceType.Unknown; string command = alexaRequest.header.name.Trim().ToUpper(); switch (command) { case "TURNOFFREQUEST": requestType = ControlRequestType.TurnOffRequest; deviceType = DeviceType.OnOff; break; case "TURNONREQUEST": requestType = ControlRequestType.TurnOnRequest; deviceType = DeviceType.OnOff; break; case "SETTARGETTEMPERATUREREQUEST": requestType = ControlRequestType.SetTargetTemperature; deviceType = DeviceType.Thermostat; break; case "INCREMENTTARGETTEMPERATUREREQUEST": requestType = ControlRequestType.IncrementTargetTemperature; deviceType = DeviceType.Thermostat; break; case "DECREMENTTARGETTEMPERATUREREQUEST": requestType = ControlRequestType.DecrementTargetTemperature; deviceType = DeviceType.Thermostat; break; case "SETPERCENTAGEREQUEST": requestType = ControlRequestType.SetPercentage; deviceType = DeviceType.Dimmer; break; case "INCREMENTPERCENTAGEREQUEST": requestType = ControlRequestType.IncrementPercentage; deviceType = DeviceType.Dimmer; break; case "DECREMENTPERCENTAGEREQUEST": requestType = ControlRequestType.DecrementPercentage; deviceType = DeviceType.Dimmer; break; case "SETCOLORREQUEST": requestType = ControlRequestType.SetColorRequest; deviceType = DeviceType.ColorLight; break; case "SETCOLORTEMPERATUREREQUEST": requestType = ControlRequestType.SetColorTemperatureRequest; deviceType = DeviceType.ColorLight; break; case "INCREMENTCOLORTEMPERATUREREQUEST": requestType = ControlRequestType.IncrementColorTemperature; deviceType = DeviceType.ColorLight; break; case "DECREMENTCOLORTEMPERATUREREQUEST": requestType = ControlRequestType.DecrementColorTemperature; deviceType = DeviceType.ColorLight; break; default: response.header.@namespace = Faults.Namespace; response.header.name = Faults.UnsupportedOperationError; response.payload.exception = new ExceptionResponsePayload(); return(response); } // get the object IPremiseObject applianceToControl = null; try { Guid premiseId = new Guid(alexaRequest.payload.appliance.applianceId); applianceToControl = PremiseServer.RootObject.GetObject(premiseId.ToString("B")).GetAwaiter().GetResult(); if (applianceToControl == null) { throw new Exception(); } } catch { response.header.@namespace = Faults.Namespace; response.header.name = Faults.NoSuchTargetError; response.payload.exception = new ExceptionResponsePayload(); return(response); } if (deviceType == DeviceType.OnOff) { switch (requestType) { case ControlRequestType.TurnOnRequest: applianceToControl.SetValue("PowerState", "True").GetAwaiter().GetResult(); break; case ControlRequestType.TurnOffRequest: applianceToControl.SetValue("PowerState", "False").GetAwaiter().GetResult(); break; default: break; } } else if (deviceType == DeviceType.Dimmer) { double currentValue = 0.0; double adjustValue = 0.0; double valueToSend = 0.0; switch (requestType) { case ControlRequestType.SetPercentage: // obtain the adjustValue adjustValue = Math.Round(double.Parse(alexaRequest.payload.percentageState.value), 2).LimitToRange(0.00, 100.00); // convert from percentage and maintain fractional accuracy valueToSend = Math.Round(adjustValue / 100.00, 4); applianceToControl.SetValue("Brightness", valueToSend.ToString()).GetAwaiter().GetResult(); break; case ControlRequestType.IncrementPercentage: // obtain the adjustValue adjustValue = Math.Round(double.Parse(alexaRequest.payload.deltaPercentage.value) / 100.00, 2).LimitToRange(0.00, 100.00); currentValue = Math.Round(applianceToControl.GetValue <Double>("Brightness").GetAwaiter().GetResult(), 2); // maintain fractional accuracy valueToSend = Math.Round(currentValue + adjustValue, 2).LimitToRange(0.00, 1.00); applianceToControl.SetValue("Brightness", valueToSend.ToString()).GetAwaiter().GetResult(); break; case ControlRequestType.DecrementPercentage: // obtain the adjustValue adjustValue = Math.Round(double.Parse(alexaRequest.payload.deltaPercentage.value) / 100.00, 2).LimitToRange(0.00, 100.00); currentValue = Math.Round(applianceToControl.GetValue <Double>("Brightness").GetAwaiter().GetResult(), 2); // maintain fractional accuracy valueToSend = Math.Round(currentValue - adjustValue, 2).LimitToRange(0.00, 1.00); applianceToControl.SetValue("Brightness", valueToSend.ToString()).GetAwaiter().GetResult(); break; default: break; } } else if (deviceType == DeviceType.ColorLight) { const double adjustValue = 100.0; double currentValue = 0.0; double valueToSend = 0.0; response.payload.achievedState = new AchievedState(); switch (requestType) { case ControlRequestType.SetColorRequest: // obtain the adjustValue double hue = Math.Round(alexaRequest.payload.color.hue.LimitToRange(0, 360), 1); double saturation = Math.Round(alexaRequest.payload.color.saturation, 4); double brightness = Math.Round(alexaRequest.payload.color.brightness, 4); // set the values applianceToControl.SetValue("Hue", hue.ToString()).GetAwaiter().GetResult(); applianceToControl.SetValue("Saturation", saturation.ToString()).GetAwaiter().GetResult(); applianceToControl.SetValue("Brightness", brightness.ToString()).GetAwaiter().GetResult(); // read them back for achieved state response.payload.achievedState.color = new ApplianceColorValue { hue = Math.Round(applianceToControl.GetValue <Double>("Hue").GetAwaiter().GetResult(), 1), saturation = Math.Round(applianceToControl.GetValue <Double>("Saturation").GetAwaiter().GetResult(), 4), brightness = Math.Round(applianceToControl.GetValue <Double>("Brightness").GetAwaiter().GetResult(), 4) }; break; case ControlRequestType.SetColorTemperatureRequest: valueToSend = alexaRequest.payload.colorTemperature.value.LimitToRange(1000, 10000); // set the value applianceToControl.SetValue("Temperature", Math.Round(valueToSend, 0).ToString()).GetAwaiter().GetResult(); // read it back response.payload.achievedState.colorTemperature = new ApplianceColorTemperatureValue { value = applianceToControl.GetValue <int>("Temperature").GetAwaiter().GetResult() }; break; case ControlRequestType.IncrementColorTemperature: currentValue = applianceToControl.GetValue <int>("Temperature").GetAwaiter().GetResult(); valueToSend = Math.Round(currentValue + adjustValue, 0).LimitToRange(1000, 10000); // set the value applianceToControl.SetValue("Temperature", valueToSend.ToString()).GetAwaiter().GetResult(); // read it back response.payload.achievedState.colorTemperature = new ApplianceColorTemperatureValue { value = applianceToControl.GetValue <int>("Temperature").GetAwaiter().GetResult() }; break; case ControlRequestType.DecrementColorTemperature: currentValue = Math.Round(applianceToControl.GetValue <Double>("Temperature").GetAwaiter().GetResult(), 2); valueToSend = Math.Round(currentValue - adjustValue, 0).LimitToRange(1000, 10000); // set the value applianceToControl.SetValue("Temperature", valueToSend.ToString()).GetAwaiter().GetResult(); // read it back response.payload.achievedState.colorTemperature = new ApplianceColorTemperatureValue { value = applianceToControl.GetValue <int>("Temperature").GetAwaiter().GetResult() }; break; default: break; } } else if (deviceType == DeviceType.Thermostat) { int previousTemperatureMode; int temperatureMode; Temperature previousTargetTemperature = null; Temperature targetTemperature = null; double deltaTemperatureC = 0.0; // in C // obtain previous state (sys stores temperatures as K) previousTemperatureMode = applianceToControl.GetValue <int>("TemperatureMode").GetAwaiter().GetResult(); previousTargetTemperature = new Temperature(applianceToControl.GetValue <double>("CurrentSetPoint").GetAwaiter().GetResult()); switch (requestType) { case ControlRequestType.SetTargetTemperature: // get target temperature in C targetTemperature = new Temperature { Celcius = double.Parse(alexaRequest.payload.targetTemperature.value) }; break; case ControlRequestType.IncrementTargetTemperature: // get delta temp in C deltaTemperatureC = double.Parse(alexaRequest.payload.deltaTemperature.value); // increment the targetTemp targetTemperature = new Temperature { Celcius = previousTargetTemperature.Celcius + deltaTemperatureC }; break; case ControlRequestType.DecrementTargetTemperature: // get delta temp in C deltaTemperatureC = double.Parse(alexaRequest.payload.deltaTemperature.value); // decrement the targetTemp targetTemperature = new Temperature { Celcius = previousTargetTemperature.Celcius - deltaTemperatureC }; break; default: targetTemperature = new Temperature(0.00); previousTemperatureMode = 10; // error break; } // set new target temperature applianceToControl.SetValue("CurrentSetPoint", targetTemperature.Kelvin.ToString()).GetAwaiter().GetResult(); response.payload.targetTemperature = new ApplianceValue { value = targetTemperature.Celcius.ToString() }; // get new mode temperatureMode = applianceToControl.GetValue <int>("TemperatureMode").GetAwaiter().GetResult(); // report new mode response.payload.temperatureMode = new ApplianceValue { value = TemperatureMode.ModeToString(temperatureMode) }; // alloc a previousState object response.payload.previousState = new AppliancePreviousState { // report previous mode mode = new ApplianceValue { value = TemperatureMode.ModeToString(previousTemperatureMode) }, // report previous targetTemperature in C targetTemperature = new ApplianceValue { value = previousTargetTemperature.Celcius.ToString() } }; } else { response.header.@namespace = Faults.Namespace; response.header.name = Faults.UnsupportedOperationError; response.payload.exception = new ExceptionResponsePayload(); } } catch { response.header.@namespace = Faults.Namespace; response.header.name = Faults.DriverpublicError; response.payload.exception = new ExceptionResponsePayload(); } return(response); }