1
0
mirror of https://github.com/natekspencer/hacs-oasis_mini.git synced 2025-11-13 15:43:52 -05:00

13 Commits

Author SHA1 Message Date
Nathan Spencer
82a6a3cc1d Add temp fix for firmware 2.02 led issue 2025-03-13 04:32:44 +00:00
Nathan Spencer
e2f5727669 Merge pull request #59 from natekspencer/update-tracks
Update tracks
2025-03-12 22:31:45 -06:00
natekspencer
8650fd597a Update tracks 2025-03-12 19:16:35 +00:00
Nathan Spencer
7bef2cbe3b Merge pull request #58 from natekspencer/update-tracks
Update tracks
2025-03-11 15:17:35 -06:00
natekspencer
5ea472821b Update tracks 2025-03-11 19:17:53 +00:00
Nathan Spencer
ab09bde752 Merge pull request #57 from natekspencer/update-tracks
Update tracks
2025-03-09 13:13:57 -06:00
natekspencer
f49b8ce1d2 Update tracks 2025-03-09 19:12:34 +00:00
Nathan Spencer
cbbe8bc10d Merge pull request #56 from natekspencer/pre-commit
Add pre-commit
2025-03-09 11:11:21 -06:00
Nathan Spencer
c2c62bb875 Add pre-commit 2025-03-09 17:07:06 +00:00
Nathan Spencer
108b1850b7 Merge pull request #55 from natekspencer/devcontainer
Update devcontainer
2025-02-03 11:46:16 -07:00
Nathan Spencer
ffc74a9dcb Update devcontainer 2025-02-03 18:44:58 +00:00
Nathan Spencer
f67aee166a Merge pull request #54 from natekspencer/update-tracks
Update tracks
2025-02-02 12:15:58 -07:00
natekspencer
4ed6b1701d Update tracks 2025-02-02 19:15:01 +00:00
7 changed files with 451 additions and 21 deletions

View File

@@ -1,8 +1,8 @@
// See https://aka.ms/vscode-remote/devcontainer.json for format details.
{
"name": "Home Assistant integration development",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bullseye",
"postCreateCommand": "sudo apt-get update && sudo apt-get install libturbojpeg0 libpcap0.8 -y",
"image": "mcr.microsoft.com/devcontainers/python:1-3.13-bookworm",
"postCreateCommand": "scripts/setup",
"postAttachCommand": "scripts/setup",
"forwardPorts": [8123],
"customizations": {
@@ -26,7 +26,10 @@
"editor.codeActionsOnSave": {
"source.organizeImports": "always"
},
"files.trimTrailingWhitespace": true
"files.trimTrailingWhitespace": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff"
}
}
}
},

10
.pre-commit-config.yaml Normal file
View File

@@ -0,0 +1,10 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.9.10
hooks:
# Run the linter.
- id: ruff
args: [--fix]
# Run the formatter.
- id: ruff-format

View File

@@ -10,7 +10,7 @@ from urllib.parse import urljoin
from aiohttp import ClientResponseError, ClientSession
from .const import TRACKS
from .utils import _bit_to_bool, decrypt_svg_content
from .utils import _bit_to_bool, _parse_int, decrypt_svg_content
_LOGGER = logging.getLogger(__name__)
@@ -54,8 +54,8 @@ LED_EFFECTS: Final[dict[str, str]] = {
CLOUD_BASE_URL = "https://app.grounded.so"
BALL_SPEED_MAX: Final = 1000
BALL_SPEED_MIN: Final = 200
BALL_SPEED_MAX: Final = 400
BALL_SPEED_MIN: Final = 100
LED_SPEED_MAX: Final = 90
LED_SPEED_MIN: Final = -90
@@ -209,25 +209,29 @@ class OasisMini:
raw_status = await self._async_get(params={"GETSTATUS": ""})
_LOGGER.debug("Status: %s", raw_status)
values = raw_status.split(";")
playlist = [int(track) for track in values[3].split(",") if track]
playlist = [_parse_int(track) for track in values[3].split(",") if track]
shift = len(values) - 18 if len(values) > 17 else 0
status = {
"status_code": int(values[0]), # see status code map
"error": int(values[1]), # noqa: E501; error, 0 = none, and 10 = ?, 18 = can't download?
"ball_speed": int(values[2]), # 200 - 1000
"status_code": _parse_int(values[0]), # see status code map
"error": _parse_int(values[1]), # noqa: E501; error, 0 = none, and 10 = ?, 18 = can't download?
"ball_speed": _parse_int(values[2]), # 200 - 1000
"playlist": playlist,
"playlist_index": min(int(values[4]), len(playlist)), # index of above
"progress": int(values[5]), # 0 - max svg path
"playlist_index": min(_parse_int(values[4]), len(playlist)), # noqa: E501; index of above
"progress": _parse_int(values[5]), # 0 - max svg path
"led_effect": values[6], # led effect (code lookup)
"led_color_id": values[7], # led color id?
"led_speed": int(values[8]), # -90 - 90
"brightness": int(values[9]) if values[10] else 0, # noqa: E501; 0 - 200 in app, but seems to be 0 (off) to 304 (max), then repeats
"color": values[10] or None, # hex color code
"busy": _bit_to_bool(values[11]), # noqa: E501; device is busy (downloading track, centering, software update)?
"download_progress": int(values[12]),
"max_brightness": int(values[13]),
"wifi_connected": _bit_to_bool(values[14]),
"repeat_playlist": _bit_to_bool(values[15]),
"autoplay": AUTOPLAY_MAP.get(values[16]),
"led_speed": _parse_int(values[8]), # -90 - 90
"brightness": _parse_int(values[9]), # noqa: E501; 0 - 200 in app, but seems to be 0 (off) to 304 (max), then repeats
"color": values[10] if "#" in values[10] else None, # hex color code
"busy": _bit_to_bool(values[11 + shift]), # noqa: E501; device is busy (downloading track, centering, software update)?
"download_progress": _parse_int(values[12 + shift]),
"max_brightness": _parse_int(values[13 + shift]),
"wifi_connected": _bit_to_bool(values[14 + shift]),
"repeat_playlist": _bit_to_bool(values[15 + shift]),
"autoplay": AUTOPLAY_MAP.get(values[16 + shift]),
"autoclean": _bit_to_bool(values[17 + shift])
if len(values) > 17
else False,
}
for key, value in status.items():
if (old_value := getattr(self, key, None)) != value:

View File

@@ -266,6 +266,16 @@
"1": 6879
}
},
"7404": {
"id": 7404,
"name": "Axolotle",
"author": "Otávio Bittencourt",
"image": "2025/03/f64af5becf1924fc0699119a742a5f9f.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 33808
}
},
"5947": {
"id": 5947,
"name": "Baby Dino",
@@ -319,6 +329,16 @@
"1": 68353
}
},
"3515": {
"id": 3515,
"name": "Barracuda",
"author": "Luany Camila",
"image": "2024/09/604dcb2dbc036c4c49dc94e6c75f5cb9.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 9875
}
},
"194": {
"id": 194,
"name": "Bass",
@@ -383,6 +403,16 @@
},
"updated_at": "2024-08-04T15:58:47.000000Z"
},
"6765": {
"id": 6765,
"name": "Beautiful Geisha",
"author": "Otávio Bittencourt",
"image": "2025/01/3bdcb830fb6909ba5135ceb0f81a510c.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 53742
}
},
"168": {
"id": 168,
"name": "Betta Fish",
@@ -532,6 +562,16 @@
},
"updated_at": "2024-08-23T15:50:41.000000Z"
},
"2187": {
"id": 2187,
"name": "Cachalote",
"author": "Otávio Bittencourt",
"image": "2024/08/ac6a377297a052639da5f36d206bb557.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 44161
}
},
"58": {
"id": 58,
"name": "Camalion",
@@ -586,6 +626,16 @@
},
"updated_at": "2024-08-04T15:58:48.000000Z"
},
"7219": {
"id": 7219,
"name": "Chinese dragon",
"author": "Luany Camila",
"image": "2025/02/7499ca933049f6de7abe4fd76221ffb3.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 23348
}
},
"5087": {
"id": 5087,
"name": "Christmas Angel",
@@ -1246,6 +1296,16 @@
},
"updated_at": "2024-09-05T13:53:22.000000Z"
},
"7225": {
"id": 7225,
"name": "Drago jr.",
"author": "Otávio Bittencourt",
"image": "2025/02/62fa0a3bf27a1e7636d53246bfd6abd8.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 41881
}
},
"195": {
"id": 195,
"name": "Dragon",
@@ -1257,6 +1317,16 @@
},
"updated_at": "2024-08-04T15:58:56.000000Z"
},
"2118": {
"id": 2118,
"name": "Drums of Fate",
"author": "Anders",
"image": "2024/08/1978f6c6169d1f68c163aad94b8b1e95.svg",
"clean_pattern": 117,
"reduced_svg_content": {
"1": 30812
}
},
"193": {
"id": 193,
"name": "Duck",
@@ -1289,6 +1359,16 @@
},
"updated_at": "2024-08-04T15:58:54.000000Z"
},
"7255": {
"id": 7255,
"name": "Elf on a Bike",
"author": "Otávio Bittencourt",
"image": "2025/02/f3a0369934c1f0f1641a87e77129dfa6.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 34869
}
},
"129": {
"id": 129,
"name": "Engine Turn",
@@ -1629,6 +1709,16 @@
"1": 34208
}
},
"7100": {
"id": 7100,
"name": "Giraffe",
"author": "Otávio Bittencourt",
"image": "2025/02/05c566016b59e48110711e2dd4323a79.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 44743
}
},
"1777": {
"id": 1777,
"name": "Great Wave",
@@ -1804,6 +1894,16 @@
},
"updated_at": "2024-08-04T16:01:33.000000Z"
},
"7154": {
"id": 7154,
"name": "Heart with Wings",
"author": "Otávio Bittencourt",
"image": "2025/02/677a2ea86594860d7ec17d8cb3eb5352.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 24307
}
},
"356": {
"id": 356,
"name": "Hedgehog",
@@ -1986,6 +2086,16 @@
},
"updated_at": "2024-08-04T15:58:52.000000Z"
},
"5637": {
"id": 5637,
"name": "Jack in the box",
"author": "Luany Camila",
"image": "2024/12/7d8507f05918c13c709a9c05a72b78c1.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 20697
}
},
"238": {
"id": 238,
"name": "Jack Russell Terrier",
@@ -2029,6 +2139,16 @@
},
"updated_at": "2024-08-04T15:58:56.000000Z"
},
"7096": {
"id": 7096,
"name": "Kangaroo",
"author": "Otávio Bittencourt",
"image": "2025/02/24aed7f4d3b0be562bd2d5e8ec26a774.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 43094
}
},
"2796": {
"id": 2796,
"name": "Killer Wale",
@@ -2039,6 +2159,16 @@
"1": 42409
}
},
"7138": {
"id": 7138,
"name": "Kitty Playing with Yarn",
"author": "Otávio Bittencourt",
"image": "2025/02/03d03c3a6b5ec3df9a3712ecafd1b39d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 79176
}
},
"239": {
"id": 239,
"name": "Kobra",
@@ -2273,6 +2403,16 @@
"1": 20347
}
},
"7417": {
"id": 7417,
"name": "Manta Ray",
"author": "Otávio Bittencourt",
"image": "2025/03/8a4f9fe0bf4a17ea40013961ba8f1b2d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 10011
}
},
"339": {
"id": 339,
"name": "Marmoset Monkey",
@@ -2295,6 +2435,16 @@
},
"updated_at": "2024-08-04T15:59:00.000000Z"
},
"7211": {
"id": 7211,
"name": "Mindfulness",
"author": "Otávio Bittencourt",
"image": "2025/02/0283bb411e5ff892bf8b5940793aeedd.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 39419
}
},
"78": {
"id": 78,
"name": "Mini Bouquet",
@@ -2348,6 +2498,16 @@
"1": 6986
}
},
"7028": {
"id": 7028,
"name": "Mosasaur",
"author": "Otávio Bittencourt",
"image": "2025/02/e9158184556f47f56a97e5f11e352a0d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 36811
}
},
"202": {
"id": 202,
"name": "Moth",
@@ -2692,6 +2852,16 @@
"1": 60547
}
},
"7268": {
"id": 7268,
"name": "Playful Little Robot",
"author": "Otávio Bittencourt",
"image": "2025/02/7ac44b24ff9cff01130cb0cb1309e7f0.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 36853
}
},
"1049": {
"id": 1049,
"name": "PolarValentine",
@@ -2868,6 +3038,16 @@
"1": 33471
}
},
"6778": {
"id": 6778,
"name": "Robot with a flower",
"author": "Luany Camila",
"image": "2025/01/a28339205d4c9837241f69064ba48adc.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 36372
}
},
"210": {
"id": 210,
"name": "Rocket",
@@ -2889,6 +3069,16 @@
"1": 29953
}
},
"6614": {
"id": 6614,
"name": "Romantic Valentine Kiss",
"author": "Otávio Bittencourt",
"image": "2025/01/05651f308ce8c114041eb9f46f3b01c4.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 41462
}
},
"105": {
"id": 105,
"name": "Rooster",
@@ -2951,6 +3141,26 @@
"1": 15406
}
},
"7304": {
"id": 7304,
"name": "Sakura Ryu",
"author": "Otávio Bittencourt",
"image": "2025/03/1edf5f98df8ea2fec430efbb82392f2d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 51520
}
},
"6787": {
"id": 6787,
"name": "Samurai",
"author": "Otávio Bittencourt",
"image": "2025/01/c4722369a149e42d7d8a19db37377380.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 72807
}
},
"4580": {
"id": 4580,
"name": "Santa Claus",
@@ -3194,6 +3404,26 @@
"1": 28533
}
},
"5952": {
"id": 5952,
"name": "Skateasaurus",
"author": "Luany Camila",
"image": "2024/12/050d6aec400597aa7831ace7909207f1.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 20864
}
},
"7190": {
"id": 7190,
"name": "Skating Fairy",
"author": "Otávio Bittencourt",
"image": "2025/02/ea3e536c4458d0ca2aab281da553545b.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 44630
}
},
"209": {
"id": 209,
"name": "Skull",
@@ -3259,6 +3489,16 @@
},
"updated_at": "2024-08-04T15:59:33.000000Z"
},
"7377": {
"id": 7377,
"name": "Snake Chinese Year",
"author": "Otávio Bittencourt",
"image": "2025/03/4a071f3f90ea12025241dd7d1044d651.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 24568
}
},
"551": {
"id": 551,
"name": "snowflake",
@@ -3291,6 +3531,16 @@
"1": 4116
}
},
"5564": {
"id": 5564,
"name": "SnowFlake (C C)",
"author": "RiverRatDC",
"image": "2024/12/3f5e5f460465ab17ea0003826ac3ded5.svg",
"clean_pattern": null,
"reduced_svg_content": {
"1": 26547
}
},
"4803": {
"id": 4803,
"name": "Snowman Frosty",
@@ -3374,6 +3624,16 @@
"1": 6404
}
},
"6609": {
"id": 6609,
"name": "Spinosaurus",
"author": "Otávio Bittencourt",
"image": "2025/01/aa915de291b74a4a625402d4c6cf0ab7.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 70140
}
},
"1695": {
"id": 1695,
"name": "spiral",
@@ -3808,6 +4068,16 @@
},
"updated_at": "2024-08-23T16:00:00.000000Z"
},
"6739": {
"id": 6739,
"name": "Stellar Sea Lion over the Rocks",
"author": "Otávio Bittencourt",
"image": "2025/01/df3917677652ff73b194c8a34d773402.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 53595
}
},
"115": {
"id": 115,
"name": "String ray",
@@ -3904,6 +4174,26 @@
},
"updated_at": "2024-08-04T15:58:54.000000Z"
},
"7276": {
"id": 7276,
"name": "Takeshi Ren",
"author": "Otávio Bittencourt",
"image": "2025/02/72d29db6dcdef850cc37c2721216989c.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 55111
}
},
"7325": {
"id": 7325,
"name": "Tango the pango",
"author": "Otávio Bittencourt",
"image": "2025/03/42477ad4a8b1d08cb7fc34e9ad4f8314.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 35762
}
},
"5729": {
"id": 5729,
"name": "The Baby Cat",
@@ -3914,6 +4204,36 @@
"1": 58681
}
},
"5728": {
"id": 5728,
"name": "The Baby Cat",
"author": "Otávio Bittencourt",
"image": "2024/12/2d01ed84e45f5366ff8977e4c18f9df3.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 58681
}
},
"6998": {
"id": 6998,
"name": "The Camel",
"author": "Otávio Bittencourt",
"image": "2025/01/8ff29f5fa10c0b5213115ae8ebfaa87d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 61839
}
},
"6992": {
"id": 6992,
"name": "The Frog",
"author": "Otávio Bittencourt",
"image": "2025/01/8d46682ac8cb96fd1dc7e6c425b5da73.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 56023
}
},
"223": {
"id": 223,
"name": "The Knot",
@@ -4228,6 +4548,16 @@
},
"updated_at": "2024-08-04T15:58:49.000000Z"
},
"2207": {
"id": 2207,
"name": "UConn",
"author": "JeffDLowe",
"image": "2024/08/841e0c9b75cbe33f152672f76d8909b6.svg",
"clean_pattern": null,
"reduced_svg_content": {
"1": 23086
}
},
"218": {
"id": 218,
"name": "Unicorn",
@@ -4259,6 +4589,36 @@
"1": 60236
}
},
"6810": {
"id": 6810,
"name": "Valentines Heart-Shaped Box",
"author": "Otávio Bittencourt",
"image": "2025/01/ecb41379a6cf281dbed0b95d4e4b8126.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 63975
}
},
"7029": {
"id": 7029,
"name": "Valentines Moon",
"author": "Otávio Bittencourt",
"image": "2025/02/96d1d52db7f234a78913e53a003129cd.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 39111
}
},
"6594": {
"id": 6594,
"name": "Velociraptor",
"author": "Otávio Bittencourt",
"image": "2025/01/53a5ff36f6b4b06df954601622c6b1a3.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 49603
}
},
"2116": {
"id": 2116,
"name": "Void of Death",
@@ -4362,6 +4722,16 @@
"1": 2310
}
},
"2146": {
"id": 2146,
"name": "Warped Waves",
"author": "Crystal James",
"image": "2024/08/794b3a39e45f75fd487728e5cf9fb1ed.svg",
"clean_pattern": null,
"reduced_svg_content": {
"1": 17243
}
},
"555": {
"id": 555,
"name": "Wavy dude",
@@ -4476,6 +4846,16 @@
"1": 42218
}
},
"7221": {
"id": 7221,
"name": "Winter Sand",
"author": "000843.bf34f133184943939b950674aaaa4ac9.2327",
"image": "2025/02/48f5d7a080145e4f8442eb0b1b5f3872.svg",
"clean_pattern": null,
"reduced_svg_content": {
"1": 17842
}
},
"500": {
"id": 500,
"name": "Wipe Left to Right",
@@ -4613,6 +4993,16 @@
"1": 37914
}
},
"7233": {
"id": 7233,
"name": "Yoga Tree Pose",
"author": "Otávio Bittencourt",
"image": "2025/02/cc38fea088324f283faaaebe1feef4d9.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 51214
}
},
"437": {
"id": 437,
"name": "Yorkshire",
@@ -4623,5 +5013,15 @@
"1": 23212
},
"updated_at": "2024-08-04T16:01:31.000000Z"
},
"4014": {
"id": 4014,
"name": "Zombie",
"author": "Luany Camila",
"image": "2024/09/3a42cbf8da47cf3a922fab6246093d2d.svg",
"clean_pattern": 119,
"reduced_svg_content": {
"1": 21411
}
}
}

View File

@@ -26,6 +26,14 @@ def _bit_to_bool(val: str) -> bool:
return val == "1"
def _parse_int(val: str) -> int:
"""Convert an int string to int."""
try:
return int(val)
except Exception:
return 0
def draw_svg(track: dict, progress: int, model_id: str) -> str | None:
"""Draw SVG."""
if track and (svg_content := track.get("svg_content")):

View File

@@ -10,4 +10,5 @@ cryptography # should already be installed with Home Assistant
# Development
colorlog
pip>=21.0
pre-commit
ruff

View File

@@ -1,9 +1,13 @@
#!/usr/bin/env bash
sudo apt-get update && sudo apt-get install libturbojpeg0 libpcap0.8 -y
set -e
cd "$(dirname "$0")/.."
python3 -m pip install --requirement requirements.txt --upgrade
pre-commit install
mkdir -p config