Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do i avoid doing the device discovery every time? #296

Closed
LiveITA opened this issue Apr 13, 2023 · 6 comments
Closed

How do i avoid doing the device discovery every time? #296

LiveITA opened this issue Apr 13, 2023 · 6 comments
Labels
duplicate This issue or pull request already exists waiting validation Waiting for user's validation/approval/test

Comments

@LiveITA
Copy link

LiveITA commented Apr 13, 2023

Hi guys, I am using merossiot to push a doorphone button remotely (MSG100 hw 4.0.0. sw v4.2.6). It works perfectly, but the problem is that I have to rediscover all the devices every time, which leads to a total of 8 seconds needed to send the command. I only have one device in my account. Is there any way for me to avoid the device discovery and simply connect and send the close door message? I read that I should not use the discovery too ofter as I might get banned for it.
PS. i call this script once a day or less, but i just need it to be faster and i want to avoid bans.

import asyncio
import os

import requests
from meross_iot.controller.mixins.garage import GarageOpenerMixin
from meross_iot.http_api import MerossHttpClient
from meross_iot.manager import MerossManager

EMAIL = os.environ.get('[email protected]') or "[email protected]"
PASSWORD = os.environ.get('xxxxxx') or "xxxxxxx"
TELEGRAM_API_KEY = os.environ.get('xxxxxx') or "xxxxxx"
TELEGRAM_CHAT_ID = os.environ.get('xxxxxxx') or "xxxxxxx"


async def main():
    # Setup the HTTP client API from user-password
    http_api_client = await MerossHttpClient.async_from_user_password(email=EMAIL, password=PASSWORD)

    # Setup and start the device manager
    manager = MerossManager(http_client=http_api_client)
    await manager.async_init()

    # Retrieve all the devices that implement the garage-door opening mixin
    await manager.async_device_discovery()
    openers = manager.find_devices(device_class=GarageOpenerMixin)

    if len(openers) < 1:
        print("No garage opener found...")
    else:
        dev = openers[0]

        # Update device status
        await dev.async_update()

        # Check current door status
        open_status = dev.get_is_open()
        if open_status:
            print(f"Door {dev.name} is open")
        else:
            print(f"Door {dev.name} is closed")

        # Close the door and send Telegram message
        print(f"Closing door {dev.name}...")
        await dev.async_close()
        print(f"Door closed!")
        requests.get(f"https://api.telegram.org/bot{TELEGRAM_API_KEY}/sendMessage?chat_id={TELEGRAM_CHAT_ID}&text=La porta di BnB Bianca/Camilla e' stata aperta")

    # Close the manager and logout from http_api
    manager.close()
    await http_api_client.async_logout()

if __name__ == '__main__':
    if os.name == 'nt':
        asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())
    loop.stop()
@dominicdumont
Copy link

I would also be interested to know how to avoid the costly device discovery 👍

@stale
Copy link

stale bot commented Jun 16, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Jun 16, 2023
@LiveITA
Copy link
Author

LiveITA commented Jun 16, 2023

Not stale

@stale stale bot removed the stale label Jun 16, 2023
@albertogeniola
Copy link
Owner

Isn't this a duplicate of #255 ? See here and let me know if that works for you.

@albertogeniola albertogeniola added waiting validation Waiting for user's validation/approval/test duplicate This issue or pull request already exists labels Jun 19, 2023
@LiveITA
Copy link
Author

LiveITA commented Jun 23, 2023

Oh thanks! I could not find it before, maybe rename it from dump.py to dump(avoid-device-discovery).py? ahaha
Seems to be ALMOST working!

I run this code after creating the dump file but i still get an error

import asyncio
import os
import http.client
from urllib.parse import quote
import inspect

from meross_iot.controller.mixins.toggle import ToggleXMixin
from meross_iot.http_api import MerossHttpClient
from meross_iot.manager import MerossManager

EMAIL = "xxxxxx"
PASSWORD = "xxxxxx"
API_KEY = "xxxxxx"
PHONE_NUMBER = "xxxxxx"

async def main():
    # Setup the HTTP client API from user-password
    http_api_client = await MerossHttpClient.async_from_user_password(email=EMAIL, password=PASSWORD)

    # Setup and start the device manager
    manager = MerossManager(http_client=http_api_client)
    await manager.async_init()

    # Load the device list from the dump file
    manager.load_devices_from_dump("/home/door-opener/python/dump.dump")

    # Retrieve all the devices that implement the toggle mixin
    toggles = manager.find_devices(device_class=ToggleXMixin)

    if len(toggles) < 1:
        print("No toggle device found...")
    else:
        # Find the desired toggle device by name
        current_file = inspect.getframeinfo(inspect.currentframe()).filename
        file_name = os.path.basename(current_file)
        desired_toggle_name = file_name.split("-", 1)[-1].rsplit(".", 1)[0]

        dev = next((toggle for toggle in toggles if toggle.name == desired_toggle_name), None)

        if dev is None:
            print(f"Toggle device '{desired_toggle_name}' not found.")
        else:
            # Check the filename prefix to determine the behavior
            if file_name.startswith("mss710-"):
                # Turn on the toggle device for half a second
                print(f"Turning on toggle device {dev.name}...")
                await dev.async_turn_on()
                await asyncio.sleep(0.5)

                # Turn off the toggle device
                print(f"Turning off toggle device {dev.name}...")
                await dev.async_turn_off()

                print(f"Toggle device {dev.name} toggled!")
            elif file_name.startswith("msg100-"):
                # Close the door
                print(f"Opening door {dev.name}...")
                await dev.async_close()
                print(f"Door open!")
            else:
                print("Invalid filename prefix.")

            # Send WhatsApp message
            conn = http.client.HTTPSConnection("api.textmebot.com")
            message = (
                f"Toggle device {dev.name} toggled!"
                if file_name.startswith("mss710-")
                else f"Door open {dev.name}!"
            )
            encoded_message = quote(message)
            payload = f"/send.php?recipient={PHONE_NUMBER}&force=yes&apikey={API_KEY}&text={encoded_message}"
            conn.request("GET", payload)
            res = conn.getresponse()
            data = res.read()
            print(data.decode("utf-8"))

    # Close the manager and logout from http_api
    manager.close()
    await http_api_client.async_logout()


if __name__ == '__main__':
    asyncio.run(main())

This is the error

python msg100-CG-cancellostrada.py
Opening door CG-cancellostrada...
INFO:Allocating new mqtt client for mqtt-us.meross.com:443...
INFO:Subscribed to topics, scheduling state update for already known devices.
INFO:

------- Triggering Manager Discovery, filter_device: [None] -------
INFO:Fetch and update done
INFO:
------- Manager Discovery ended -------

WARNING:Updating status for device CG-cancellostrada (msg100, HW 3.5.0, FW 3.2.7, class: msg100:3.5.0:3.2.7)
Door open!

<br><b>Warning: FORCING SEND (skip 8seconds mandatory delay)</b><br>Recipient GroupID: <b>[email protected]</b><br>Sender's phone number: <b>+39hiddenforprivacy</b><br>API version: <b>2.0</b><br>Sending message...<br>Result: <b>Success!</b>
INFO:Manager stop requested.
INFO:Disconnection detected. Reason: 0
/usr/lib/python3.10/asyncio/base_events.py:1881: RuntimeWarning: coroutine 'MerossManager._update_and_send_push' was never awaited
  handle = self._ready.popleft()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
INFO:Logout succeeded.
/usr/lib/python3.10/asyncio/runners.py:47: RuntimeWarning: coroutine 'MerossManager._update_and_send_push' was never awaited
  _cancel_all_tasks(loop)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

So it looks like it runs, it opens the door, but then it crashes. I tried to fix it but it was not successful

@LiveITA
Copy link
Author

LiveITA commented Aug 2, 2023

Ok all good!
Had to test a bit but it worked

@LiveITA LiveITA closed this as completed Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists waiting validation Waiting for user's validation/approval/test
Projects
None yet
Development

No branches or pull requests

3 participants