/// <summary> /// Handles commands for the Harmony published to MQTT. /// </summary> /// <param name="e">Event args.</param> protected override async void Mqtt_MqttMsgPublishReceived(MqttApplicationMessageReceivedEventArgs e) { var message = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); _log.LogInformation("MQTT message received for topic " + e.ApplicationMessage.Topic + ": " + message); // Parse topic out var topicWithoutRoot = e.ApplicationMessage.Topic.Substring(TopicRoot.Length + 1); var thermostatId = topicWithoutRoot.Substring(0, topicWithoutRoot.IndexOf('/')); var thermostatTopic = topicWithoutRoot.Substring(topicWithoutRoot.IndexOf('/') + 1); // ONLY VALID OPTIONS // HvacMode (auto, auxHeatOnly, cool, heat, off) - hvacMode/set // Fan (on, off, auto) - desiredFanMode/set // SetHold ({ hold object }) - hold/set // Desired Heat - desiredHeat/set // Desired Cool - desiredCool/set var request = new ThermostatUpdateRequest { Selection = new Selection { SelectionType = "thermostats", SelectionMatch = thermostatId } }; _log.LogInformation($"Sending request to {request.Uri} with thermostat selection {thermostatId} for action {thermostatTopic}"); switch (thermostatTopic) { case "desiredCool/set": if (int.TryParse(message, out int desiredCoolValue) && int.TryParse(_thermostatStatus[thermostatId].Status["desiredHeat"], out int currentDesiredHeatValue)) { request.Functions = new List <Function> { new SetHoldFunction { Params = new SetHoldParams { HoldType = "nextTransition", CoolHoldTemp = desiredCoolValue * 10, HeatHoldTemp = currentDesiredHeatValue * 10 } } }; var desiredCoolResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredCoolResponse.Status.Code}) {desiredCoolResponse.Status.Message}"); // Publish updates and cache new values await GetInitialStatusAsync(); } break; case "desiredFanMode/set": if (message == "auto" || message == "off" || message == "on") { request.Functions = new List <Function> { new SetHoldFunction { Params = new SetHoldParams { HoldType = "nextTransition", Fan = message } } }; var desiredFanModeResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredFanModeResponse.Status.Code}) {desiredFanModeResponse.Status.Message}"); // Publish updates and cache new values await GetInitialStatusAsync(); } break; case "desiredHeat/set": if (int.TryParse(message, out int desiredHeatValue) && int.TryParse(_thermostatStatus[thermostatId].Status["desiredCool"], out int currentDesiredCoolValue)) { request.Functions = new List <Function> { new SetHoldFunction { Params = new SetHoldParams { HoldType = "nextTransition", CoolHoldTemp = currentDesiredCoolValue * 10, HeatHoldTemp = desiredHeatValue * 10 } } }; var desiredHeatResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredHeatResponse.Status.Code}) {desiredHeatResponse.Status.Message}"); // Publish updates and cache new values await GetInitialStatusAsync(); } break; case "hold/set": try { if (message.Contains("resumeProgram")) { var resumeFunction = JsonSerializer <ResumeProgramFunction> .Deserialize(message); request.Functions = new List <Function> { resumeFunction }; } else { var holdFunction = JsonSerializer <SetHoldFunction> .Deserialize(message); request.Functions = new List <Function> { holdFunction }; } var setHoldResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({setHoldResponse.Status.Code}) {setHoldResponse.Status.Message}"); // Publish updates and cache new values await GetInitialStatusAsync(); } catch (JsonException ex) { _log.LogWarning(ex, $"Could not deserialize payload: {message}"); } break; case "hvacMode/set": if (message == "auto" || message == "auxHeatOnly" || message == "cool" || message == "heat" || message == "off") { request.Thermostat = new { Settings = new { HvacMode = message } }; var hvacModeResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({hvacModeResponse.Status.Code}) {hvacModeResponse.Status.Message}"); // Publish updates and cache new values await GetInitialStatusAsync(); } break; default: _log.LogWarning($"Unknown command topic {thermostatTopic} for thermostat {thermostatId}"); break; } }
/// <summary> /// Handles commands for the Harmony published to MQTT. /// </summary> /// <param name="e">Event args.</param> protected override async void Mqtt_MqttMsgPublishReceived(MqttApplicationMessageReceivedEventArgs e) { var message = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); _log.LogInformation("MQTT message received for topic " + e.ApplicationMessage.Topic + ": " + message); // Parse topic out var topicWithoutRoot = e.ApplicationMessage.Topic.Substring(TopicRoot.Length + 1); var thermostatId = topicWithoutRoot.Substring(0, topicWithoutRoot.IndexOf('/')); var thermostatTopic = topicWithoutRoot.Substring(topicWithoutRoot.IndexOf('/') + 1); // ONLY VALID OPTIONS // HvacMode (auto, auxHeatOnly, cool, heat, off) - hvacMode/set // Fan (on, off, auto) - desiredFanMode/set // SetHold (hold, resume) - hold/set // Desired Heat - desiredHeat/set // Desired Cool - desiredCool/set var request = new ThermostatUpdateRequest { Selection = new Selection { SelectionType = "thermostats", SelectionMatch = thermostatId } }; _log.LogInformation($"Sending request to {request.Uri} with thermostat selection {thermostatId} for action {thermostatTopic}"); switch (thermostatTopic) { case "hvacMode/set": request.Thermostat = new { Settings = new { HvacMode = message } }; var hvacModeResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({hvacModeResponse.Status.Code}) {hvacModeResponse.Status.Message}"); break; case "desiredFanMode/set": request.Thermostat = new { Settings = new { Vent = message } }; var desiredFanModeResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredFanModeResponse.Status.Code}) {desiredFanModeResponse.Status.Message}"); break; case "hold/set": if (message == "hold") { // TODO: Figure out how to pass both desired heat and cool values at same time var holdFunc = new SetHoldFunction(); ((SetHoldParams)holdFunc.Params).HoldType = "indefinite"; ((SetHoldParams)holdFunc.Params).CoolHoldTemp = 0; ((SetHoldParams)holdFunc.Params).HeatHoldTemp = 0; request.Functions.Add(holdFunc); ////_client.Post<ThermostatUpdateRequest, Response>(request); } else { var resumeFunc = new ResumeProgramFunction(); ((ResumeProgramParams)resumeFunc.Params).ResumeAll = true; request.Functions.Add(resumeFunc); await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); } break; case "desiredHeat/set": if (int.TryParse(message, out int desiredHeatValue)) { request.Thermostat = new { Runtime = new { DesiredHeat = desiredHeatValue * 10 } }; var desiredHeatResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredHeatResponse.Status.Code}) {desiredHeatResponse.Status.Message}"); } break; case "desiredCool/set": if (int.TryParse(message, out int desiredCoolValue)) { request.Thermostat = new { Runtime = new { DesiredCool = desiredCoolValue * 10 } }; var desiredCoolResponse = await _client.PostAsync <ThermostatUpdateRequest, Response>(request) .ConfigureAwait(false); _log.LogInformation($"{request.Uri} response: ({desiredCoolResponse.Status.Code}) {desiredCoolResponse.Status.Message}"); } break; default: _log.LogWarning($"Unknown command topic {thermostatTopic} for thermostat {thermostatId}"); break; } }