fhempy: miio (Xiaomi WiFi Devices)

Begonnen von dominik, 30 Oktober 2020, 21:26:31

Vorheriges Thema - Nächstes Thema

dominik

Hallo zusammen,

ich habe ein neues Modul zur Steuerung von Xiaomi WiFi Devices erstellt. Soll vorrangig dazu dienen fuer z.B. Xiaomi Cameras ein/aus/motion detection aktivieren/deaktivieren, etc..
Das Modul basiert auf python-miio (https://github.com/rytilahti/python-miio), hier die Liste der unterstuetzten Devices:
  airconditioningcompanion
  airconditioningcompanionv3
  airdehumidifier
  airfresh
  airfresht2017
  airhumidifier
  airhumidifierca1
  airhumidifiercb1
  airhumidifierjsq
  airhumidifiermiot
  airhumidifiermjjsq
  airpurifier
  airpurifiermiot
  airqualitymonitor
  alarmclock
  aqaracamera
  ceil
  chuangmicamera
  chuangmiir
  chuangmiplug
  cooker
  device
  fan
  fanp5
  fansa1
  fanv2
  fanza1
  fanza3
  fanza4
  gateway
  gatewayalarm
  gatewaydevice
  gatewaylight
  gatewayradio
  gatewayzigbee
  heater
  miotdevice
  philipsbulb
  philipseyecare
  philipsmoonlight
  philipsrwread
  philipswhitebulb
  plug
  plugv1
  plugv3
  powerstrip
  pwznrelay
  toiletlid
  vacuum
  viomivacuum
  waterpurifier
  wifirepeater
  wifispeaker
  yeelight


Das Modul unterstuetzt aktuell nur Kommandos die keine weiteren Argumente benoetigen. Z.B. ein Lautstaerke setzen geht noch nicht, on/off, motion aktivieren/deaktivieren geht. Bitte beachtet, dass das Modul sehr generisch aufgebaut ist, fuer Saugroboter/Airpurifier sollte das Modul von Markus hier verwendet werden: https://forum.fhem.de/index.php/topic,73052.0.html

Installation (Basisinstallation fhem_pythonbinding)
https://github.com/dominikkarall/fhem_pythonbinding

Nutzung miio Modul:
https://github.com/dominikkarall/fhem_pythonbinding/blob/master/FHEM/bindings/python/lib/miio/README.md

Ich nutze es aktuell nur um die Ueberwachung auf meinen Kameras zu aktivieren/deaktivieren.
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

neturmel

Hi,

ich nutze das Modul dafür, meinen Xiaomi Mijia G1 über FHEM zu steuern, da ich mir dafür ein python-miioo Modul gebaut habe.
Das funktioniert prima, wäre aber noch schöner, wenn man den Status sehen könnte oder noch besser als Reading hätte.

Leider habe ich eigentlich nicht wirklich Zeit, auch noch am FHEM zu basteln, aber da jetzt ja schon ein Teil funktioniert...

Wie würde man denn vorgehen, um z.B. das:


miiocli  g1vacuum --ip 192.168.... --token 82... status
State: G1State.Sweeping
Error: G1Error.Everything_is_ok
Battery: 42%
Mode: G1Mode.Global_clean
Mop State: G1MopState.Off
Charge Status: G1ChargeState.Not_charging
DND enabled: False
Direction: None
Fan speed: G1FanLevel.Standard
Water level: G1WaterLevel.Level2
Filter Life Level: 65%
Brush Life Level: 82%
Side Brush Life Level: 63%
Clean Area: 4768
Total Clean Area: 0
Clean Time: 70
Total Clean Count: 0


in FHEM-Readings zu mappen?
FHEM, Homebridge, Philips Hue, Innr, Tradfri, Osram, Shelly 1 2 2.5,  LD382A, MQTT, Xiaomi Mijia G1

dominik

Hi,

eigentlich werden durch das miio Modul auch Readings angelegt und alle 300s automatisch per "status" aktualisiert. Erscheinen gar keine Readings bei dir mit dem Modul?
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

neturmel

#3
Es erscheinen leider nur Readings nach dem Aufruf eines set commands.

Eventuell passt die Umsetzung des Status-commands mit dem neuen get_properties_by_dataclass() da nicht (mein Modul entstand aus einem Pull Request für den dreame Sauger, der im Moment scheinbar ruht und den Status nur rudimentär anzeigt). Oder ich habe beim zusammen hacken (oder nennen wir es besser pfuschen) irgendwas kaputt gemacht.

Das muss ich mir dann doch mal an der Stelle nochmal genauer anschauen.

Raw Dev:

defmod staubi PythonModule miio g1vacuum 192.168.... 82...
attr staubi IODev local_pybinding
attr staubi icon vacuum_top
attr staubi room Wohnzimmer

setstate staubi online
setstate staubi 2020-11-20 10:48:35 accesspoint {'ssid': 'fleck', 'bssid': '98:9B:CB:21:D2:D5', 'rssi': -36, 'primary': 6}
setstate staubi 2020-11-19 17:29:53 find {'did': 'call-6-1', 'siid': 6, 'aiid': 1, 'code': 0}
setstate staubi 2020-11-20 10:48:35 firmware_version 2.0.8
setstate staubi 2020-11-20 10:48:35 hardware_version esp32
setstate staubi 2020-11-20 10:48:35 mac_address 64:90:C1
setstate staubi 2020-11-20 10:48:35 model mijia.vacuum.v2
setstate staubi 2020-11-20 10:48:35 network_interface {'localIp': '192.168.', 'mask': '255.255.255.0', 'gw': '192.168.178.1'}
setstate staubi 2020-11-20 10:48:35 raw {'life': 53248, 'uid': 633960, 'model': 'mijia.vacuum.v2', 'token': '82', 'ipflag': 1, 'fw_ver': '2.0.8', 'mcu_fw_ver': '6138', 'miio_ver': '0.0.8', 'hw_ver': 'esp32', 'mmfree': 64144, 'mac': '64:90:C1', 'wifi_fw_ver': 'cef6c09-dirty', 'ap': {'ssid': 'fck', 'bssid': '98:9B:CB:21:D2:D5', 'rssi': -36, 'primary': 6}, 'netif': {'localIp': '192.168.', 'mask': '255.255.255.0', 'gw': '192.168.178.1'}}
setstate staubi 2020-11-19 17:34:06 return_home {'did': 'call-2-3', 'siid': 2, 'aiid': 3, 'code': 0}
setstate staubi 2020-11-19 17:33:44 start {'did': 'call-2-1', 'siid': 2, 'aiid': 1, 'code': 0}
setstate staubi 2020-11-21 06:19:00 state online
setstate staubi 2020-11-19 17:33:35 stop {'did': 'call-2-2', 'siid': 2, 'aiid': 2, 'code': 0}
FHEM, Homebridge, Philips Hue, Innr, Tradfri, Osram, Shelly 1 2 2.5,  LD382A, MQTT, Xiaomi Mijia G1

dominik

Kannst du mir mal den Link zum miio Code schicken wo der g1vacuum integriert wurde? Dann kann ich nachschauen warum die anderen Statuswerte da nicht übernommen werden.
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

neturmel

#5
Ich habe mein python-miip-g1vacuum Modul jetzt so umgeschrieben, dass der Status als Objekt zurück geliefert wird (Danke @dominik ) und bekomme jetzt auch Readings.

Einen Pull Request als Basis zu nehmen, war im Nachhinein keine gute Idee. Die neuen Miot_Device-Funktionen, die u.a. darin implementiert wurden,
sind noch nicht so richtig ausgereift und liefern nicht immer das, was man erwartet.

Ich habe jetzt den Master-Branch als Basis genommen und das Mapping und die Abfrage der Properties wie in den bisherigen MIOT-Devices kodiert.

Habe mal einen Pull-Request (https://github.com/rytilahti/python-miio/pull/867/files) angelegt.

FHEM, Homebridge, Philips Hue, Innr, Tradfri, Osram, Shelly 1 2 2.5,  LD382A, MQTT, Xiaomi Mijia G1

neturmel

Ich finde das mit den Python-Bindings übrigens toll, gerade wenn man sonst eher mit Python als mit Perl arbeitet, kommt man wirklich schnell zu brauchbaren Ergebnissen.

Super Arbeit!
FHEM, Homebridge, Philips Hue, Innr, Tradfri, Osram, Shelly 1 2 2.5,  LD382A, MQTT, Xiaomi Mijia G1

dominik

Super, freut mich, dass alles so gut geklappt hat!

Ich hoffe der PR wird akzeptiert und damit können dann alle den g1vacuum schnell nutzen.
Falls der g1vacuum auch History, usw. abrufen kann, habe ich schon mal ein Attribut vorbereitet mit dem man alle x Sekunden den Status abfragen kann. Ich muss es nur noch selbst testen.

Zum PythonBinding: Alleine wenn ich mir die Liste der Module ansehe (https://github.com/dominikkarall/fhem_pythonbinding#fhem-python-binding-beta) die ich in kürzester Zeit erstellt habe, zeigt sich, dass man mit den Python Libraries wirklich schnell in der Entwicklung ist...und noch dazu alles aynchron ohne Blocking :)
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

Stelaku

Hallo
Ich nutze das Modul auch für meinen Xiaomi Saugroboter. Das Modul von Markus 72_XiaomiDevice scheint meinen Saugroboter nicht zu unterstützen. Mit diesem Modul funktioniert es schon sehr gut.
Ich habe es nur noch nicht herausgefunden, wie ich den move Befehl richtig setzte.
Wenn ich das richtig gesehen habe muss ich die Richtung angeben. 1 für forward und dann die Dauer. Nur die genaue Schreibweise finde ich nicht raus.
Ist das schon mitberücksichtigt oder geht das einfach noch nicht.
Gebe ich z.b. set Martha_1 move 1 100 ein bekomme ich folgendes im Pyhtonbinding log angezeigt.


2020-11-27 23:18:12,557 - ERROR    - asyncio: Task exception was never retrieved
future: <Task finished coro=<miio.send_command() done, defined at /opt/fhem/FHEM/bindings/python/lib/miio/miio.py:90> exception=AttributeError("'float' object has no attribute 'value'")>
Traceback (most recent call last):
  File "/opt/fhem/FHEM/bindings/python/lib/miio/miio.py", line 109, in send_command
    reply = await utils.run_blocking(functools.partial(fct, *args))
  File "/opt/fhem/FHEM/bindings/python/lib/utils.py", line 28, in run_blocking
    pool, function)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/opt/fhem/.local/lib/python3.7/site-packages/miio/viomivacuum.py", line 372, in move
    self.send("set_direction", [direction.value])
AttributeError: 'float' object has no attribute 'value'



Leider werde ich daraus nicht schlau.


Gruß

Stephan

dominik

Hi,

probier bitte mal
set Martha_1 move Forward 100
Die Direction Angabe ist nämlich ein Enum (https://github.com/rytilahti/python-miio/blob/master/miio/viomivacuum.py#L148) daher müssen die Namen angegeben werden. Ich muss da noch eine Hilfefunktion für solche Commands integrieren, so dass man "move ?" machen kann und damit eine Hilfe zu den Optionen bekommt. Weil Funktionen mit mehreren Parametern können in FHEM leider keine Auswahlliste haben (zumindest ist mir diese Funktion nicht bekannt).
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

Stelaku

Hallo Dominik

Ich hatte schon so einige Variationen Probiert. Darunter war auch unter anderen set Martha_1 move Forward 100.
Meine bis jetzt erfolglos getesteten Variationen waren
2020-11-28_16:10:11 Martha_1 move Forward 100
2020-11-28_16:10:51 Martha_1 move Forward,100
2020-11-28_16:12:46 Martha_1 move forward 100
2020-11-28_16:13:23 Martha_1 move 100 Forward
2020-11-28_16:13:35 Martha_1 online
2020-11-28_16:13:35 Martha_1 ViomiVacuumState.Idle
2020-11-28_16:13:35 Martha_1 battery: 96
2020-11-28_16:13:35 Martha_1 move 100 forward
2020-11-28_16:13:48 Martha_1 move 100,forward
2020-11-28_16:13:59 Martha_1 move 100,Forward
2020-11-28_16:18:35 Martha_1 online
2020-11-28_16:18:35 Martha_1 ViomiVacuumState.Idle
2020-11-28_16:18:35 Martha_1 battery: 95
2020-11-28_16:19:58 Martha_1 move Forward.100
2020-11-28_16:20:11 Martha_1 move forward.100
2020-11-28_16:20:29 Martha_1 move 100.Forward

Leider waren alle kombinationen ohne Erfolg es kommt immer im Phytonbinding.log eine Fehlermeldung.
2020-11-28 16:30:16,179 - ERROR    - lib.utils: Error in asyncio thread
Traceback (most recent call last):
  File "/opt/fhem/FHEM/bindings/python/lib/utils.py", line 28, in run_blocking
    pool, function)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/opt/fhem/.local/lib/python3.7/site-packages/miio/viomivacuum.py", line 372, in move
    while time.time() - start < duration:
AttributeError: 'str' object has no attribute 'value'
2020-11-28 16:30:16,181 - ERROR    - asyncio: Task exception was never retrieved
future: <Task finished coro=<miio.send_command() done, defined at /opt/fhem/FHEM/bindings/python/lib/miio/miio.py:90> exception=AttributeError("'str' object has no attribute 'value'")>
Traceback (most recent call last):
  File "/opt/fhem/FHEM/bindings/python/lib/miio/miio.py", line 109, in send_command
    reply = await utils.run_blocking(functools.partial(fct, *args))
  File "/opt/fhem/FHEM/bindings/python/lib/utils.py", line 28, in run_blocking
    pool, function)
  File "/usr/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/opt/fhem/.local/lib/python3.7/site-packages/miio/viomivacuum.py", line 372, in move
    while time.time() - start < duration:
AttributeError: 'str' object has no attribute 'value'


Gruß

Stephan

dominik

Ich weiß schon was fehlt, die Annotation im Code. Ich vermute clean_mode kannst du auch nicht setzen, oder?

set_fan_speed liefert den richtigen Typ:
>>> inspect.signature(miio.viomivacuum.ViomiVacuum.set_fan_speed).parameters['speed'].annotation
<enum 'ViomiVacuumSpeed'>


move jedoch nicht:
>>> inspect.signature(miio.viomivacuum.ViomiVacuum.move).parameters['direction'].annotation
<class 'inspect._empty'>


Da muss im python-miio Code die Annotation hinzugefügt werden, dann wird es vom miio Modul auch richtig erkannt.
fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

dominik

fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik

Stelaku

Total Klasse damit funktioniert es.
Jetzt ist es möglich den Sauger per move zu steuern.

Dann kann ich jetzt wieder weiter herum spielen.

Vielen dank und noch ein schönes Wochenende

Gruß

Stephan

dominik

fhempy -  https://github.com/fhempy/fhempy: GoogleCast, Tuya, UPnP, Ring, EQ3BT, Nespresso, Xiaomi, Spotify, Object Detection, ...
Kaffeespende: https://paypal.me/todominik