Closed galletn closed 5 months ago
@galletn , I setup mitmproxy and managed to capture turning the robot on and off. It looks like its all websocket traffic which means Im a little out of my depth. I am however happy to work with you to provide you with the capture and also to test if that is helpful?
Here is where the coms changed to websocket
GET /devices HTTP/1.1
Host: prod-socket.zodiac-io.com
Sec-WebSocket-Key:
Sec-WebSocket-Version: 13
Upgrade: websocket
Origin: https://prod-socket.zodiac-io.com
Authorization: <Authorization>
Connection: Upgrade
content-length: 0
HTTP/1.1 101 Switching Protocols
Date: Mon, 22 May 2023 10:51:20 GMT
Connection: upgrade
upgrade: websocket
sec-websocket-accept:
content-length: 0
Here is the redacted websocket messages. Ive replaced userID, robot serial number and other serial/part numbers
SEND-->
{
"action": "subscribe",
"namespace": "authorization",
"payload": {
"userId": $USERID$
},
"service": "Authorization",
"target": "$ROBOTSERIALNUMBER$",
"version": 1
}
RECIEVE <--
{
"namespace": "authorization",
"payload": {
"data": [
{
"accelero": [
-85,
-31,
1049
],
"angleRotation": 183,
"cleanerPos": 1,
"cumulAngleRotation": 502,
"cycleId": 1684646687,
"floorBlockageCnt": 0,
"gyro": [
1,
-2,
1
],
"iPump": 2442,
"iTract1": 99,
"iTract2": 109,
"lastMoveLength": 13,
"loopCnt": 200,
"magneto": [
0,
0,
0
],
"movementId": 1,
"patternId": 0,
"pwmPump": 100,
"pwmTract1": 80,
"pwmTract2": 80,
"stairsCnt": 1764,
"tiltCnt": 32692,
"timestamp": 1684650932,
"totalHours": 348,
"vEbox": 28,
"vRobot": 28,
"vSensor": 11,
"wallCnt": 1660
}
],
"ota": {
"status": "UP_TO_DATE"
},
"robot": {
"metadata": {
"desired": {
"equipment": {
"robot": {}
}
},
"reported": {
"aws": {
"session_id": {
"timestamp": 1684751732
},
"status": {
"timestamp": 1684751732
},
"timestamp": {
"timestamp": 1684751732
}
},
"dt": {
"timestamp": 1681926072
},
"eboxData": {
"completeCleanerPn": {
"timestamp": 1681926072
},
"completeCleanerSn": {
"timestamp": 1681926072
},
"controlBoxPn": {
"timestamp": 1681926072
},
"controlBoxSn": {
"timestamp": 1681926072
},
"motorBlockSn": {
"timestamp": 1681926072
},
"powerSupplySn": {
"timestamp": 1681926072
},
"sensorBlockSn": {
"timestamp": 1681926072
}
},
"equipment": {
"robot": {
"canister": {
"timestamp": 1684571511
},
"customCyc": {
"timestamp": 1681926072
},
"customIntensity": {
"timestamp": 1681926072
},
"cycleStartTime": {
"timestamp": 1684752278
},
"durations": {
"customTim": {
"timestamp": 1681926072
},
"deepTim": {
"timestamp": 1681926072
},
"firstSmartTim": {
"timestamp": 1681926072
},
"quickTim": {
"timestamp": 1681926072
},
"smartTim": {
"timestamp": 1681926072
},
"waterTim": {
"timestamp": 1681926072
}
},
"equipmentId": {
"timestamp": 1681926073
},
"errorCode": {
"timestamp": 1681926072
},
"errorState": {
"timestamp": 1681926072
},
"firstSmrtFlag": {
"timestamp": 1681926072
},
"liftControl": {
"timestamp": 1681926072
},
"logger": {
"timestamp": 1681926072
},
"prCyc": {
"timestamp": 1684752605
},
"repeat": {
"timestamp": 1681926072
},
"rmt_ctrl": {
"timestamp": 1681926072
},
"scanTimeDuration": {
"timestamp": 1681926072
},
"schConf0Enable": {
"timestamp": 1681926072
},
"schConf0Hour": {
"timestamp": 1681926072
},
"schConf0Min": {
"timestamp": 1681926072
},
"schConf0Prt": {
"timestamp": 1681926072
},
"schConf0WDay": {
"timestamp": 1681926072
},
"schConf1Enable": {
"timestamp": 1681926072
},
"schConf1Hour": {
"timestamp": 1681926072
},
"schConf1Min": {
"timestamp": 1681926072
},
"schConf1Prt": {
"timestamp": 1681926072
},
"schConf1WDay": {
"timestamp": 1681926072
},
"schConf2Enable": {
"timestamp": 1681926072
},
"schConf2Hour": {
"timestamp": 1681926072
},
"schConf2Min": {
"timestamp": 1681926072
},
"schConf2Prt": {
"timestamp": 1681926072
},
"schConf2WDay": {
"timestamp": 1681926072
},
"schConf3Enable": {
"timestamp": 1681926072
},
"schConf3Hour": {
"timestamp": 1681926072
},
"schConf3Min": {
"timestamp": 1681926072
},
"schConf3Prt": {
"timestamp": 1681926072
},
"schConf3WDay": {
"timestamp": 1681926072
},
"schConf4Enable": {
"timestamp": 1681926072
},
"schConf4Hour": {
"timestamp": 1681926072
},
"schConf4Min": {
"timestamp": 1681926072
},
"schConf4Prt": {
"timestamp": 1681926072
},
"schConf4WDay": {
"timestamp": 1681926072
},
"schConf5Enable": {
"timestamp": 1681926072
},
"schConf5Hour": {
"timestamp": 1681926072
},
"schConf5Min": {
"timestamp": 1681926072
},
"schConf5Prt": {
"timestamp": 1681926072
},
"schConf5WDay": {
"timestamp": 1681926072
},
"schConf6Enable": {
"timestamp": 1681926072
},
"schConf6Hour": {
"timestamp": 1681926072
},
"schConf6Min": {
"timestamp": 1681926072
},
"schConf6Prt": {
"timestamp": 1681926072
},
"schConf6WDay": {
"timestamp": 1681926072
},
"sensors": {
"sns_1": {
"state": {
"timestamp": 1684752306
},
"type": {
"timestamp": 1681926072
}
},
"sns_2": {
"state": {
"timestamp": 1684752306
},
"type": {
"timestamp": 1681926072
}
},
"sns_3": {
"state": {
"timestamp": 1681926072
},
"type": {
"timestamp": 1681926072
}
}
},
"state": {
"timestamp": 1684752605
},
"stepper": {
"timestamp": 1681926072
},
"stepperAdjTime": {
"timestamp": 1681926072
},
"totalHours": {
"timestamp": 1684752280
},
"vr": {
"timestamp": 1681926073
}
}
},
"jobId": {
"timestamp": 1651189088
},
"sn": {
"timestamp": 1681926072
},
"vr": {
"timestamp": 1681926072
}
}
},
"state": {
"desired": {
"equipment": {
"robot": {}
}
},
"reported": {
"aws": {
"session_id": "7d0137d2-06bd-45f4-8be9-e3f503886d65",
"status": "connected",
"timestamp": 1684751732835
},
"dt": "vr",
"eboxData": {
"completeCleanerPn": "${some-part-number}",
"completeCleanerSn": "${some-serial-number}",
"controlBoxPn": "${some-part-number}",
"controlBoxSn": "${some-serial-number}",
"motorBlockSn": "${some-serial-number}",
"powerSupplySn": "${some-serial-number}",
"sensorBlockSn": ""
},
"equipment": {
"robot": {
"canister": 0,
"customCyc": 1,
"customIntensity": 0,
"cycleStartTime": 1684752276,
"durations": {
"customTim": 150,
"deepTim": 165,
"firstSmartTim": 150,
"quickTim": 75,
"smartTim": 111,
"waterTim": 45
},
"equipmentId": "JY21",
"errorCode": 0,
"errorState": 0,
"firstSmrtFlag": 0,
"liftControl": 0,
"logger": 0,
"prCyc": 1,
"repeat": 0,
"rmt_ctrl": 0,
"scanTimeDuration": 30,
"schConf0Enable": 0,
"schConf0Hour": 0,
"schConf0Min": 0,
"schConf0Prt": 1,
"schConf0WDay": 0,
"schConf1Enable": 0,
"schConf1Hour": 0,
"schConf1Min": 0,
"schConf1Prt": 1,
"schConf1WDay": 1,
"schConf2Enable": 0,
"schConf2Hour": 0,
"schConf2Min": 0,
"schConf2Prt": 1,
"schConf2WDay": 2,
"schConf3Enable": 0,
"schConf3Hour": 0,
"schConf3Min": 0,
"schConf3Prt": 1,
"schConf3WDay": 3,
"schConf4Enable": 0,
"schConf4Hour": 0,
"schConf4Min": 0,
"schConf4Prt": 1,
"schConf4WDay": 4,
"schConf5Enable": 0,
"schConf5Hour": 0,
"schConf5Min": 0,
"schConf5Prt": 1,
"schConf5WDay": 5,
"schConf6Enable": 0,
"schConf6Hour": 0,
"schConf6Min": 0,
"schConf6Prt": 1,
"schConf6WDay": 6,
"sensors": {
"sns_1": {
"state": 0,
"type": "temperature"
},
"sns_2": {
"state": 0,
"type": "pressure"
},
"sns_3": {
"state": 0,
"type": "compass"
}
},
"state": 0,
"stepper": 0,
"stepperAdjTime": 15,
"totalHours": 349,
"vr": "V32E47"
}
},
"jobId": "Job_VR_V32E47_V32C47",
"sn": "$ROBOTSERIALNUMBER$",
"vr": "V32C47"
}
},
"timestamp": 1684752680,
"version": 138294
}
},
"service": "Authorization",
"target": "$ROBOTSERIALNUMBER$"
}
SEND --> (start clean cycle on the app)
{
"action": "setCleanerState",
"namespace": "vr",
"payload": {
"clientToken": "$USERID$|",
"state": {
"desired": {
"equipment": {
"robot": {
"state": 1
}
}
}
}
},
"service": "StateController",
"target": "$ROBOTSERIALNUMBER$",
"version": 1
}
notice state:1
RECIEVE <-- (a bunch of these)
{
"event": "StateReported",
"payload": {
"clientToken": "$USERID$|",
"metadata": {
"desired": {
"equipment": {
"robot": {
"state": {
"timestamp": 1684752688
}
}
}
}
},
"state": {
"desired": {
"equipment": {
"robot": {
"state": 1
}
}
}
},
"timestamp": 1684752688,
"version": 138295
},
"service": "StateStreamer",
"target": "$ROBOTSERIALNUMBER$",
"version": 1
}
SEND --> (stop clean cycle on the app)
{
"action": "setCleanerState",
"namespace": "vr",
"payload": {
"clientToken": "$USERID$|",
"state": {
"desired": {
"equipment": {
"robot": {
"state": 0
}
}
}
}
},
"service": "StateController",
"target": "$ROBOTSERIALNUMBER$",
"version": 1
}
notice state: 0
RECIEVE <-- (a bunch of these)
{
"event": "StateReported",
"payload": {
"clientToken": "$USERID$|",
"metadata": {
"desired": {
"equipment": {
"robot": {
"state": {
"timestamp": 1684752705
}
}
}
}
},
"state": {
"desired": {
"equipment": {
"robot": {
"state": 0
}
}
}
},
"timestamp": 1684752705,
"version": 138300
},
"service": "StateStreamer",
"target": "$ROBOTSERIALNUMBER$",
"version": 1
}
Let me know if you need more as I have everything set up and ready to capture more traffic.
removed a few authorization and key hashes to make sure no one gets any password of yours đź‘Ť
looks like this is what we need to try:
https://websocket-client.readthedocs.io/en/latest/examples.html
I'll see when I can test it out.
moved some posts to new issues to deal with them separately to start/stop functionality.
I found some GO code here for the iAqualink websocket connection and tried to convert. Is this helpful;
import json
import time
import random
import websocket
import contextlib
import logging
from websocket._abnf import ABNF
APIKey = "EOOEMOW4YR6QNB07"
IAquaLinkAPIBase = "https://r-api.iaqualink.net"
WebSocketAPIBase = "https://prod-socket.zodiac-io.com"
ZodiacAPIBase = "https://prod.zodiac-io.com"
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
class DeviceWebSocketInputSubscribePayload:
def __init__(self, UserID):
self.UserID = UserID
class DeviceWebSocketInputSetStatePayload:
def __init__(self, state, ClientToken):
self.State = state
self.ClientToken = ClientToken
class DeviceWebSocketInput:
def __init__(self, Version, Action, Namespace, Service, Target, Payload):
self.Version = Version
self.Action = Action
self.Namespace = Namespace
self.Service = Service
self.Target = Target
self.Payload = Payload
class DeviceWebSocketOutputSubscribePayload:
def __init__(self, Robot):
self.Robot = Robot
class DeviceWebSocketOutput:
def __init__(self, Event, Service, Target, Payload):
self.Event = Event
self.Service = Service
self.Target = Target
self.Payload = Payload
class Client:
def __init__(self):
self.IAquaLinkAPIBase = IAquaLinkAPIBase
self.WebSocketAPIBase = WebSocketAPIBase
self.ZodiacAPIBase = ZodiacAPIBase
self.APIKey = APIKey
self.AuthenticationToken = None
self.IDToken = None
self.UserID = None
self.websocket = None
def login(self, username, password):
# Same as the login method in the Go code
def device_web_socket(self, deviceID, actions):
self.init()
url = self.WebSocketAPIBase.replace("https://", "wss://") + "/devices"
header = ["Authorization: " + self.IDToken]
logger.debug("Connecting to Web Socket: %s", url)
self.websocket = websocket.WebSocket()
self.websocket.connect(url, header=header)
userId = int(self.UserID)
logger.debug("User ID: %d", userId)
output = {}
subscribeInput = DeviceWebSocketInput(
Version=1,
Action="subscribe",
Namespace="authorization",
Service="Authorization",
Target=deviceID,
Payload=DeviceWebSocketInputSubscribePayload(userId)
)
def json_to_string(value):
contents = json.dumps(subscribeInput.__dict__)
return contents
logger.debug("Writing: %s", json_to_string(subscribeInput))
self.websocket.send(json_to_string(subscribeInput))
with contextlib.suppress(Exception):
while True:
contents = self.websocket.recv()
logger.debug("Received: %s", contents)
if len(contents) == 0:
time.sleep(0.1)
continue
subscribeOutput = json.loads(contents)
if subscribeOutput["Service"] != subscribeInput.Service:
logger.debug("Service does not match: got %s (expected %s)", subscribeOutput["Service"], subscribeInput.Service)
continue
if subscribeOutput["Namespace"] != subscribeInput.Namespace:
logger.debug("Namespace does not match: got %s (expected %s)", subscribeOutput["Namespace"], subscribeInput.Namespace)
continue
if subscribeOutput["Target"] != subscribeInput.Target:
logger.debug("Target does not match: got %s (expected %s)", subscribeOutput["Target"], subscribeInput.Target)
continue
subscribeOutputPayload = DeviceWebSocketOutputSubscribePayload(
Robot=subscribeOutput["Payload"]["Robot"]
)
output["_equipment_length"] = str(len(subscribeOutputPayload.Robot["State"]["Reported"]["Equipment"]))
for key, value in subscribeOutputPayload.Robot["State"]["Reported"]["Equipment"].items():
output["_robot_key"] = key
output["mode"] = str(value["Mode"])
break
break
def generate_thing():
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
b = ''.join(random.choice(letters) for _ in range(22))
return b
for action in actions:
logger.debug("Performing action: %s", action)
if action == "start" or action == "stop":
mode = 1 if action == "start" else 0
thing1 = generate_thing()
thing2 = generate_thing()
subscribeInput = DeviceWebSocketInput(
Version=1,
Action="setState",
Namespace="cyclonext",
Service="StateController",
Target=deviceID,
Payload=DeviceWebSocketInputSetStatePayload(
state={
"desired": {
"equipment": {
output["_robot_key"]: {
"mode": mode
}
}
}
},
ClientToken=f"{userId}|{thing1}|{thing2}"
)
)
logger.debug("Writing: %s", json_to_string(subscribeInput))
self.websocket.send(json_to_string(subscribeInput))
with contextlib.suppress(Exception):
while True:
contents = self.websocket.recv()
logger.debug("Received: %s", contents)
if len(contents) == 0:
time.sleep(0.1)
continue
subscribeOutput = json.loads(contents)
if subscribeOutput["Event"] != "StateReported":
logger.debug("Event does not match: got %s (expected %s)", subscribeOutput["Event"], "StateReported")
continue
if subscribeOutput["Service"] != "StateStreamer":
logger.debug("Service does not match: got %s (expected %s)", subscribeOutput["Service"], "StateStreamer")
continue
if subscribeOutput["Target"] != subscribeInput.Target:
logger.debug("Target does not match: got %s (expected %s)", subscribeOutput["Target"], subscribeInput.Target)
continue
output["mode"] = str(mode)
break
return output
this might take a while to implement, I'll see what I can do, seems to contain some interesting parts for sure!
this might take a while to implement, I'll see what I can do, seems to contain some interesting parts for sure!
Please let me know if I can help you. Also please send me your postman collection so I can test/play with the execute command bit - It will be interesting to see if my robot goes to offline like yours.
Hello I have a Polaris - VRX iQ+ robot. Will this integration into Home Assistant work with this robot? Also, I noticed when I create the sensor in home assistant it's asking for an API key. Where can I get that from? Any assistance anyone can provide is greatly appreciated. Also, I would be more than happy to help with anything on this project.
Hello I have a Polaris - VRX iQ+ robot. Will this integration into Home Assistant work with this robot? Also, I noticed when I create the sensor in home assistant it's asking for an API key. Where can I get that from? Any assistance anyone can provide is greatly appreciated. Also, I would be more than happy to help with anything on this project.
It shouldn't be asking you for an API key as its built into the code. It is 'EOOEMOW4YR6QNB07'. As to whether your device is supported - the short answer is not sure. I'd encourage you to install via HACS, set-up your sensor in config.yaml and see if you get data populated in the sensor. If it does, great. if not then check your logs and report back here by opening a new issue.
Awesome thank you so much!! I just tried it and everything is working! Just curious, is the start/stop feature still being worked on?
It is. @galletn may I suggest updating the readme to include confirmed support for Polaris - VRX iQ+
added the new confirmed supported robot, and indeed, I want to make the start stop work indeed, but might need some time as its quite busy @work lately.
Ok no problem. Let me know if I can help at all with anything
added the new confirmed supported robot, and indeed, I want to make the start stop work indeed, but might need some time as its quite busy @work lately.
Also, Polaris alpha IQ works with the integration.
Hi @galletn just checking in with you. How are you progressing? Can I offer any help? You're probably very busy at work - no worries if that's the case.
hi @ppastur indeed, busy at work, also weekends, so no progress yet. I'll try to see when I can free up some time to get this websocket thing going.
@ppastur I'm fixing some parts of the code first, but I'm almost going to do this stop start too. Read some stuff on it and I setup a development environment of HA so that I don't break and need to reboot my HA all the time :)
PS for latest version you will have some breaking changes, as I needed to move the folder to not interfere with the other integration of Iaqualink #6 so you need to remove it from your config first, update and add it back to the config and watch that the platform is now iaqualinkRobots instead of iaqualink
@ppastur I'm fixing some parts of the code first, but I'm almost going to do this stop start too. Read some stuff on it and I setup a development environment of HA so that I don't break and need to reboot my HA all the time :)
PS for latest version you will have some breaking changes, as I needed to move the folder to not interfere with the other integration of Iaqualink #6 so you need to remove it from your config first, update and add it back to the config and watch that the platform is now iaqualinkRobots instead of iaqualink
Thanks for the heads up @galletn. I uninstalled, changed the platform sensor in the config and reinstalled. After some tweaks to the frontend referencing the old sensor, it all works as expected.
Any news yet on the start/stop?
I revamped some of the code already, but I'm having struggles creating both a sensor and button ... I'll try to find some more time to invest, but unless I get that part fixed it will be very hard to implement this. Any help is welcome đź‘Ť
What help do you need? I can dedicate some time.
Well creating one or more sensors works like a charm, but as soon as I try to create a button and a sensor from the same integration it's not creating both ... I'm not a Python expert so ... probably I'm doing something wrong in the constructors...
bellow my button.py file
could also be that we need to move the creation into the init.py ... but I did not find enough time to investigate that deep.
the help pages of HA are a bit lacking on that end, tried chat GPT too, but not with desired result yet.
from __future__ import annotations
from homeassistant.components.button import ButtonEntity
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
def setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None
) -> None:
"""Set up the sensor platform."""
add_entities([iaqualinkRobotStart(config)])
class iaqualinkRobotStart(ButtonEntity):
_attr_has_entity_name = True
_attr_name = "Start"
@property
def unique_id(self) -> str:
"""Return the name of the sensor."""
return (
f"Start"
)
@property
def name(self):
"""Name of the entity."""
return "Start"
def __init__(self, config):
# Apply throttling to methods using configured interval
def press(self) -> None:
"""Handle the button press."""
Been a while but just a heads up, the code is ready for stop/start ... the only job I still need to do is get a damn button into HA 🗡️ once that is done ... we are up and running! Keep you posted!
so I found out how to do it with the buttons, but I did not like the setup. So I'm changing all the code towards Vacuum entity that provides stop start functionality as needed.
I'll release the code tomorrow, and hope this week to implement the stop start code that works into it. Also I got some help of one of the other guys here that has another device type so that cyclones should also be supported!
keep you posted!
beware that tomorrows code will break your stuff! But it will have many advantages in the end
Thanks for the update - thats great news.
please try out the new vacuum entity and let me know how it works!
Hi thats awesome. I assume this will or may break my current working card, sensors etc. Do you have a recommendation on how I can test and if required roll back?
HI @ppastur you can keep both for now, I implemented the vacuum entity, you can enter both sensor and vacuum in your yaml.
@galletn I Tried the new version and I can confirm it works fine. I however cant for the life of me work out how to create a button in my YAML to Start/Stop cleaning. Can you share your yaml?
@ppastur you need to add as written in the readme:
vacuum:
- platform: iaqualinkRobots
username: <username>
password: <password>
api_key: EOOEMOW4YR6QNB07
name: <Robot name, will also be the sensor name>
so you now have:
sensor:
- platform: iaqualinkRobots
username: <username>
password: <password>
api_key: EOOEMOW4YR6QNB07
name: <Robot name, will also be the sensor name>
but you can put both ... but then add to your dashboard the vacuum sensor too it looks like this and has buttons when you open the entity:
@galletn Thanks - I have already done that and have the same as you. What I was asking about was how to add a button into a Lovelace card or entity card so you don't have to go to the vacuum entity to start / stop etc
@ppastur just add the vacuum entity.
or add it to an existing card.
once added if you click on it you see the start & stop button.
Hi @galletn Thank you - I understand and have that already.
What Im asking about is slightly different. I have a card that I created for my Pool area and robot. See here I have 2 cards, one using data from sensor.py and the other using the new vacuum.py
If I click on the entity I get the standard entity card and I can then start/stop the robot. What I would like is to create a button on the card (like the one shown) that allows me to start/stop activities without having to bring up a the entity card. Make sense? I've tried to use the action call service vacuum.start / vacuume.stop / vacuume.toggle but it is unreliable. I even created a script that call service vacuum.start / vacuume.stop / vacuume.toggleand and had the button call the script but again its unreliable but I suspect that is on me and how I'm doing it as the start / stop functionality works great - you have done a splendid job. I was asking to see if you had managed to get a button in a card to directly control the robot without having to go into the entity
I can’t recall, however, I think it’s in the hassio forums somewhere to be able to bring that on to its own card. I set up with my pool lights through scripts.. I just need to get home and have a look.
On Thu, Jul 4, 2024 at 8:19 PM ppastur @.***> wrote:
Hi @galletn https://github.com/galletn Thank you - I understand and have that already. image.png (view on web) https://github.com/galletn/iaqualink/assets/91765182/528a84aa-fc7d-4a2c-9b65-532ad7111945
What Im asking about is slightly different. I have a card that I created for my Pool area and robot. See here I have 2 cards, one using data from sensor.py and the other using the new vacuum.py
image.png (view on web) https://github.com/galletn/iaqualink/assets/91765182/9f94dc70-2e77-4122-8e7f-1345dce1194f
If I click on the entity I get the standard entity card and I can then start/stop the robot. What I would like is to create a button on the card (like the one shown) that allows me to start/stop activities without having to bring up a the entity card. Make sense? I've tried to use the action call service vacuum.start / vacuume.stop / vacuume.toggle but it is unreliable. I even created a script that call service vacuum.start / vacuume.stop / vacuume.toggleand and had the button call the script but again its unreliable but I suspect that is on me and how I'm doing it as the start / stop functionality works great - you have done a splendid job. I was asking to see if you had managed to get a button in a card to directly control the robot without having to go into the entity
— Reply to this email directly, view it on GitHub https://github.com/galletn/iaqualink/issues/1#issuecomment-2209661509, or unsubscribe https://github.com/notifications/unsubscribe-auth/AVQMRHJNAV6JXEEJ3ZOFDBLZKXRBLAVCNFSM6AAAAABKCKUMBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBZGY3DCNJQHE . You are receiving this because you commented.Message ID: @.***>
On Thu, Jul 4, 2024 at 8:22 PM ian dcruZ @.***> wrote:
I can’t recall, however, I think it’s in the hassio forums somewhere to be able to bring that on to its own card. I set up with my pool lights through scripts.. I just need to get home and have a look.
On Thu, Jul 4, 2024 at 8:19 PM ppastur @.***> wrote:
Hi @galletn https://github.com/galletn Thank you - I understand and have that already. image.png (view on web) https://github.com/galletn/iaqualink/assets/91765182/528a84aa-fc7d-4a2c-9b65-532ad7111945
What Im asking about is slightly different. I have a card that I created for my Pool area and robot. See here I have 2 cards, one using data from sensor.py and the other using the new vacuum.py
image.png (view on web) https://github.com/galletn/iaqualink/assets/91765182/9f94dc70-2e77-4122-8e7f-1345dce1194f
If I click on the entity I get the standard entity card and I can then start/stop the robot. What I would like is to create a button on the card (like the one shown) that allows me to start/stop activities without having to bring up a the entity card. Make sense? I've tried to use the action call service vacuum.start / vacuume.stop / vacuume.toggle but it is unreliable. I even created a script that call service vacuum.start / vacuume.stop / vacuume.toggleand and had the button call the script but again its unreliable but I suspect that is on me and how I'm doing it as the start / stop functionality works great - you have done a splendid job. I was asking to see if you had managed to get a button in a card to directly control the robot without having to go into the entity
— Reply to this email directly, view it on GitHub https://github.com/galletn/iaqualink/issues/1#issuecomment-2209661509, or unsubscribe https://github.com/notifications/unsubscribe-auth/AVQMRHJNAV6JXEEJ3ZOFDBLZKXRBLAVCNFSM6AAAAABKCKUMBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMBZGY3DCNJQHE . You are receiving this because you commented.Message ID: @.***>
Yep - that's what I did previously. I think I found the problem. My script was set to single mode. I changed it to restart mode and it seems to be working now. Ill test a little more
Ok - Confirmed and Tested. I managed to get a button in a card to work the start/stop
https://github.com/galletn/iaqualink/assets/91765182/ba2b1fd6-4ee4-48d2-b72b-3ed0fc097fe6
Check out the short vid
Can you share the script. Thanks
On Fri, Jul 5, 2024 at 7:28 AM ppastur @.***> wrote:
Ok - Confirmed and Tested. I managed to get a button in a card to work the start/stop
https://github.com/galletn/iaqualink/assets/91765182/ba2b1fd6-4ee4-48d2-b72b-3ed0fc097fe6
Check out the short vid
— Reply to this email directly, view it on GitHub https://github.com/galletn/iaqualink/issues/1#issuecomment-2210707824, or unsubscribe https://github.com/notifications/unsubscribe-auth/AVQMRHLSDEQGNIX4MID6TY3ZKZ7OHAVCNFSM6AAAAABKCKUMBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDEMJQG4YDOOBSGQ . You are receiving this because you commented.Message ID: @.***>
sure - here you go
` alias: Vacuum toggle script sequence:
Nice video, do you mind I share it on the intro page, the delay in HA is normal, its between 0 and 30 seconds depending on when you clicked the start as the status updates are delay by that time window
no problem - least I can do for you
I can edit the video and remove the title Test new vaccum.py if you want
https://github.com/galletn/iaqualink/assets/91765182/75806d16-6350-4a8d-84d0-7ce2996ae8f6
Here it is without vacuum.py test title
Need to investigate stop start functionality