-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
882 additions
and
796 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import std/httpclient | ||
import std/strformat | ||
import std/terminal | ||
import std/json | ||
|
||
import puppy | ||
|
||
import ../common | ||
|
||
proc brightness*(device: int = 0; brightness = -1; output: bool = on): int = | ||
## Set device brightness | ||
|
||
if not isSetup(output) or not checkDevices(device, output = output): return | ||
|
||
let | ||
apiKey = readFile(keyFile) | ||
devices = parseJson readFile(devicesFile) | ||
(deviceAddr, model) = getDeviceInfo(devices, device) | ||
|
||
if brightness == -1: # if brightness is default value | ||
let response = getDeviceState(deviceAddr, model, apiKey) | ||
|
||
if output: | ||
echo fmt"Device {device} brightness: ", response["data"]["properties"][2]["brightness"].getInt(), '%' | ||
|
||
return response["data"]["properties"][2]["brightness"].getInt() | ||
|
||
if brightness notin 1..100 : | ||
if output: | ||
error "Invalid brightness, is not in the range 1-100" | ||
|
||
return | ||
|
||
let body = %* { | ||
"device": deviceAddr, | ||
"model": model, | ||
"cmd": { | ||
"name": "brightness", | ||
"value": brightness | ||
} | ||
} | ||
|
||
let re = put(ControlURI, @{"Govee-API-Key": apiKey, "Content-Type": "application/json"}, $body) | ||
|
||
if output: | ||
sendCompletionMsg re.code, parseJson(re.body)["message"], HttpCode(re.code) | ||
|
||
return brightness |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import std/httpclient | ||
import std/strformat | ||
import std/strutils | ||
import std/terminal | ||
import std/random | ||
import std/colors | ||
import std/json | ||
|
||
import puppy | ||
|
||
import ../common | ||
|
||
proc color*(device: int = 0; color: string = ""; output: bool = on): string = | ||
## Set device color with an HTML/hex color code. | ||
## NOTE: when called with no parameters, the device's current color will be #000000 if: | ||
## | ||
## 1. Music mode is on. | ||
## 2. color temperature is not 0. | ||
## 3. A scene is playing on the device. | ||
|
||
if not isSetup(output) or not checkDevices(device, output = output): return | ||
|
||
let | ||
apiKey = readFile(keyFile) | ||
devices = parseJson readFile(devicesFile) | ||
(deviceAddr, model) = getDeviceInfo(devices, device) | ||
|
||
var | ||
color = color.replace(" ").replace("-").normalize() | ||
colorJson = %* {"r": 0, "g": 0, "b": 0} | ||
r, g, b: int | ||
|
||
if color == "": | ||
let response = getDeviceState(deviceAddr, model, apiKey) | ||
|
||
try: | ||
colorJson = response["data"]["properties"][3]["color"] | ||
except KeyError: discard | ||
|
||
let | ||
color = $rgb( | ||
colorJson["r"].getInt(), | ||
colorJson["g"].getInt(), | ||
colorJson["b"].getInt() | ||
) | ||
|
||
if output: | ||
echo fmt"Device {device} color: ", colorToAnsi(parseColor(color)), color, esc | ||
|
||
return color | ||
|
||
block checks: | ||
if color notin ["random", "rand"]: | ||
if color.isColor(): | ||
color = $color.parseColor() | ||
break checks | ||
|
||
if color[0] != '#': | ||
color = '#' & color | ||
|
||
if not color.isColor(): | ||
if output: | ||
error fmt"{color[1..^1]} is an invalid color." | ||
|
||
return | ||
|
||
if color in ["random", "rand"]: | ||
r = rand(255) | ||
g = rand(255) | ||
b = rand(255) | ||
else: | ||
(r, g, b) = parseColor(color).extractRGB() | ||
|
||
let body = %* { | ||
"device": deviceAddr, | ||
"model": model, | ||
"cmd": { | ||
"name": "color", | ||
"value": { | ||
"r": r, | ||
"g": g, | ||
"b": b | ||
} | ||
} | ||
} | ||
|
||
let re = put(ControlURI, @{"Govee-API-Key": apiKey, "Content-Type": "application/json"}, $body) | ||
|
||
if output: | ||
echo fmt"Set device {device}'s color to ", colorToAnsi(rgb(r, g, b)), rgb(r, g, b), esc, '\n' | ||
|
||
sendCompletionMsg re.code, parseJson(re.body)["message"], HttpCode(re.code) | ||
|
||
return color |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import std/httpclient | ||
import std/strformat | ||
import std/terminal | ||
import std/json | ||
import std/math | ||
|
||
import puppy | ||
|
||
import ../common | ||
|
||
func kelvinToRgb*(temp: int): tuple[r, g, b: range[0..255]] = | ||
## Converts color temperature to rgb | ||
|
||
# Algorithm from https://tannerhelland.com/2012/09/18/convert-temperature-rgb-algorithm-code.html | ||
|
||
let temp = temp.clamp(1000, 40000) / 100 | ||
|
||
if temp <= 66: | ||
result.r = 255 | ||
result.g = int (99.4708025861 * ln(temp) - 161.1195681661).clamp(0.0, 255.0) | ||
else: | ||
result.r = int (329.698727446 * (pow(temp - 60, -0.1332047592))).clamp(0.0, 255.0) | ||
result.g = int (288.1221695283 * (pow(temp - 60, -0.0755148492))).clamp(0.0, 255.0) | ||
|
||
if temp >= 66: | ||
result.b = 255 | ||
elif temp <= 19: | ||
result.b = 0 | ||
else: | ||
result.b = int (138.5177312231 * ln(temp - 10) - 305.0447927307).clamp(0.0, 255.0) | ||
|
||
proc colorTemp*(device: int = 0; output: bool = on; temperature: int = -1): int = | ||
## Set device color temperature in kelvin | ||
|
||
if not isSetup(output) or not checkDevices(device, output = output): return | ||
|
||
let | ||
apiKey = readFile(keyFile) | ||
devices = parseJson readFile(devicesFile) | ||
(deviceAddr, model) = getDeviceInfo(devices, device) | ||
|
||
if temperature == -1: | ||
let | ||
response = getDeviceState(deviceAddr, model, apiKey) | ||
|
||
temp = response["data"]["properties"][3]["colorTemInKelvin"].getInt(0) | ||
|
||
ansi = colorToAnsi(kelvinToRgb(temp)) | ||
|
||
if output: | ||
echo fmt"Device {device}'s color temperature is ", ansi, temp, 'K', esc | ||
|
||
return temp | ||
|
||
let | ||
jsonColorTemRange = devices[device]["properties"]["colorTem"]["range"] | ||
colorTemRange = jsonColorTemRange["min"].getInt() .. jsonColorTemRange["max"].getInt() | ||
|
||
if temperature notin colorTemRange: | ||
if output: | ||
# .a is slice lower bound, .b is slice upper bound | ||
error fmt"Color temperature {temperature}K out of supported range: {colorTemRange.a}K-{colorTemRange.b}K" | ||
|
||
return | ||
|
||
let body = %* { | ||
"device": deviceAddr, | ||
"model": model, | ||
"cmd": { | ||
"name": "colorTem", | ||
"value": temperature | ||
} | ||
} | ||
|
||
let | ||
re = put(ControlURI, @{"Govee-API-Key": apiKey, "Content-Type": "application/json"}, $body) | ||
|
||
ccolor = colorToAnsi(kelvinToRgb(temperature)) | ||
|
||
if output: | ||
echo fmt"Set device {device}'s color temperature to {ccolor}{temperature}K{esc}", '\n' | ||
|
||
sendCompletionMsg re.code, parseJson(re.body)["message"], HttpCode(re.code) | ||
|
||
return temperature |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import std/strutils | ||
import std/terminal | ||
import std/sugar | ||
import std/json | ||
|
||
import ../common | ||
|
||
proc devices* = | ||
## Get list of devices and their properties | ||
|
||
if not isSetup(true): return | ||
|
||
let devices = parseJson readFile(devicesFile) | ||
|
||
for dev, i in devices.getElems(): | ||
let | ||
cmds = collect(for i in i["supportCmds"]: i.getStr()) | ||
## seq of all supported commands of the device | ||
|
||
echo "\e[1m", "DEVICE ", $dev, ansiResetCode | ||
echo " Mac Address: ", i["device"].getStr() | ||
echo " Model: ", i["model"].getStr() | ||
echo " Device Name: ", i["deviceName"].getStr() | ||
echo " Controllable: ", capitalizeAscii($(i["controllable"].getBool())) | ||
echo " Retrievable: ", capitalizeAscii($(i["retrievable"].getBool())) | ||
echo " Supported Commands: ", cmds.join(", "), "\n" |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
## other, kinda-related commands that don't do much | ||
|
||
import std/browsers | ||
|
||
import puppy | ||
|
||
import ../common | ||
|
||
proc version* = | ||
## Get Nova current version | ||
|
||
echo "Nova ", Version | ||
|
||
proc about* = | ||
## Nova about | ||
|
||
echo "Nova ", Version, '\n' | ||
echo Description | ||
echo "Made by ", Author, '.' | ||
|
||
proc description* = | ||
## Prints Nova's description | ||
|
||
echo Description | ||
|
||
proc source* = | ||
## View Nova's source code | ||
|
||
openDefaultBrowser("https://github.com/neroist/nova/blob/main/src/nova.nim") | ||
|
||
proc repo* = | ||
## View Nova's GitHub repository | ||
|
||
openDefaultBrowser("https://github.com/neroist/nova/") | ||
|
||
proc license*(browser: bool = false) = | ||
## View Nova's license | ||
|
||
if browser: | ||
openDefaultBrowser("https://github.com/neroist/nova/blob/main/LICENSE") | ||
else: | ||
echo fetch("https://raw.githubusercontent.com/neroist/nova/main/LICENSE") | ||
|
||
proc docs* = | ||
## View Nova's documentation | ||
|
||
openDefaultBrowser("https://neroist.github.io/nova/") |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import std/strutils | ||
import std/random | ||
import std/colors | ||
|
||
import tinydialogs | ||
|
||
import ../common | ||
import ./color | ||
|
||
proc picker*(device: int = 0; setProperty: bool = true; output: bool = on) = | ||
## Pick a color through a GUI (your OS's default color picker dialog) | ||
|
||
let | ||
pickedColor = colorChooser( | ||
"Pick a color", | ||
[rand(0..255).byte, rand(0..255).byte, rand(0..255).byte] | ||
) | ||
|
||
if output: | ||
echo "Picked ", colorToAnsi(parseColor(pickedColor.hex)), toUpper pickedColor.hex, esc | ||
|
||
if setProperty: | ||
if output: echo "" | ||
|
||
discard color(device, pickedColor.hex, output) | ||
|
Oops, something went wrong.