-
-
Save jshatch/34b3d1929b642ed53b4cc30013529778 to your computer and use it in GitHub Desktop.
EverLights API
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
The app always sends a nocache param, which appears to be time since the app launched. It's ignored by the control box. | |
Color is just RGB. 255,255,255 = 0xffffff. 0,255,0 = 0x00ff00 | |
Modes: | |
all modes can take a value between 0-255. only one of tw, cf, cr, wi, ra can be set at once | |
tw: twinkle | |
fa: fade | |
bl: blink | |
st: strobe | |
cf: chase forward | |
cr: chase reverse | |
wi: wipe | |
ra: random | |
rb: ??? | |
For pattern names, spaces are saved as underscores (you can't save underscores) | |
User-Agent: everlights2/7 CFNetwork/978.0.7 Darwin/18.6.0 | |
GET /status/get?nocache=534.999015 | |
{"stsCnt":20,"ch1Cnt":402,"ch2Cnt":201,"version":"2.3.0","mac":"2C:3A:E8:FF:FF:FF","autopilot":0,"epoch":1560017691,"tzOffset":-7,"stsActive":1,"ch1Active":0,"ch2Active":0,"stsInd":1,"lightingStatus":0,"ssid":"Cutrer","rssi":-58,"ip":"192.168.10.10","mode":1,"status":"connected","rebootCnt":21,"loopsPerSecond":13422,"writeDuration":19327} | |
GET /epoch/set?epoch=1560017696&nocache=567.472399 | |
{"success":true} | |
GET /ptrn/all | |
{"patterns":["NEW_YEAR'S","VALENTINE'S_DAY","ST_PATRICK'S_DAY","EASTER","MOTHER'S_DAY","FATHER'S_DAY","HALLOWEEN","VETERANS_DAY","THANKSGIVING","CHRISTMAS","Color_splat","My_Christmas","INDEPENDENCE_DAY"],"cnt":13} | |
GET /ptrn/get?id=NEW_YEAR'S | |
{"len":3,"ptrn":[16733952,16777215,16733952],"modes":{"fa":0,"bl":0,"st":0,"cf":0,"cr":0,"wi":0,"ra":0,"tw":0,"rb":0},"name":"NEW_YEAR'S"} | |
GET /sch/getchannel?channel=1 | |
{"schedules":[]} | |
GET /ptrn/set?channel=3&data=%7B%22len%22:4,%22ptrn%22:[16777215,16711680,16777215,45056],%22modes%22:%7B%22fa%22:0,%22bl%22:0,%22st%22:0,%22cf%22:0,%22cr%22:0,%22wi%22:0,%22ra%22:0,%22tw%22:0,%22rb%22:0%7D,%22name%22:%22%22%7D | |
{"success":true} | |
GET /status/get | |
{"stsCnt":20,"ch1Cnt":402,"ch2Cnt":201,"version":"2.3.0","mac":"2C:3A:E8:FF:FF:FF","autopilot":0,"epoch":1560018587,"tzOffset":-7,"stsActive":1,"ch1Active":1,"ch2Active":1,"stsInd":1,"lightingStatus":0,"ssid":"Cutrer","rssi":-58,"ip":"192.168.10.10","mode":1,"status":"connected","rebootCnt":21,"loopsPerSecond":13099,"writeDuration":19660} | |
turn lights off | |
GET /ptrn/clear?channel=0 | |
GET /ptrn/clear?channel=1 | |
GET /ptrn/clear?channel=2 | |
GET /ptrn/clear?channel=3 | |
save pattern | |
GET /ptrn/sv?id=My_Christmas2&data=%7B%22len%22:4,%22ptrn%22:[16777215,16711680,16777215,45056],%22modes%22:%7B%22fa%22:0,%22bl%22:0,%22st%22:0,%22cf%22:0,%22cr%22:0,%22wi%22:0,%22ra%22:154,%22tw%22:0,%22rb%22:0%7D,%22name%22:%22My_Christmas2%22%7D | |
delete a pattern | |
GET /ptrn/del?id=MY_CHRUSTMAS |
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
rule "Any rule that runs daily at sunset or whenever you want the lights to come on" | |
when | |
... | |
then | |
// Calculate if Everlights should be on | |
var holiday = executeCommandLine("/var/lib/openhab2/holidays.rb", 500) | |
if (holiday != "") { | |
Everlights_Preset.sendCommand(holiday) | |
Everlights_Switch.sendCommand(ON) | |
} | |
end | |
// don't forget a rule to turn them off |
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
Switch Everlights_Switch "Everlights" <light> (gAllOff) | |
String EverlightsZone1_Data | |
String EverlightsZone2_Data | |
Group gEverlights | |
Group gEverlightsExclusive | |
String Everlights_Preset "Pattern" | |
Switch Everlights_PatternChanging | |
Number Everlights_Count "Pattern Length [%s]" (gEverlights) | |
Color Everlights1_RGB "Color 1" (gEverlights) | |
Color Everlights2_RGB "Color 2" (gEverlights) | |
Color Everlights3_RGB "Color 3" (gEverlights) | |
Color Everlights4_RGB "Color 4" (gEverlights) | |
Color Everlights5_RGB "Color 5" (gEverlights) | |
Color Everlights6_RGB "Color 6" (gEverlights) | |
Color Everlights7_RGB "Color 7" (gEverlights) | |
Color Everlights8_RGB "Color 8" (gEverlights) | |
Color Everlights9_RGB "Color 9" (gEverlights) | |
Color Everlights10_RGB "Color 10" (gEverlights) | |
Number Everlights_Twinkle "Twinkle" (gEverlights, gEverlightsExclusive) | |
Number Everlights_Fade "Fade" (gEverlights) | |
Number Everlights_Blink "Blink" (gEverlights) | |
Number Everlights_Strobe "Strobe" (gEverlights) | |
Number Everlights_Chase "Chase" (gEverlights, gEverlightsExclusive) | |
Number Everlights_ChaseReverse "Reverse Chase" (gEverlights, gEverlightsExclusive) | |
Number Everlights_Wipe "Wipe" (gEverlights, gEverlightsExclusive) | |
Number Everlights_Random "Random" (gEverlights, gEverlightsExclusive) |
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
#!/usr/bin/env ruby | |
require 'cgi' | |
require 'json' | |
require 'net/http' | |
def hsv_to_rgb(h, s, v) | |
h, s, v = h.to_f/360, s.to_f/100, v.to_f/100 | |
h_i = (h*6).to_i | |
f = h*6 - h_i | |
p = v * (1 - s) | |
q = v * (1 - f*s) | |
t = v * (1 - (1 - f) * s) | |
r, g, b = v, t, p if h_i==0 | |
r, g, b = q, v, p if h_i==1 | |
r, g, b = p, v, t if h_i==2 | |
r, g, b = p, q, v if h_i==3 | |
r, g, b = t, p, v if h_i==4 | |
r, g, b = v, p, q if h_i==5 | |
[(r*255).to_i, (g*255).to_i, (b*255).to_i] | |
end | |
def convert_rgb(string) | |
string = "0,0,0" if string == "NULL" | |
hsv_to_rgb(*string.split(',')).inject(0) do |result, value| | |
result *= 256 | |
result + value.to_i | |
end | |
end | |
def normalize_pattern(pattern, reverse: false) | |
modes = { fa: 0, bl: 0, st: 0, cf: 0, cr: 0, wi: 0, ra: 0, tw: 0, rb: 0 }.merge(pattern[:modes] || {}) | |
pattern = pattern[:ptrn] | |
if reverse | |
temp = modes[:cf] | |
modes[:cf] = modes[:cr] | |
modes[:cr] = temp | |
pattern = pattern.reverse | |
end | |
CGI.escape({ len: pattern.length, ptrn: pattern, modes: modes }.to_json) | |
end | |
reverse = !!ARGV.delete('--reverse') | |
pattern = {} | |
Net::HTTP.start('localhost', 8080) do |http| | |
pattern[:len] = http.get("/rest/items/Everlights_Count/state").body.to_i | |
pattern[:ptrn] = (1..pattern[:len]).map do |i| | |
convert_rgb(http.get("/rest/items/Everlights#{i}_RGB/state").body) | |
end | |
modes = pattern[:modes] = {} | |
modes[:tw] = http.get("/rest/items/Everlights_Twinkle/state").body.to_i | |
modes[:fa] = http.get("/rest/items/Everlights_Fade/state").body.to_i | |
modes[:bl] = http.get("/rest/items/Everlights_Blink/state").body.to_i | |
modes[:st] = http.get("/rest/items/Everlights_Strobe/state").body.to_i | |
modes[:cf] = http.get("/rest/items/Everlights_Chase/state").body.to_i | |
modes[:cr] = http.get("/rest/items/Everlights_ChaseReverse/state").body.to_i | |
modes[:wi] = http.get("/rest/items/Everlights_Wipe/state").body.to_i | |
modes[:ra] = http.get("/rest/items/Everlights_Random/state").body.to_i | |
end | |
puts normalize_pattern(pattern, reverse: reverse) |
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
rule "Everlights On" | |
when | |
Item Everlights_Switch changed to ON | |
then | |
if (EverlightsZone1_Data.state != "") { | |
sendHttpGetRequest("http://192.168.85.223/ptrn/set?channel=1&data=" + EverlightsZone1_Data.state) | |
} | |
if (EverlightsZone2_Data.state != "") { | |
sendHttpGetRequest("http://192.168.85.223/ptrn/set?channel=2&data=" + EverlightsZone2_Data.state) | |
} | |
end | |
rule "Everlights Off" | |
when | |
Item Everlights_Switch changed to OFF | |
then | |
sendHttpGetRequest("http://192.168.85.223/ptrn/clear?channel=3") | |
end | |
rule "Everlights zone1 change" | |
when | |
Item EverlightsZone1_Data changed | |
then | |
if (Everlights_Switch.state == ON && EverlightsZone1_Data.state != "") { | |
sendHttpGetRequest("http://192.168.85.223/ptrn/set?channel=1&data=" + EverlightsZone1_Data.state) | |
} | |
end | |
rule "Everlights zone2 change" | |
when | |
Item EverlightsZone2_Data changed | |
then | |
if (Everlights_Switch.state == ON && EverlightsZone2_Data.state != "") { | |
sendHttpGetRequest("http://192.168.85.223/ptrn/set?channel=2&data=" + EverlightsZone2_Data.state) | |
} | |
end | |
rule "Everlights Pattern Changed" | |
when | |
Member of gEverlights changed | |
then | |
// Delay updating this until everything is changed from a preset | |
if (Everlights_PatternChanging.state != ON) { | |
EverlightsZone1_Data.postUpdate(executeCommandLine("/var/lib/openhab2/everlights.rb", 500)) | |
EverlightsZone2_Data.postUpdate(executeCommandLine("/var/lib/openhab2/everlights.rb --reverse", 500)) | |
Everlights_Pattern.postUpdate("") | |
} | |
end | |
rule "Everlights exclusive modes" | |
when | |
Member of gEverlightsExclusive changed | |
then | |
gEverlightsExclusive.members.forEach[item| | |
if (item != triggeringItem) { | |
item.postUpdate(0) | |
} | |
] | |
end | |
rule "Everlights preset pattern" | |
when | |
Item Everlights_Preset changed | |
then | |
Everlights_PatternChanging.postUpdate(ON) | |
if (Everlights_Preset.state == "Valentine's Day") { | |
Everlights_Count.postUpdate(6) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(255, 0, 0)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(255, 255, 255)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(255, 0, 0)) | |
Everlights4_RGB.postUpdate(HSBType.fromRGB(252, 0, 255)) | |
Everlights5_RGB.postUpdate(HSBType.fromRGB(252, 0, 255)) | |
Everlights6_RGB.postUpdate(HSBType.fromRGB(252, 0, 255)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
Everlights_Chase.postUpdate(100) | |
} else if (Everlights_Preset.state == "St. Patrick's Day") { | |
Everlights_Count.postUpdate(3) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(0, 255, 65)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(0, 255, 65)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(0, 255, 0)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
Everlights_Chase.postUpdate(100) | |
} else if (Everlights_Preset.state == "Easter") { | |
Everlights_Count.postUpdate(5) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(253, 19, 255)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(249, 255, 32)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(255, 1, 65)) | |
Everlights4_RGB.postUpdate(HSBType.fromRGB(90, 255, 18)) | |
Everlights5_RGB.postUpdate(HSBType.fromRGB(41, 73, 255)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
gEverlightsExclusive.sendCommand(0) | |
} else if (Everlights_Preset.state == "Patriotic") { | |
Everlights_Count.postUpdate(6) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(0, 0, 255)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(255, 0, 0)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(255, 255, 255)) | |
Everlights4_RGB.postUpdate(HSBType.fromRGB(252, 0, 0)) | |
Everlights5_RGB.postUpdate(HSBType.fromRGB(0, 0, 255)) | |
Everlights6_RGB.postUpdate(HSBType.fromRGB(0, 0, 0)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
Everlights_Chase.postUpdate(100) | |
} else if (Everlights_Preset.state == "Halloween") { | |
Everlights_Count.postUpdate(3) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(255, 41, 0)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(255, 41, 0)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(115, 0, 255)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
gEverlightsExclusive.sendCommand(0) | |
} else if (Everlights_Preset.state == "Thanksgiving") { | |
Everlights_Count.postUpdate(4) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(255, 135, 33)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(255, 75, 0)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(153, 0, 0)) | |
Everlights4_RGB.postUpdate(HSBType.fromRGB(255, 75, 0)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
gEverlightsExclusive.sendCommand(0) | |
} else if (Everlights_Preset.state == "Christmas") { | |
Everlights_Count.postUpdate(4) | |
Everlights1_RGB.postUpdate(HSBType.fromRGB(255, 255, 255)) | |
Everlights2_RGB.postUpdate(HSBType.fromRGB(255, 0, 0)) | |
Everlights3_RGB.postUpdate(HSBType.fromRGB(255, 255, 255)) | |
Everlights4_RGB.postUpdate(HSBType.fromRGB(0, 176, 0)) | |
Everlights_Fade.postUpdate(0) | |
Everlights_Blink.postUpdate(0) | |
Everlights_Strobe.postUpdate(0) | |
gEverlightsExclusive.sendCommand(0) | |
} | |
EverlightsZone1_Data.postUpdate(executeCommandLine("/var/lib/openhab2/everlights.rb", 500)) | |
EverlightsZone2_Data.postUpdate(executeCommandLine("/var/lib/openhab2/everlights.rb --reverse", 500)) | |
Everlights_PatternChanging.postUpdate(OFF) | |
end |
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
Switch item=Everlights_Switch | |
Text label="Everlights Pattern" { | |
Frame label="Presets" { | |
Selection item=Everlights_Preset mappings=[ | |
""="---", | |
"Valentine's Day"="Valentine's Day", | |
"St. Patrick's Day"="St. Patrick's Day", | |
"Easter"="Easter", | |
"Patriotic"="Patriotic", | |
"Halloween"="Halloween", | |
"Thanksgiving"="Thanksgiving", | |
"Christmas"="Christmas"] | |
} | |
Frame label="Colors" { | |
Selection item=Everlights_Count mappings=[1="1", 2="2", 3="3", 4="4", 5="5", 6="6", 7="7", 8="8", 9="9", 10="10"] | |
Colorpicker item=Everlights1_RGB visibility=[Everlights_Count>=1] | |
Colorpicker item=Everlights2_RGB visibility=[Everlights_Count>=2] | |
Colorpicker item=Everlights3_RGB visibility=[Everlights_Count>=3] | |
Colorpicker item=Everlights4_RGB visibility=[Everlights_Count>=4] | |
Colorpicker item=Everlights5_RGB visibility=[Everlights_Count>=5] | |
Colorpicker item=Everlights6_RGB visibility=[Everlights_Count>=6] | |
Colorpicker item=Everlights7_RGB visibility=[Everlights_Count>=7] | |
Colorpicker item=Everlights8_RGB visibility=[Everlights_Count>=8] | |
Colorpicker item=Everlights9_RGB visibility=[Everlights_Count>=9] | |
Colorpicker item=Everlights10_RGB visibility=[Everlights_Count>=10] | |
} | |
Frame label="Mode" { | |
Slider item=Everlights_Twinkle | |
Slider item=Everlights_Fade | |
Slider item=Everlights_Blink | |
Slider item=Everlights_Strobe | |
Slider item=Everlights_Chase | |
Slider item=Everlights_ChaseReverse | |
Slider item=Everlights_Wipe | |
Slider item=Everlights_Random | |
} | |
} |
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
#!/usr/bin/env ruby | |
require 'cgi' | |
require 'holidays' | |
require 'json' | |
# keys are either a single value, or an array that's a range of two date_specs | |
# for values, it's the pattern name. if it's nil, match the holiday's name | |
# for date_specs, it can be a month and day, or it can be a holiday name. | |
# you can append + or - a number to the end of the string to do lights "around" | |
# a date | |
SCHEDULE = { | |
"Valentine's Day" => nil, | |
"St. Patrick's Day" => nil, | |
["Easter Sunday-1", "Easter Sunday"] => "Easter", | |
"Memorial Day" => "Patriotic", | |
["Independence Day-3", "Independence Day"] => "Patriotic", | |
["Jul 24-1", "Jul 24"] => "Patriotic", | |
["Halloween-7", "Halloween"] => nil, | |
["Thanksgiving-4", "Thanksgiving"] => nil, | |
["Thanksgiving+1", "Dec 31"] => "Christmas", | |
# can't go over the year boundary | |
"Jan 1" => "Christmas", | |
} | |
HOLIDAYS = Holidays.year_holidays([:us, :informal], Date.parse('Jan 1')).map { |x| [x[:name], x[:date]] }.to_h | |
def normalize_schedule(schedule) | |
schedule.map do |(dates, pattern)| | |
dates = [dates, dates] unless dates.is_a?(Array) | |
pattern ||= dates.last | |
[dates, pattern] | |
end.to_h | |
end | |
def identify_date(date_spec) | |
offset = 0 | |
if date_spec =~ /^(.+)([+-]\d+)$/ | |
offset = $2.to_i | |
date_spec = $1 | |
end | |
date = HOLIDAYS[date_spec] || Date.parse(date_spec) | |
date + offset | |
end | |
def dates_range(date_specs) | |
identify_date(date_specs.first)..identify_date(date_specs.last) | |
end | |
def search_schedule(date) | |
normalize_schedule(SCHEDULE).find { |(date_specs, pattern)| dates_range(date_specs).include?(date) }&.last | |
end | |
date = ARGV[0] ? Date.parse(ARGV[0]) : Date.today | |
puts search_schedule(date) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment