//turn the fan off public void FanOff() { try { var response = PostCommand("{\"command\":\"sdm.devices.commands.Fan.SetTimer\",\"params\":{\"timerMode\":\"OFF\"}}"); if (response != null) { if (response.Length > 0) { if (response == "{}\n") { if (onFanState != null) { onFanState(0); } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in Thermostat: FanOff()" + e, DebugLogic.ErrorLevel.Error, true); } }
//Run fan for specified time public void RunFan(ushort timeInSeconds) { try { if (timeInSeconds > 0) { var response = PostCommand("{\"command\":\"sdm.devices.commands.Fan.SetTimer\",\"params\":{\"timerMode\":\"ON\",\"duration\":\"" + timeInSeconds + "s\"}}"); if (response != null) { if (response.Length > 0) { if (response == "{}\n") { fanTimer.Reset(timeInSeconds * 1000); if (onFanState != null) { onFanState(1); } } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in Thermostat: RunFan(ushort)" + e, DebugLogic.ErrorLevel.Error, true); } }
//Use refresh token to request a session token private void UseRefreshToken(object o) { try { using (HttpsClient client = new HttpsClient()) { client.TimeoutEnabled = true; client.Timeout = 10; client.HostVerification = false; client.PeerVerification = false; client.AllowAutoRedirect = false; HttpsClientRequest request = new HttpsClientRequest(); request.Url.Parse("https://www.googleapis.com/oauth2/v4/token?client_id=" + ClientID + "&refresh_token=" + refreshToken + "&grant_type=refresh_token&redirect_uri=https://www.google.com&client_secret=" + ClientSecret); request.RequestType = RequestType.Post; HttpsClientResponse response = client.Dispatch(request); if (response.ContentString != null) { if (response.ContentString.Length > 0) { JObject body = JObject.Parse(response.ContentString); if (body["expires_in"] != null) { var seconds = Convert.ToInt16(body["expires_in"].ToString().Replace("\"", string.Empty)) - 10; var milliseconds = seconds * 1000; refreshTimer = new CTimer(UseRefreshToken, milliseconds); } if (body["access_token"] != null) { Token = body["access_token"].ToString().Replace("\"", string.Empty); } if (body["token_type"] != null) { TokenType = body["token_type"].ToString().Replace("\"", string.Empty); } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in UseRefreshToken" + e, DebugLogic.ErrorLevel.Error, true); } }
//Get all devices public void GetDevices() { try { using (var client = new HttpsClient()) { client.TimeoutEnabled = true; client.Timeout = 10; client.HostVerification = false; client.PeerVerification = false; client.AllowAutoRedirect = false; HttpsClientRequest request = new HttpsClientRequest(); request.Url.Parse("https://smartdevicemanagement.googleapis.com/v1/enterprises/" + ProjectID + "/devices"); request.RequestType = RequestType.Get; request.Header.ContentType = "application/json"; request.Header.AddHeader(new HttpsHeader("Authorization", string.Format("{0} {1}", TokenType, Token))); HttpsClientResponse response = client.Dispatch(request); if (response.ContentString != null) { if (response.ContentString.Length > 0) { JObject body = JObject.Parse(response.ContentString); if (body["error"] != null) { onErrorMessage(body["error"]["message"].ToString().Replace("\"", string.Empty)); } foreach (var dev in body["devices"]) { if (devices.ContainsKey(dev["traits"]["sdm.devices.traits.Info"]["customName"].ToString().Replace("\"", string.Empty))) { devices[dev["traits"]["sdm.devices.traits.Info"]["customName"].ToString().Replace("\"", string.Empty)].ParseData(dev); } } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in GetDevices" + e, DebugLogic.ErrorLevel.Error, true); } }
//Set heat/cool range setpoints public void SetRange(ushort heat, ushort cool) { try { //convert s+ ushort to a double moving the percision byb 10 var HsPoint = Math.Round((decimal)(heat / (decimal)10.0), 1); var CsPoint = Math.Round(((decimal)cool / (decimal)10.0), 1); if (isFahrenheit) { HsPoint = FahrenheitToCelsius(HsPoint); CsPoint = FahrenheitToCelsius(CsPoint); } //checks if set point is an allowable range if (HsPoint >= 9 && HsPoint <= 32 && CsPoint >= 9 && CsPoint <= 32) { var response = PostCommand("{\"command\":\"sdm.devices.commands.ThermostatTemperatureSetpoint.SetRange\",\"params\":{\"heatCelsius\":" + HsPoint + ",\"coolCelsius\":" + CsPoint + "}}"); if (response != null) { if (response.Length > 0) { if (response == "{}\n") { if (onCurrentHeatSetPoint != null) { onCurrentHeatSetPoint(heat); } if (onCurrentCoolSetPoint != null) { onCurrentCoolSetPoint(cool); } } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in Thermostat: SetRange(ushort, ushort)" + e, DebugLogic.ErrorLevel.Error, true); } }
//Turn eco mode on or off public void SetEcoMode(string mode) { try { var response = PostCommand("{\"command\":\"sdm.devices.commands.ThermostatEco.SetMode\",\"params\":{\"mode\":\"" + mode + "\"}}"); if (response != null) { if (response.Length > 0) { if (response == "{}\n") { GetDevice(); } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in Thermostat: SetEcoMode(string)" + e, DebugLogic.ErrorLevel.Error, true); } }
//Set heat setpoint public void SetHeat(ushort setPoint) { try { //convert s+ ushort to a double moving the percision by 10 decimal sPoint = Math.Round((decimal)setPoint / (decimal)10.0, 1); if (isFahrenheit) { sPoint = FahrenheitToCelsius(sPoint); } //checks if set point is an allowable range if (sPoint >= 9 && sPoint <= 32) { var response = PostCommand("{\"command\":\"sdm.devices.commands.ThermostatTemperatureSetpoint.SetHeat\",\"params\":{\"heatCelsius\":" + sPoint + "}}"); if (response != null) { if (response.Length > 0) { if (response == "{}\n") { if (onCurrentHeatSetPoint != null) { onCurrentHeatSetPoint(setPoint); } } } } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in Thermostat: SetHeat(ushort)" + e, DebugLogic.ErrorLevel.Error, true); } }
//Check if refresh token file exists and consume if it does public void Initialize() { try { refreshTokenFilePath = string.Format(@"\user\{0}\", Directory.GetApplicationDirectory().Replace("/", "\\").Split('\\')[2]); DebugLogic.Log(">>> LOGGING: refreshTokenFilePath: " + refreshTokenFilePath, DebugLogic.ErrorLevel.Notice, true); if (File.Exists(refreshTokenFilePath + refreshTokenFileName)) { using (StreamReader reader = new StreamReader(File.OpenRead(refreshTokenFilePath + refreshTokenFileName))) { refreshToken = reader.ReadToEnd().Replace("\r\n", string.Empty); } if (refreshToken.Length > 0) { UseRefreshToken(null); } else { if (onErrorMessage != null) { onErrorMessage("Stored refresh token file is empty, please delete file and use authorization code"); } } } else { if (AuthCode.Length > 0) { GetTokenAndRefreshToken(); } else { if (onErrorMessage != null) { onErrorMessage("Authorization code cannot be empty on the first query to the Google API service, please set authorization code"); } } } if (Token.Length > 0) { Initialized = true; if (onIsInitialized != null) { onIsInitialized(1); } GetDevices(); } else { Initialized = false; if (onIsInitialized != null) { onIsInitialized(0); } } } catch (Exception e) { Initialized = false; if (onIsInitialized != null) { onIsInitialized(0); } DebugLogic.Log(">>> ERROR: Exception ocurred in Initialize" + e, DebugLogic.ErrorLevel.Error, true); } }
//Use authorization code to retrieve a refresh token and a session token private void GetTokenAndRefreshToken() { try { using (var client = new HttpsClient()) { client.TimeoutEnabled = true; client.Timeout = 10; client.HostVerification = false; client.PeerVerification = false; client.AllowAutoRedirect = false; var request = new HttpsClientRequest(); var url = "https://www.googleapis.com/oauth2/v4/token?client_id=" + ClientID + "&code=" + AuthCode + "&grant_type=authorization_code&redirect_uri=https://www.google.com&client_secret=" + ClientSecret; request.Url.Parse(url); DebugLogic.Log(">>> LOGGING: GetTokenAndRefreshToken: URL: " + url, DebugLogic.ErrorLevel.Notice, true); request.RequestType = RequestType.Post; request.Header.SetHeaderValue("Content-Type", "application/json; charset=utf-8"); var response = client.Dispatch(request); if (response.ContentString == null) { return; } if (response.ContentString.Length <= 0) { return; } DebugLogic.Log(">>> LOGGING: GetTokenAndRefreshToken: Response Content String - Not Parsed: " + response.ContentString, DebugLogic.ErrorLevel.Notice, true); var body = JObject.Parse(response.ContentString); DebugLogic.Log(">>> LOGGING: GetTokenAndRefreshToken: Parsed String: " + body.ToString(), DebugLogic.ErrorLevel.Notice, true); if (body["expires_in"] != null) { var seconds = Convert.ToInt16(body["expires_in"].ToString().Replace("\"", string.Empty)) - 10; var milliseconds = seconds * 1000; refreshTimer = new CTimer(UseRefreshToken, milliseconds); } if (body["access_token"] != null) { Token = body["access_token"].ToString().Replace("\"", string.Empty); } if (body["token_type"] != null) { TokenType = body["token_type"].ToString().Replace("\"", string.Empty); } if (body["refresh_token"] == null) { return; } refreshToken = body["refresh_token"].ToString().Replace("\"", string.Empty); using (var writer = new StreamWriter(File.Create(refreshTokenFilePath + refreshTokenFileName))) { writer.WriteLine(refreshToken); } } } catch (Exception e) { DebugLogic.Log(">>> ERROR: Exception ocurred in GetTokenAndRefreshToken" + e, DebugLogic.ErrorLevel.Error, true); } }