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

Support for new vaccum Xiaomi Mijia STYJ02YM #550

Closed
kwetnico opened this issue Sep 20, 2019 · 37 comments · Fixed by #576
Closed

Support for new vaccum Xiaomi Mijia STYJ02YM #550

kwetnico opened this issue Sep 20, 2019 · 37 comments · Fixed by #576

Comments

@kwetnico
Copy link

Hello,

It's possible to add the new vaccum xaomi.
This model : https://fr.gearbest.com/vacuum-cleaners/pp_009487950353.html

Thanks

@ABRT29
Copy link

ABRT29 commented Oct 1, 2019

hi, please mee too

@ABRT29
Copy link

ABRT29 commented Oct 1, 2019

Model number : STYJ02YM
Capture d’écran 2019-10-01 à 09 17 11

with mi home 5.4.54 :

{"did":"27XXX6986","token":"72676b4a764bXXXXXXXXXXXXXX5363","longitude":"XXX","latitude":"XXX","name":"Mi Robot Vacuum-Mop P","pid":"0","localip":"192.168.0.35","mac":"XX:XX:XX:XX:XX:XX","ssid":"XX","bssid":"XX:XX:XX:XX:XX:XX","parent_id":"","parent_model":"","show_mode":1,"model":"viomi.vacuum.v7","adminFlag":1,"shareFlag":0,"permitLevel":16,"isOnline":true,"desc":"Appareil en ligne ","extra":{"isSetPincode":0,"fw_version":"3.5.3_0042","needVerifyCode":0,"isPasswordEncrypt":0}

@alex7614
Copy link

alex7614 commented Oct 5, 2019

Hi
Please too

@HydrelioxGitHub
Copy link

I have this vacuum too. Is there anything we can do for help ?

@NSDmitry
Copy link

Hi, please too

@ABRT29
Copy link

ABRT29 commented Oct 16, 2019

have you any news ?

@edubox
Copy link

edubox commented Nov 6, 2019

Model number : STYJ02YM
Capture d’écran 2019-10-01 à 09 17 11

with mi home 5.4.54 :

{"did":"27XXX6986","token":"72676b4a764bXXXXXXXXXXXXXX5363","longitude":"XXX","latitude":"XXX","name":"Mi Robot Vacuum-Mop P","pid":"0","localip":"192.168.0.35","mac":"XX:XX:XX:XX:XX:XX","ssid":"XX","bssid":"XX:XX:XX:XX:XX:XX","parent_id":"","parent_model":"","show_mode":1,"model":"viomi.vacuum.v7","adminFlag":1,"shareFlag":0,"permitLevel":16,"isOnline":true,"desc":"Appareil en ligne ","extra":{"isSetPincode":0,"fw_version":"3.5.3_0042","needVerifyCode":0,"isPasswordEncrypt":0}

Where did you get this info? I can't find mine in /Smarthome/log files

@ABRT29
Copy link

ABRT29 commented Nov 6, 2019

Numéro de modèle: STYJ02YM
Capture d'écran 2019-10-01 à 09 17 11
avec mon domicile 5.4.54:
{"did": "27XXX6986", "jeton": "72676b4a764bXXXXXXXXXXXXXX5363", "longitude": "XXX", "latitude": "XXX", " nom": "Mi Robot Vacuum-Mop P" , "pid": "0", "localip": "192.168.0.35", "mac": "XX: XX: XX: XX: XX", "ssid": "XX", "bssid": "XX: XX: XX : XX: XX: XX "," parent_id ":" "," parent_model ":" "," show_mode ": 1," modèle ":" viomi.vacuum.v7 ", " adminFlag ": 1," shareFlag ": 0, "permitLevel": 16, "isOnline": true, "desc": "Appareil en ligne", "extra": {"isSetPincode": 0, "fw_version": "3.5.3_0042 "," needVerifyCode ": 0," isPasswordEncrypt ": 0}

Où avez-vous obtenu cette information? Je ne trouve pas le mien dans / Smarthome / log files

I got the information from smarthome / logs with version 5.4.54 of the Mi home application (Xiaomi home)

@rezmus
Copy link

rezmus commented Nov 7, 2019

my best guess is that local api is disabled after provisioning, because in the plugin all requests are forced to send via cloud when usually mi home decides whenever use local or cloud.

@edubox
Copy link

edubox commented Nov 7, 2019

Numéro de modèle: STYJ02YM
Capture d'écran 2019-10-01 à 09 17 11
avec mon domicile 5.4.54:
{"did": "27XXX6986", "jeton": "72676b4a764bXXXXXXXXXXXXXX5363", "longitude": "XXX", "latitude": "XXX", " nom": "Mi Robot Vacuum-Mop P" , "pid": "0", "localip": "192.168.0.35", "mac": "XX: XX: XX: XX: XX", "ssid": "XX", "bssid": "XX: XX: XX : XX: XX: XX "," parent_id ":" "," parent_model ":" "," show_mode ": 1," modèle ":" viomi.vacuum.v7 ", " adminFlag ": 1," shareFlag ": 0, "permitLevel": 16, "isOnline": true, "desc": "Appareil en ligne", "extra": {"isSetPincode": 0, "fw_version": "3.5.3_0042 "," needVerifyCode ": 0," isPasswordEncrypt ": 0}

Où avez-vous obtenu cette information? Je ne trouve pas le mien dans / Smarthome / log files

I got the information from smarthome / logs with version 5.4.54 of the Mi home application (Xiaomi home)

Thanks! Got it now! :)

@edubox
Copy link

edubox commented Nov 7, 2019

my best guess is that local api is disabled after provisioning, because in the plugin all requests are forced to send via cloud when usually mi home decides whenever use local or cloud.

The problem is that this robot is manufactured by Viomi, not Roborock like other models, I think that the way of use it is not the same and maybe will be impossible to support it (at least not in the same way)

@rezmus
Copy link

rezmus commented Nov 7, 2019

vedor is not important, because all miio devices use same way to communicate, they just use different methods/props. problem here is that local udp 54321 looks disabled after provisioning, so only cloud rpc is used (normally it is only used when device is in different network).

@ABRT29
Copy link

ABRT29 commented Nov 7, 2019

I am not an expert in this area but what you are saying is that it will be impossible to integrate it into Home-Assistant?

@rezmus
Copy link

rezmus commented Nov 7, 2019

seems not possible with local api.

@nqkdev
Copy link

nqkdev commented Nov 9, 2019

I did a quick test with this:

miio protocol call 192.168.1.105 get_prop '["run_state","mode","err_state","battary_life","box_type","mop_type","s_time","s_area","suction_grade","water_grade","remember_map","has_map","is_mop","has_newmap"]'

and got a response so local api is possible 👍

[
  5,
  0,
  2103,
  85,
  3,
  1,
  0,
  0,
  1,
  11,
  1,
  1,
  1,
  0
]

@rezmus
Copy link

rezmus commented Nov 9, 2019

good news! i wonder why all ppl before had problems using local api. maybe it's related to firmware version?

@nqkdev
Copy link

nqkdev commented Nov 9, 2019

I think the api has changed. I don't have the other vacuum so can't tell the difference. Also, Mi home does not connect directly to the local api but it sends rpc commands to the cloud so, without internet, the robot is useless :p

@ABRT29
Copy link

ABRT29 commented Nov 10, 2019

it does not work like the other models? I would like to drive it from Home-Assistant even if my internet connection is broken

@kwetnico
Copy link
Author

kwetnico commented Nov 10, 2019

ça ne marche pas comme les autres modèles? Je voudrais le conduire à partir de Home-Assistant même si ma connexion Internet est interrompue

Me too but with Jeedom (not possible with Google Home 😢)

@jevd
Copy link

jevd commented Nov 11, 2019

Hello,
Same for me, I can't use miiocli or mirobo to manage my Xiaomi STYJ02YM.

When not registered on miHome:
mirobo discover --handshake 1
sends me the IP (192.168.5.1) and token.

When registered on miHome, vacuum is still detected, but seems not supported:

mirobo discover
INFO:miio.discovery:Discovering devices with mDNS, press any key to quit...
WARNING:miio.discovery:Found unsupported device viomi-vacuum-v7_miio308780740._miio._udp.local. at 192.168.0.16, please report to developers

I scanned UDP ports with nmap (vacuum registered on miHome), opened ports are:
53, 67, 5353, 54321

But commands ends with time out.

miiocli vacuum --ip 192.168.0.16 --token xxx status
Running command status
ERROR:miio.device:Got error when receiving: timed out

mirobo --ip 192.168.0.16 --token xxx info
ERROR:miio.device:Got error when receiving: timed out

I would be happy to help for investigation. :-)

@rytilahti
Copy link
Owner

@jevd

When registered on miHome, vacuum is still detected, but seems not supported:

You are using --handshake 1 in your first example and omitting it for the second. Will it respond with --handshake 1 after being provisioned?

Also, are you able to request the properties as mentioned by @nqkdev?

Anyway, after the device is provisioned, it's token gets changed and that's why you are getting timed outs.

@nqkdev am I interpreting you correctly, that you were able to request these properties using some firmware version, but that it's blocked in some other? If those properties work in "local mode", it would be fairly simple to add a preliminary implementation for this.

@nqkdev
Copy link

nqkdev commented Nov 11, 2019

@rytilahti I am using the latest firmware (3.5.3_0044). I don't think the local api is blocked in any version. Only the methods and params are different. I was able to figure out a few rpc commands for this.

Just did a quick hack so that it works with my home-assistant. Check it out here

@jevd
Copy link

jevd commented Nov 11, 2019

@rytilahti ,
After registration on miHome, i use an old version 5.4.54 to get the token and test the other commands. So i suppose it's ok...

When registered on miHome, the handshake command result is

mirobo discover --handshake 1
INFO:miio.device:Sending discovery to <broadcast> with timeout of 5s..
INFO:miio.device:  IP 192.168.0.16 (ID: xxxxxx) - token: b'ffffffffffffffffffffffffffffffff'
INFO:miio.device:Discovery done

i don't know which version of miio is used by @nqkdev , but i don't have that command available ("miio protocol call") in my mirobo version 0.4.7).

All the commands i send to the vacuum ends in time out.

miiocli vacuum --ip 192.168.0.16 --token XXXXXXXXXXXXXXXXX status
Running command status

ERROR:miio.device:Got error when receiving: timed out
Error: No response from the device
miiocli -d device --ip 192.168.0.16 --token XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX info
INFO:miio.cli:Debug mode active
DEBUG:miio.protocol:Unable to decrypt, returning raw bytes: b''
DEBUG:miio.device:Got a response: Container:
    data = Container:
        data = b'' (total 0)
        value = b'' (total 0)
        offset1 = 32
        offset2 = 32
        length = 0
    header = Container:
        data = b'!1\x00 \x00\x00\x00\x00\xxxxxxxxx\xe0l' (total 16)
        value = Container:
            length = 32
            unknown = 0
            device_id = b'xxxxx' (total 4)
            ts = 2019-11-11 22:27:56
        offset1 = 0
        offset2 = 16
        length = 16
    checksum = b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff' (total 16)
DEBUG:miio.device:Discovered xxxxxx
 with ts: 2019-11-11 22:27:56, token: b'ffffffffffffffffffffffffffffffff'
DEBUG:miio.device:192.168.0.16:54321 >>: {'id': 1, 'method': 'miIO.info', 'params': []}
DEBUG:miio.device:192.168.0.16:54321 (ts: 2019-11-11 22:27:56, id: 1) << {'partner_id': '', 'id': 1, 'code': 0, 'message': 'ok', 'result': {'hw_ver': 'Linux', 'fw_ver': '3.5.3_0044', 'ap': {'ssid': 'XXXXX', 'bssid': 'XXXXXXX'}, 'netif': {'localIp': '192.168.0.16', 'mask': '255.255.255.0', 'gw': '192.168.0.1'}, 'model': 'viomi.vacuum.v7', 'mac': '5C:E5:0C:XX:XX:XX', 'token': 'XXXXXXXXXXXXXXXXXXXXXXXXX', 'life': 258083}}
Model: viomi.vacuum.v7
Hardware version: Linux
Firmware version: 3.5.3_0044
Network: {'localIp': '192.168.0.16', 'mask': '255.255.255.0', 'gw': '192.168.0.1'}
AP: {'ssid': 'XXXXXX', 'bssid': 'XXXXXXX'}

please find the result of status command with debug enabled in attachment.

status command.txt
sorry for deleting previous post, but i forgot to remove sensitive info.

rytilahti added a commit that referenced this issue Nov 12, 2019
Based on findings done by @nqkdev - thanks a lot for help!
This is the initial PR to fix #550 - plenty of values are still unknown so any help is welcome!
@rytilahti
Copy link
Owner

I just created a PR based on the work done by @nqkdev, thanks a lot! 🎉

Please feel to test the linked PR and report your findings:

$ miiocli viomivacuum
Usage: miiocli viomivacuum [OPTIONS] COMMAND [ARGS]...

Options:
  --ip TEXT     [required]
  --token TEXT  [required]
  --help        Show this message and exit.

Commands:
  home           Return to home.
  info           Get miIO protocol information from the device.
  pause          Pause cleaning.
  raw_command    Send a raw command to the device.
  set_fan_speed  Set fanspeed [silent, standard, medium, turbo].
  start          Start cleaning.
  status         Retrieve properties.
  stop           Stop cleaning.

@rytilahti
Copy link
Owner

rytilahti commented Nov 12, 2019

@jevd thanks for your input, too! miio command used by @nqkdev is from https://github.com/aholstenson/miio .

The respective command for python-miio is miiocli raw_command, which can be used to test commands for devices that are not yet supported. So in this case,
miiocli device --ip <address> --token <token> raw_command '["run_state","mode","err_state","battary_life","box_type","mop_type","s_time","s_area","suction_grade","water_grade","remember_map","has_map","is_mop","has_newmap"]'should return similar output as @nqkdev gave us.

To anyone reading this at some point in the future, the device part here corresponds to the class name of corresponding device, e.g., viomivacuum for the ViomiVacuum class, or vacuum for Vacuum. Device is the base class of all supported devices, so miiocli device --ip <addr> --token <token> info will print out the info and raw_command allows testing of arbitrary commands :-)

@rezmus
Copy link

rezmus commented Nov 12, 2019

similar should work for viomi.vacuum.v6 (V-RVCLM21B).

3rd param of set_mode_withroom is room_array_len and next are room ids ([0, 1, 3, 11, 12, 13] = start cleaning rooms 11-13). room ids are encoded in map and it's part of cloud api so best way to get it is log between device <> mi home app (before map format is supported).

some undocumented methods

set_language [1/2] - voice pack (1 - CN, 2 - EN)
set_carpetturbo [0/1/2] - carpet detection with suction level used on carpets (0 - off, 1 - medium suction, 2 - turbo suction)

there is also multimap support, not yet supported by mi home plugin UI.

list of all methods/params (don't test them if you don't know what you are doing).

get_prop
set_mode
set_pointclean
set_wall
set_zone
set_charge
set_ischarge
set_direction
set_suction
set_repeat
set_broken
set_light
set_voice
set_language
set_ordertime
del_ordertime
get_ordertime
set_notdisturb
get_notdisturb
set_carpetturbo
set_remember
set_calibration
get_curpos
set_resetpos
set_resetmap
set_uploadmap
get_consumables
set_consumables
map_plan
add_map
set_mode_withroom
reset_factory
arrange_room
rename_room
set_mop
set_newmap
set_cardoper
set_iswork
set_timezoneorder
set_auto

hw_info
sw_info
run_state
suction_grade
mode
err_state
battary_life
start_time
order_time
s_time
s_area
v_state
zone_data
repeat_state
remember_map
has_map
water_grade
box_type
mop_type
is_mop
light_state
has_newmap
is_charge
is_work

@boscorelly
Copy link

Thanks, I will try :)

@jevd
Copy link

jevd commented Nov 15, 2019

Hello, thank you for this update :-)
it seems that i have issue to get it working - but it's probably a configuration issue.
Setup:

Ubuntu 18.04 
sudo apt-get install libffi-dev libssl-dev
sudo apt-get install  python3-pip python3-venv python3-dev
python3 -m venv .venv

. .venv/bin/activate
pip3 install -U setuptools
pip3 install asyncio
pip3 install https://github.com/rytilahti/python-miio/archive/viomi.zip

version:
pip3 freeze

appdirs==1.4.3
attrs==19.3.0
cffi==1.13.2
Click==7.0
construct==2.9.45
cryptography==2.8
ifaddr==0.1.6
netifaces==0.10.9
pkg-resources==0.0.0
pycparser==2.19
python-miio==0.4.7
pytz==2019.3
six==1.13.0
tqdm==4.38.0
zeroconf==0.23.0

I can't get any info from the vacuum when it's registered on miHome.
If i unregister it from miHome, it works ! :-) First step OK.

I can run "status", but not "info" command

(.venv) user@server:~$ miiocli viomivacuum --ip 192.168.5.1 --token xxxxxxxxxxxxxxxxxxxxx status

State: ViomiVacuumState.Docked
Mode: 0
Error: None
Battery: 100
Fan speed: ViomiVacuumSpeed.Medium
Box type: 3
Mop type: 1
Clean time: 0:00:00
Clean area: 0
Water level: 12
Remember map: True
Has map: True
Has new map: False
Is mop: True

(.venv) user@server:~$ miiocli viomivacuum --ip 192.168.5.1 --token xxxxxxxxxx info

ERROR:miio.protocol:unable to parse json '': Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
  File "/home/jvn/.venv/bin/miiocli", line 11, in <module>
    load_entry_point('python-miio==0.4.7', 'console_scripts', 'miiocli')()
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/cli.py", line 44, in create_cli
    return cli(auto_envvar_prefix="MIIO")
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/click_common.py", line 59, in __call__
    return self.main(*args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 717, in main
    rv = self.invoke(ctx)
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 1137, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 956, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/click_common.py", line 280, in wrap
    kwargs["result"] = func(*args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/decorators.py", line 64, in new_func
    return ctx.invoke(f, obj, *args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/click/core.py", line 555, in invoke
    return callback(*args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/click_common.py", line 245, in command_callback
    return miio_command.call(miio_device, *args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/click_common.py", line 193, in call
    return method(*args, **kwargs)
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/device.py", line 352, in info
    return DeviceInfo(self.send("miIO.info"))
  File "/home/jvn/.venv/lib/python3.6/site-packages/miio/device.py", line 278, in send
    self.__id = m.data.value["id"]
TypeError: 'NoneType' object is not subscriptable

i didn't tried the other commands.

@jevd
Copy link

jevd commented Nov 17, 2019

Thank you very much @rytilahti and @nqkdev !!
Finally it's working even when registered on miHome :-)

miiocli viomivacuum --ip 192.168.0.16 --token xxx info

Model: viomi.vacuum.v7
Hardware version: Linux
Firmware version: 3.5.3_0044
Network: {'localIp': '192.168.0.16', 'mask': '255.255.255.0', 'gw': '192.168.0.1'}
AP: {'ssid': 'xxx', 'bssid': 'xxx'}

mirobo --ip 192.168.0.16 --token xxxxx raw-command miIO.info

Sending cmd miIO.info with params []
{'hw_ver': 'Linux', 'fw_ver': '3.5.3_0044', 'ap': {'ssid': 'xxxx', 'bssid': 'xxx'}, 'netif': {'localIp': '192.168.0.16', 'mask': '255.255.255.0', 'gw': '192.168.0.1'}, 'model': 'viomi.vacuum.v7', 'mac': '5C:E5:xx:xx:xx:xx', 'token': 'xxxxxx', 'life': 770937}

Edit - now i only got time out response... from the vacuum cleaner
i investigate.

@rumpeltux
Copy link
Contributor

I also tried a bit:

  • Discovery and getting tokens works fine after device reset.
  • The app changes the token during provisioning, using Mi Home v5.4.56, I am able to see the new token in some cache files (in /data/data/com.xiaomi.smarthome/cache/smrc4-cache): adb shell "grep -R '\"token\"' /data/data/com.xiaomi.smarthome"
  • Local API access works after provisioning with the token recovered above
  • Local access stops working within a few minutes. Not sure if it’s getting disabled or there’s another token-change performed.

@rumpeltux
Copy link
Contributor

  • Local access stops working within a few minutes. Not sure if it’s getting disabled or there’s another token-change performed.

Actually it continues to work, but since rerunning the tool doesn’t keep track of the last sequence-id, it needs more retries / higher ids. As a quick fix, I increased retry_count=3 to 20 in device.py and set timeout = 0.5 and now it seems to be working reliably.

@rumpeltux
Copy link
Contributor

@rezmus Out of curiosity: how did you acquire the list of supported commands?

@rezmus
Copy link

rezmus commented Nov 24, 2019

from robot binaries.

rytilahti added a commit that referenced this issue Dec 4, 2019
* Add support for Xiaomi Mijia STYJ02YM (viomi.vacuum.v7)

Based on findings done by @nqkdev - thanks a lot for help!
This is the initial PR to fix #550 - plenty of values are still unknown so any help is welcome!

* update README

* add help message to set_fan_speed

* Add state "idle not docked"

* Add support for a few more commands of the STYJ02YM (#581)

* STYJ02YM: Add support for DND

* STYJ02YM: Add support to change language.

* STYJ02YM: Add support to switch button LEDs on/off

* add carpetturbo as new method, add docstrings
@rumpeltux
Copy link
Contributor

A look at current binaries (3.5.3_0045) reveals a couple of more commands not previously mentioned in #550 (comment):

+miIO.ota
+miIO.get_ota_state
+miIO.get_ota_progress
+deal_map
+set_map
+del_map
+get_map
+rename_map
+upload_map
+set_moproute

In particular it looks like the device may have multimap support.

Similarly there are params for get_prop:

+cur_mapid
+mop_route
+water_percent
+map_num
+side_brush_life
+side_brush_hours
+main_brush_life
+main_brush_hours
+hypa_life
+hypa_hours
+mop_life
+mop_hours

For the map editor:
Sample command to divide a room:
{'method': 'arrange_room', 'params': {'lang': 'de', 'mapID': 1577912345, 'pointArr': [[1, '3.8_0', '5.4_2.35']], 'roomID': 11, 'type': 1}}

Sample command to rename a room:
{'method': 'rename_room', 'params': [1577912345, 1, 11, 'Living Room']}

@ABRT29
Copy link

ABRT29 commented Jan 7, 2020

how to use it from home-assistant?

@silentkiller88
Copy link

r ids. As a quick fix, I

Thanks for this! I was struggeling to get it working but this did the trick. I don't understand why it works after multiple tries and why this is STYJ02YM specific.
Is there the ability to fix this in a future version?

@rytilahti
Copy link
Owner

Yes, this should be fixed in miiocli, currently only mirobo has it implemented (in a very hacky way): https://github.com/rytilahti/python-miio/blob/master/miio/vacuum_cli.py#L58 Feel free to open a new issue for that.

Repository owner locked as resolved and limited conversation to collaborators Jan 14, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.