Comments (46)
Is this problem related to HomeControl?
from hc.
I can confirm this behavior. After a timeout (20-30 seconds) the connection is closed with "[INFO] Close connection and remove session" (https://github.com/brutella/hc/blob/master/netio/connection.go#L108) and iOS can not reconnect any longer. A restart of the HomeControl program fixes this problem imediatelly.
If HomeControl could restart listening quicker would be a good improvement otherwise the devices are unreachable.
from hc.
Yeah, this seem to happen to me too.
from hc.
Same here. Initial pairing works as expected, but after toggling airplane mode my iPhone wonโt reconnect. Is this maybe related to #25 ?
from hc.
If i on my iOS 9 device that won't reconnect (device says disconnected) deletes the connection to one of the brutella devices then i see the delete information on brutella console. So the connection isn't totally dead and removed.
from hc.
I have a similar issue with my iPhone running iOS 9.1.
from hc.
I've just tested it with an iPhone 6 running iOS 9.1, the latest version of HomeControl and the Home app.
I could not reproduce the problem with the following steps:
- Pair with a HomeControl accessory
- Enable Airplane Mode -> Accessory becomes Unreachable
- Disable Airplane Mode -> iOS connects to the accessory as expected
If you experience the issue with the HomeKit Accessory Simulator, then it's definitely an iOS issue.
You can download the HomeKit Accessory Simulator from the Apple Developer Download page.
from hc.
I'm having the same issue with my iPhone 6S Plus, iPhone 5, iPad Air 2 and iPad 3, all running iOS 9.1.
After paring with an accessory and losing connection (toggling Airplane mode, Wifi, or waiting a while) iOS isn't able to reconnect. When I remove the accessory and re-pair it, everything works as expected again until the connection is lost. The code is running on a Raspberry Pi in my case.
I'm not able to download the HomeKit Accessory Simulator from the link you provided, as it isn't listed.
Edit:
This is weird: when I run the code on my Mac, everything is fine. The iPhone reconnects without a problem. It can't, however, reconnect to the exact same program when being run on my Raspberry Pi.
from hc.
@Obbut How did you compile the binary for your rpi? I think you have to use GOARM=5 instead of GOARM=6 because version 6 of the Raspberry has a floating point issue.
See: http://selfcoded.com/blog/2015/07/31/diy-homekit-accessory.html under deployment.
from hc.
@0bscur3 I did indeed compile the binary using GOARM=6
. I didn't know of the floating point issue.
I just tried it, and I can confirm that using GOARM=5
to build it fixes the issue of not being able to reconnect for me. Thank you!
from hc.
Compiling with GOARM=5
fixed this for me.
from hc.
I have the same issue with hc and hklifx. Before i disconnect from WiFi the light bulbs are controllable fine via Siri and the Home app. After reconnecting to my WiFi the bulbs are shown as not reachable. The only thing I can do to fix this is restarting the Bridge. Devices from Homekit Accessory Simulator are reachable instantly after reconnecting so it shouldn't be an iOS bug.
I'm running hc/hklifx on FreeBSD in a Jail (FreeNAS) and all packages are up2date. Go version is 1.5.1 if this matters
EDIT: I also don't get "[INFO] Close connection and remove session" after disconnect from network and waiting 10 minutes. I only get this message when closing the bridge
EDIT2: Same issue on a rPi 2 with golang 1.5.1 on Raspian Jessie. Compiled on rpi with GOARM=7 and 5 - both have exact the same behaviour as the installation on FreeBSD. Whats your go version?
from hc.
Is this still an issue?
from hc.
Hi,
have just tried it with a fresh go (version 1.6.1) installation inside a FreeBSD Jail.
Same issue as some months ago
from hc.
Did you update to the latest hc changes?
from hc.
Yes - I did an complete clean install. I've just changed the broadcast address in pdf/golifx/protocol/v2.go to my subnet's broadcast - without this hklifx doesn't write anything in console/no lights get detected. Can this be the problem?
Are tons of those messages in console are normal:
2016/04/15 14:15:32 [INFO] Unknown Device Event: shared.EventBroadcastSent
from hc.
Does all of your LIFX lights have a different name?
from hc.
Yes they have different names
from hc.
I've done dome debugging on the issue. It seems that the problem is something bonjour related.
When I disable Wifi on iPhone all my bulbs are listed inside _hap._tcp. within bonjour browser. After about 30-60s after I reconnect my Phone to Wifi _hap._tcp. disappears completely from Bonjour Browser. The only way to fix it is by restarting hc/hklifx
from hc.
I'm pretty sure this is related to mDNS.
I've forked the bonjour library and made some changes. Please checkout the hostname
branch on https://github.com/brutella/bonjour. I have it running for some time now and it seems to fix that issue.
from hc.
I've tested with your modified bonjour library. Indeed some "could not bind" error messages regarding IPv6 have disappeared, but the problem remains the same.
_hap._tcp. disappears after some time after the iPhone is reconnected to wireless.
EDIT: What also helps to bring the bulb back reachable in Home app is switching off the bulb, waiting some time and turn it on again. After this hklifx also finds the bulb again:
2016/04/20 08:36:16 [INFO] Discovered Device Martin
2016/04/20 08:36:16 [INFO] Creating New HKLight for Martin
2016/04/20 08:36:16 [INFO] Accessory IP is 192.168.99.27
2016/04/20 08:36:17 [VERB] 192.168.99.40:54073 POST /pair-verify
2016/04/20 08:36:17 [VERB] Create new pair verify controller
2016/04/20 08:36:17 [VERB] -> A: 46d8238208e850cbc0e6c50e00c475ef73dbe09c2e6372639efca72cxxxxxxxx
2016/04/20 08:36:17 [VERB] K: 202a629a3c8739edbb6fb80e396b343c077a219f93b62014a14f49cfcxxxxxxxx
2016/04/20 08:36:17 [VERB] B: f778d70469e67f6b26728ae87a1468d2c2f9983fd9debd8656e9d481xxxxxxxxx
2016/04/20 08:36:17 [VERB] S: e61524929655361eaf0337f38f7c3177c80741b96a6c97a835e1d01xxxxxxxxx
2016/04/20 08:36:17 [VERB] Shared: 905203411abf00f645c693aaa804bbf0b38f5e56d7ef7697798a138xxxxxxxx
2016/04/20 08:36:17 [VERB] <- B: f778d70469e67f6b26728ae87a1468d2c2f9983fd9debd8656e9d4814xxxxxxxx
2016/04/20 08:36:17 [VERB] 192.168.99.40:54073 POST /pair-verify
2016/04/20 08:36:17 [VERB] -> Message: b1dac1fc955e734f5aff65ec9865dd311bf76734a366dee14f10c0780986e42d1579f342011a826d73f8a90960a0581a0bbbc680f3c27ab149e35c2d57c8cd8f8e2545096667bee2975235dd3cc4c060637c4e1bc7d98b0d478a0364e094xxxxxxxxxxxxxxxx
2016/04/20 08:36:17 [VERB] -> MAC: b1257baa6f3338d202299820xxxxxxxx
2016/04/20 08:36:17 [VERB] client: 111ECDD9-4687-41ED-89FB-XXXXXXXXXXX
2016/04/20 08:36:17 [VERB] signature: e688104167c57dd3253c7992653afba6ac67cea7d09069d913ad384ebf4858d979a9e237197eb02d967d9bd788c5a9918c7b76ba1e976c6xxxxxxxxxxxxxx
2016/04/20 08:36:17 [VERB] signature is valid
2016/04/20 08:36:17 [VERB] Setup secure session
2016/04/20 08:36:17 [VERB] 192.168.99.40:54073 GET /accessories
2016/04/20 08:36:17 [VERB] {"accessories":[{"aid":1,"services":[{"iid":1,"type":"3E","characteristics":[{"iid":2,"type":"14","perms":["pw"],"format":"bool"},{"iid":3,"type":"20","perms":["pr"],"value":"LIFX","format":"string"},{"iid":4,"type":"21","perms":["pr"],"value":"undefined","format":"string"},{"iid":5,"type":"23","perms":["pr"],"value":"Martin","format":"string"},{"iid":6,"type":"30","perms":["pr"],"value":"undefined","format":"string"}]},{"iid":7,"type":"43","characteristics":[{"iid":8,"type":"25","perms":["pr","pw","ev"],"value":true,"format":"bool"},{"iid":9,"type":"8","perms":["pr","pw","ev"],"value":100,"format":"int32","unit":"percentage","maxValue":100,"minValue":0,"minStep":1},{"iid":10,"type":"2F","perms":["pr","pw","ev"],"value":0,"format":"float","unit":"percentage","maxValue":100,"minValue":0,"minStep":1},{"iid":11,"type":"13","perms":["pr","pw","ev"],"value":0,"format":"float","unit":"arcdegrees","maxValue":360,"minValue":0,"minStep":1}]}]}]}
2016/04/20 08:36:17 [VERB] 192.168.99.40:54073 PUT /characteristics
2016/04/20 08:36:17 [VERB] {"characteristics":[{"aid":1,"iid":8,"ev":true}]}
2016/04/20 08:36:17 [VERB] 192.168.99.40:54073 GET /characteristics
from hc.
Oddly enough I've had this issue since I began using this library.
It's pretty simple to reproduce and I cannot reproduce it using the homekit simulator or the example provided in this repo, leading me to believe it's coming down to user error on my part (And quite possibly the same cause as above).
Here's what it looks like in my instance (Repo here FYI: https://github.com/nickw444/homekit/tree/master/bridge)
When pairing the bridge, I get this error:
Once pairing is complete, sometimes the accessories won't be able to be controlled (No response):
Upon restarting the homekit bridge all is good:
Until you go offline (i.e. airplane mode).
from hc.
After playing around for a little it seems to even be reproducible in the provided example code:
Initially I thought it may have been to do with using a Bridge type accessory as the first accessory, however that does not seem to be the case. In the example it also seems that toggling wi-fi brings the accessories back to life. (unlike in my actual usage where this does not bring them back to life).
Example code I used using a bridge as the first accessory:
package main
import (
"github.com/brutella/hc"
"github.com/brutella/hc/accessory"
"github.com/brutella/hc/log"
"time"
)
func main() {
switchInfo := accessory.Info{
Name: "BridgeLamp",
}
acc := accessory.NewSwitch(switchInfo)
bridge := accessory.New(accessory.Info{
Name: "TestBridge",
Manufacturer: "nickw",
Model: "bridge",
}, accessory.TypeBridge)
config := hc.Config{Pin: "12344321", Port: "12346", StoragePath: "./db2"}
t, err := hc.NewIPTransport(config, bridge, acc.Accessory)
if err != nil {
log.Info.Panic(err)
}
// Log to console when client (e.g. iOS app) changes the value of the on characteristic
acc.Switch.On.OnValueRemoteUpdate(func(on bool) {
if on == true {
log.Debug.Println("Client changed switch to on")
} else {
log.Debug.Println("Client changed switch to off")
}
})
// Periodically toggle the switch's on characteristic
go func() {
for {
on := !acc.Switch.On.GetValue()
if on == true {
log.Debug.Println("Switch is on")
} else {
log.Debug.Println("Switch is off")
}
acc.Switch.On.SetValue(on)
time.Sleep(5 * time.Second)
}
}()
hc.OnTermination(func() {
t.Stop()
})
t.Start()
}
Edit
I have seemed to get it into a state in which I cannot get my phone re-connect to either instance:
.....
{"characteristics":[{"aid":2,"iid":8,"value":true}]}
DEBUG 2017/04/09 16:00:40 Switch is off
DEBUG 2017/04/09 16:00:40 192.168.8.105:51593 <- EVENT/1.0 200 OK
Content-Length: 53
Content-Type: application/hap+json
{"characteristics":[{"aid":2,"iid":8,"value":false}]}
DEBUG 2017/04/09 16:00:45 Switch is on
DEBUG 2017/04/09 16:00:45 192.168.8.105:51593 <- EVENT/1.0 200 OK
Content-Length: 52
Content-Type: application/hap+json
{"characteristics":[{"aid":2,"iid":8,"value":true}]}
DEBUG 2017/04/09 16:00:48 Close connection and remove session
DEBUG 2017/04/09 16:00:50 Switch is off
DEBUG 2017/04/09 16:00:55 Switch is on
DEBUG 2017/04/09 16:01:00 Switch is off
DEBUG 2017/04/09 16:01:05 Switch is on
DEBUG 2017/04/09 16:01:10 Switch is off
DEBUG 2017/04/09 16:01:15 Switch is on
DEBUG 2017/04/09 16:01:20 Switch is off
DEBUG 2017/04/09 16:01:25 Switch is on
DEBUG 2017/04/09 16:01:30 Switch is off
DEBUG 2017/04/09 16:01:35 Switch is on
DEBUG 2017/04/09 16:01:40 Switch is off
DEBUG 2017/04/09 16:01:45 Switch is on
DEBUG 2017/04/09 16:01:50 Switch is off
DEBUG 2017/04/09 16:01:55 Switch is on
DEBUG 2017/04/09 16:02:00 Switch is off
However, after waiting about a minute and toggling wifi back again, it seems like we're good again:
DEBUG 2017/04/09 16:02:25 Switch is on
DEBUG 2017/04/09 16:02:26 192.168.8.105:51604 POST /pair-verify
DEBUG 2017/04/09 16:02:26 Create new pair verify controller
DEBUG 2017/04/09 16:02:26 -> A: d6f5eb1bc349121ede2106d0bb6b5052d34332a2ca249ad3baf6c5a779a8564a
DEBUG 2017/04/09 16:02:26 K: d3ed5bd48ea157c36c582b481af6e8b725d13aa418fecc655ed2c8ddc7e68af5
DEBUG 2017/04/09 16:02:26 B: 21d16067583cd6570959999372e423dff8943eef398045c46cad4b840be56f60
DEBUG 2017/04/09 16:02:26 S: 3cd05e6d32d5bf3b593c081ab38326a4ade56fe5d90058354a886a87a72dddff
DEBUG 2017/04/09 16:02:26 Shared: 8eb9adf67ea95e394229320e6d246ed0f46e0509a157232f48e466a5c9d9be10
DEBUG 2017/04/09 16:02:26 <- B: 21d16067583cd6570959999372e423dff8943eef398045c46cad4b840be56f60
DEBUG 2017/04/09 16:02:26 192.168.8.105:51604 POST /pair-verify
DEBUG 2017/04/09 16:02:26 -> Message: c1dc223dc8162e4a471d5ee428e2e3854b907029ae8e5764820b9d59c04577f35711cf4e3ad8d0e3e8950bb7cba820646497c8426f769d394287f473342dcb1e01bf756e9d29ce92ab1ef57bb2187ef8eda4be7bab6fae4742209053b01f0b05538d19ec816e63f1
DEBUG 2017/04/09 16:02:26 -> MAC: d1a6b46872c3dfe54186cee17605dcf2
DEBUG 2017/04/09 16:02:26 client: 3DB7D2BA-3D93-4F81-B262-150D8281978E
DEBUG 2017/04/09 16:02:26 signature: 10e171b6ec69e8bb436b2f5ad47c71c4d92b7226638c2e6a24aca6e09d02fbe3ef9f7ff601023c3043aaeb113f03058672b33407f874b4424c83dde9271c3004
DEBUG 2017/04/09 16:02:26 signature is valid
DEBUG 2017/04/09 16:02:26 Setup secure session
DEBUG 2017/04/09 16:02:26 192.168.8.105:51604 GET /accessories
DEBUG 2017/04/09 16:02:26 {"accessories":[{"aid":1,"services":[{"iid":1,"type":"3E","characteristics":[{"iid":2,"type":"14","perms":["pw"],"format":"bool"},{"iid":3,"type":"20","perms":["pr"],"value":"nickw","format":"string"},{"iid":4,"type":"21","perms":["pr"],"value":"bridge","format":"string"},{"iid":5,"type":"23","perms":["pr"],"value":"TestBridge","format":"string"},{"iid":6,"type":"30","perms":["pr"],"value":"undefined","format":"string"}]}]},{"aid":2,"services":[{"iid":1,"type":"3E","characteristics":[{"iid":2,"type":"14","perms":["pw"],"format":"bool"},{"iid":3,"type":"20","perms":["pr"],"value":"undefined","format":"string"},{"iid":4,"type":"21","perms":["pr"],"value":"undefined","format":"string"},{"iid":5,"type":"23","perms":["pr"],"value":"BridgeLamp","format":"string"},{"iid":6,"type":"30","perms":["pr"],"value":"undefined","format":"string"}]},{"iid":7,"type":"49","characteristics":[{"iid":8,"type":"25","perms":["pr","pw","ev"],"value":true,"format":"bool"}]}]}]}
DEBUG 2017/04/09 16:02:26 192.168.8.105:51604 PUT /characteristics
DEBUG 2017/04/09 16:02:26 {"characteristics":[{"aid":2,"iid":8,"ev":true}]}
DEBUG 2017/04/09 16:02:26 192.168.8.105:51604 GET /characteristics
DEBUG 2017/04/09 16:02:30 Switch is off
DEBUG 2017/04/09 16:02:30 192.168.8.105:51604 <- EVENT/1.0 200 OK
Content-Length: 53
Content-Type: application/hap+json
from hc.
Done a fair bit more playing around with this - it seems like some sort of timeout issue with bad
signal + large amount of accessories connected to the bridge.
Creating a bridge with a single accessory, almost always succeeds, when pairing I do not get the "could not complete operation" alert ever. Start adding more accessories, the likelihood of this gets greater. Additionally, it appears if I go to an area with lower wifi signal strength, the likelihood also increases for smaller number of accessories attached to a bridge.
Looking at the source of hklifx, it appears each light detected actually creates it's own HC IP Transport: https://github.com/brutella/hklifx/blob/master/hklifxd.go#L155.
Edit: Looks like I still have trouble pairing devices once I hit a ~10 even if they each have their own transport.
Edit2: After going back to my original implementation (A single bridge accessory + numerous accessories), Adding 12 accessories appears to work fine - most of the time, however after adding an additional accessory, during pairing i am unable to even get past the "Pairing X, make sure it stays connected to power and nearby" screen. The log from HC outputs:
DEBUG 2017/07/02 22:37:23 Event: paired with device
DEBUG 2017/07/02 22:37:23 [pv=1.0 id=3c:2e:39:d6:ed:d8 c#=1 s#=1 sf=0 ff=0 md=MainBridge ci=2]
DEBUG 2017/07/02 22:37:23 Close connection and remove session
Edit3: Refactored my project to allow passing in a dummy MQTT instance, just in case that was causing some goroutine scheduling weirdness - doing this had no effect ๐ข
from hc.
Looking over at nfarina/homebridge, it appears they have similar issues:
from hc.
@nickw444 Did you test this without running an instance of an MQTT client?
from hc.
Yep, as mentioned above, I refactored my repo to allow DI of MQTT (using a simple interface), and passed a dummy implementation (which did not use MQTT at all)
from hc.
I should mention that all of my devices are running iOS 10 & tvOS 10, and I'm having these issues. I don't remember this cropping up until I added a 3rd bridged accessory.
from hc.
Same here, iOS10 on all my devices. Should also make note that the issue seemed more prominent when using an iPad (iOS 10) as a home hub - it's not as bad now though. I turned it off as a home hub, and it seemed to improve the situation.
from hc.
I shutdown my iPad at home, which was the original HomeKit host, so now it's just my ATV4 running. I also changed the default port number.
The accessory connections have been stable for the past 45 minutes, so fingers crossed.
from hc.
@Tylerflick, how'd you end up? Any connectivity issues?
from hc.
hi , all! i have a same trouble. i had tested on macox , ubuntu. I try use my iphone 6 s with ios 10.3.2
from hc.
My iphone was disconnected from bridge after 2-5 minutes
from hc.
Removing my iPad as a hub solved my issues, but I'm only running 3 accessories on my server.
My setup is as follows:
- Clients: iPhone 6s (iOS10), iPad Air 2 (iOS10)
- Hub: Apple TV4 (tvOS10)
- Server: Raspberry Pi 3 running Raspbian (hc compiled with ARM v7)
from hc.
Weird, I can reproduce consistently by building/running on an OSX El Cap machine- usually response errors during pairing, but after clicking through and restarting the bridge it all works (for a few minutes or until disconnection)
Not so consistently (but rather intermittently) on a MacBook running Sierra;
Building on the el-cap machine, targeting arm v5 or v6 and running on a Rpi2 seems to have occur but not as frequently - pairing almost always successful.
Worth mentioning I have an ATV3 but (obviously, thanks apple) can't use it as a home hub.
from hc.
I'm wondering if this has something to do with Avahi. You're using an iPad as a hub?
from hc.
Yep, using an iPad as a hub but it's still intermittent with the iPad hub functionality turned off. It could quite be avahi, but if that was the case it should be working on macOS, since it uses mdns (or whatever it's called now) rather than avahi
from hc.
It could also be a firewall setting on your mac. I saw that suggestion pop up on of the linked issues. Have you looked at the port Homecontrol is running on?
from hc.
I think this issue comes up because the used bonjour library is not fully compliant with mDNS. The best way to verify that would be to use a different mDNS library and see what happens.
from hc.
That seems like a good idea, I might give that a shot on the weekend if I get some time.
Worth noting, I took delivery of a lifx bulb, I am also experiencing the issue with the hklifx package too.
from hc.
So I updated all the dependencies for my project, recompiled, and it seemed that all my problems were gone. The bridge was working 100% of the time.
After actually investigating the server where the service was running, I soon came to realise there was a bug in one of my deps, causing a panic every now and then - essentially restarting the bridge.
This really got my hopes up - I really do wish we can figure out why mdns/bonjour is so flakey (in my usage at least).
Also, would it be worth renaming this issue to something that doesn't specifically target iOS9 - this is definitely an issue with other OS versions.
from hc.
I've made a new dnssd library which passes the multicast DNS test of Apple's Bonjour Conformance Test โ as you can see here.
This library is for now used in the dnssd branch of HomeControl. Please check out this branch if you experienced connection issues in the past.
Update on 11-October-2017: The changes are now merged into master.
from hc.
Awesome thanks @brutella. Iโll give it a shot when I get the chance (quite busy at the moment, and my setup is now working flawlessly using the PR I submitted so Iโm not too inclined to potentially end up in another flakey situation again, as itโs not just me using HomeKit in my household).
Side question- is there any reason youโre favouring using your own self rolled library rather than the zeroconf project? Just curious thatโs all.
from hc.
@nickw444 I took it as a challenge to work on a new library and learn more about DNS. ๐ Also the zeroconf project doesn't fully comply with mDNS and DNS-SD.
from hc.
Sounds like a good enough reason to me ๐ I'll pilot the changes on the lifx bridge i'm running (a slightly modified hklifx).
from hc.
Closed due to inactivity
from hc.
Related Issues (20)
- High io load (read)
- Listening to homekit HOT 6
- Quotation mark in accessory name prevents it from being added
- accessory tv HOT 7
- NewIPTransport add validation HOT 3
- Can use from Linux or Android HOT 1
- Issues with dnssd v1.2.0 HOT 5
- specify advertised IP for dnssd HOT 2
- Characteristic: Button Event HOT 2
- Build window fail HOT 2
- multiple accessories events HOT 2
- not support utf-8 chinese language HOT 1
- bridge must not expose more than 150 objects HOT 1
- TemperatureSensor steps ignored HOT 1
- Maintenance status? HOT 4
- addition & examples HOT 2
- Is there has plan to support new device types? HOT 1
- Expose `http.ServeMux` to allow applications to add additional endpoints HOT 1
- Radiation sensor HOT 5
- Client is unknown HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. ๐๐๐
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google โค๏ธ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from hc.