Last active
June 15, 2016 13:58
-
-
Save voodoojello/690a398df9b3e9ac1711 to your computer and use it in GitHub Desktop.
LUUP: AutoTherm - Set Thermostats by Inside/Outside Temp, Humidity, and Time of Day
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module("auto_therm", package.seeall) | |
-- | |
-- LUUP: AutoTherm - auto_therm.lua | |
-- Set Thermostats by Inside/Outside Temp, Humidity, and Time of Day | |
-- | |
-- Authored: Mark Page [m.e.page_at_gmail.com] | |
-- Modified: Sat Mar 21 21:22:37 CDT 2015 | |
-- | |
-- Tested on Vera Lite - UI7 Version 7.0.2 (1.7.439) | |
-- Tested on Vera Edge - UI7 Version 7.0.5 (1.7.1018) | |
-- Tested using the Wunderground Weather Plugin - http://code.mios.com/trac/mios_weather | |
-- Tested using 2GIG CT100 Thermostats - https://www.2gig.com/products/ct100 | |
-- | |
-- For more info see: http://goo.gl/9b0QPP | |
-- | |
function settherms() | |
---------------------------------------------------- | |
-- User settings start here ------------------------ | |
---------------------------------------------------- | |
-- Vacation Mode - Set true to turn-off thermostats | |
local VacationMode = false | |
-- Desired Temp Settings | |
local DayHeatSetTemp = 73 | |
local DayCoolSetTemp = 74 | |
local NightHeatSetTemp = 68 | |
local NightCoolSetTemp = 74 | |
-- Heat or Cool threshold temp | |
local OSThresTemp = 66 | |
-- Hour of day change over | |
local StartNightHour = 21 | |
local EndNightHour = 3 | |
-- Therm and sensor Device IDs | |
local OSTempDID = XX | |
local OSHumidDID = XX | |
local ThermDIDs = {XX,XX} | |
-- Multiplier to skew logarithmic equations for comfort. | |
-- Higher numbers result in colder/warmer settings. | |
-- Use caution as values >.05 may swing adjustments wildly! | |
local TempTweakIndx = .008 | |
-- Used for sms/email notification through 3rd party RESTful API | |
local MsgAppURL = 'http://path.to/some/app' | |
local MsgAppPairs = '[name1=val1&name2=val2&]msg_txt_will_be_here=' | |
---------------------------------------------------- | |
-- User settings end here -------------------------- | |
---------------------------------------------------- | |
local OSCurrTemp = 50 -- fail-safe for calc on unexpected URN nil return | |
local OSCurrHumid = 50 -- fail-safe for calc on unexpected URN nil return | |
local DebugMode = false -- Off-device debugging. Will not run on Vera if set to true! | |
local HourOfDay = os.date('*t').hour | |
local datetime = os.date() | |
local http = require("socket.http") | |
local ISTemp = "" | |
local DevName = "" | |
local _return = "" | |
if (DebugMode) then | |
OSCurrTemp = arg[1] | |
OSCurrHumid = arg[2] | |
else | |
OSCurrTemp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", OSTempDID) | |
OSCurrHumid = luup.variable_get("urn:micasaverde-com:serviceId:HumiditySensor1", "CurrentLevel", OSHumidDID) | |
end | |
OSCurrTemp = tonumber(OSCurrTemp) | |
OSCurrHumid = tonumber(OSCurrHumid) | |
for _, _did in pairs (ThermDIDs) do | |
local SetMode = "Cool" | |
local SetTemp = DayCoolSetTemp | |
local DayNight = "Day" | |
if (HourOfDay >= StartNightHour or HourOfDay <= EndNightHour) then | |
SetTemp = NightCoolSetTemp | |
DayNight = "Night" | |
end | |
if (OSCurrTemp < OSThresTemp) then | |
SetMode = "Heat" | |
SetTemp = DayHeatSetTemp | |
if (HourOfDay >= StartNightHour or HourOfDay <= EndNightHour) then | |
SetTemp = NightHeatSetTemp | |
DayNight = "Night" | |
end | |
end | |
local DevMode = SetMode .. "On" | |
local ModeSID = "urn:upnp-org:serviceId:HVAC_UserOperatingMode1" | |
local TempSID = "urn:upnp-org:serviceId:TemperatureSetpoint1_" .. SetMode | |
-- Inside temperature as reported by thermostat | |
if (DebugMode) then | |
ISTemp = arg[3] | |
else | |
ISTemp = luup.variable_get("urn:upnp-org:serviceId:TemperatureSensor1", "CurrentTemperature", _did) | |
end | |
-- Device name attribute from DID | |
if (DebugMode) then | |
DevName = "Dummy" .. _did | |
else | |
DevName = luup.attr_get('name', _did) | |
end | |
-- Primitive temperature index calculations with logarithmic adjustment. | |
-- Reference: http://www.wpc.ncep.noaa.gov/html/heatindex_equation.shtml | |
local HeatIndx = math.log(0.5 * (SetTemp + 61.0 + ((SetTemp-68.0)*1.2) + (OSCurrHumid*0.094))) | |
local TempIndx = math.log(OSCurrTemp) | |
-- Tweak set temp based on indexes and current inside temp | |
local DevTemp = ((SetTemp - TempIndx) + HeatIndx) - (ISTemp*TempTweakIndx) | |
DevTemp = string.format("%.1f", DevTemp - ((TempIndx + HeatIndx)/SetTemp)) | |
-- Turn off thermostats if "VacationMode" set to "True" | |
if (VacationMode) then | |
DevMode = 'Off' | |
SetMode = 'Off - Vacation Mode' | |
end | |
-- For whatever reason luup.call_action will occasionally miss. | |
-- We'll call it twice just to be sure luup gets the events. | |
if not (DebugMode) then | |
for l = 0, 1, 1 do | |
luup.call_action(ModeSID, "SetModeTarget", {NewModeTarget = DevMode}, _did) | |
luup.sleep(500) | |
luup.call_action(TempSID, "SetCurrentSetpoint", {NewCurrentSetpoint = DevTemp}, _did) | |
luup.sleep(500) | |
end | |
end | |
local heat_ndex = string.format("%.2f", HeatIndx) | |
local temp_ndex = string.format("%.2f", TempIndx) | |
_return = _return .. string.format("Thermostat %s [ID%s] set to %s\194\176 (%s/%s) -- [S:%s\194\176, I:%s\194\176, O:%s\194\176, H:%s%%, HI:%s\194\176, TI:%s\194\176]\n\n", DevName, _did, DevTemp, SetMode, DayNight, SetTemp, DevTemp, OSCurrTemp, OSCurrHumid, heat_ndex, temp_ndex) | |
end | |
if (DebugMode) then | |
print (_return) | |
else | |
if (MsgAppURL) then | |
local _request = MsgAppPairs .. datetime .. "\n\n" .. _return | |
local _sendmsg = http.request(MsgAppURL, _request) | |
end | |
end | |
return _return | |
end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment