Giter Site home page Giter Site logo

aioasuswrt's People

Contributors

bskaplou avatar chen-il avatar fabaff avatar jjdevries avatar kangaroomadman avatar kennedyshead avatar magnusknutas avatar ollo69 avatar omarali avatar pkishino avatar roblandry avatar tmin10 avatar wdullaer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aioasuswrt's Issues

Timeout errors and IncompleteRead exceptions on telnet connections

Currently while running the asuswrt integration using Home Assistants a lot of Timeout errors and IncompleteRead exceptions are happening. A pull request has been opened on home-assistant/core that partially fixes this.

My feeling is that the underlying issue in the library is not nicely handling a persistent connection in one AsusWrt instance (at least for the TelnetConnection). Currently there is a race issue if two commands are happening (which probably causes the IncompleteRead exceptions). While the Timeouts are probably due to the router not being able to quickly handle consecutive logins.

My proposed solution would be to do simply try to write a command (assuming self._writer is not None), and capture the relevant exceptions if a logout has happened. I'm currently running a test with increasing delays to see what exceptions is actually raised.

Sensors don't work on RT-N66U with merlin

I am running the latest home assistant (0.84.6) and the sensors are always returning 0 with my RT-N66U running merlin 380.70

I have done some investigation and home assistant is correctly calling async_update() (https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/sensor/asuswrt.py#L51) in sensors/asuswrt.py

Looking into the implementation of async_get_packets_total, it seems to be failing at this line in this library: https://github.com/kennedyshead/aioasuswrt/blob/master/aioasuswrt/asuswrt.py#L194
Essentially _IP_LINK_CMD is defined as ip -rc 1024 -s link

Running that on the router yields:

admin@RT-N66U:/tmp/home/root# ip -rc 1024 -s link
Option "-rc" is unknown, try "ip -help".

ip -s link does work, I assume returning the result in bits rather than bytes.

A potential fix could be to convert to bytes in python rather than the shell command (there's a lot of math already happening in python already, so it's not really making the solution less elegant I think).

If this sounds sensible to you, I can supply a PR with this fix.

False positive on RT-AC86U

On the RT-AC86U, the debug script displays this:

DEBUG:asyncio:Using selector: SelectSelector
DEBUG:__main__:wl
C:\Users\Maciek\AppData\Local\Programs\hass\lib\site-packages\asyncssh\crypto\ec.py:176: CryptographyDeprecationWarning: encode_point has been deprecated on EllipticCurvePublicNumbers and will be removed in a future version. Please use EllipticCurvePublicKey.public_bytes to obtain both compressed and uncompressed point encoding.
  return pub.encode_point()
C:\Users\Maciek\AppData\Local\Programs\hass\lib\site-packages\asyncssh\crypto\ec.py:182: CryptographyDeprecationWarning: Support for unsafe construction of public numbers from encoded data will be removed in a future version. Please use EllipticCurvePublicKey.from_encoded_point
  self._priv_key.curve, peer_public).public_key(backend)
C:\Users\Maciek\AppData\Local\Programs\hass\lib\site-packages\asyncssh\crypto\ec.py:144: CryptographyDeprecationWarning: Support for unsafe construction of public numbers from encoded data will be removed in a future version. Please use EllipticCurvePublicKey.from_encoded_point
  public_value)
DEBUG:__main__:['assoclist xx:xx:xx:xx:C0:9D', 'assoclist xx:xx:xx:xx:6F:0B', 'assoclist xx:xx:xx:xx:91:84', 'assoclist xx:xx:xx:xx:95:EF', 'assoclist xx:xx:xx:xx:97:61', 'assoclist xx:xx:xx:xx:7C:81', 'assoclist xx:xx:xx:xx:24:75', 'assoclist xx:xx:xx:xx:26:04', 'assoclist xx:xx:xx:xx:89:00', 'assoclist xx:xx:xx:xx:91:EA', 'assoclist xx:xx:xx:xx:0C:FA', 'assoclist xx:xx:xx:xx:20:26', 'assoclist xx:xx:xx:xx:07:FC', 'assoclist xx:xx:xx:xx:53:24', 'assoclist xx:xx:xx:xx:D8:0D', 'assoclist xx:xx:xx:xx:9D:59', 'assoclist xx:xx:xx:xx:BA:34', 'assoclist xx:xx:xx:xx:98:B6', '']
DEBUG:__main__:{'xx:xx:xx:xx:C0:9D': Device(mac='xx:xx:xx:xx:C0:9D', ip=None, name=None), 'xx:xx:xx:xx:6F:0B': Device(mac='xx:xx:xx:xx:6F:0B', ip=None, name=None), 'xx:xx:xx:xx:91:84': Device(mac='xx:xx:xx:xx:91:84', ip=None, name=None), 'xx:xx:xx:xx:95:EF': Device(mac='xx:xx:xx:xx:95:EF', ip=None, name=None), 'xx:xx:xx:xx:97:61': Device(mac='xx:xx:xx:xx:97:61', ip=None, name=None), 'xx:xx:xx:xx:7C:81': Device(mac='xx:xx:xx:xx:7C:81', ip=None, name=None), 'xx:xx:xx:xx:24:75': Device(mac='xx:xx:xx:xx:24:75', ip=None, name=None), 'xx:xx:xx:xx:26:04': Device(mac='xx:xx:xx:xx:26:04', ip=None, name=None), 'xx:xx:xx:xx:89:00': Device(mac='xx:xx:xx:xx:89:00', ip=None, name=None), 'xx:xx:xx:xx:91:EA': Device(mac='xx:xx:xx:xx:91:EA', ip=None, name=None), 'xx:xx:xx:xx:0C:FA': Device(mac='xx:xx:xx:xx:0C:FA', ip=None, name=None), 'xx:xx:xx:xx:20:26': Device(mac='xx:xx:xx:xx:20:26', ip=None, name=None), 'xx:xx:xx:xx:07:FC': Device(mac='xx:xx:xx:xx:07:FC', ip=None, name=None), 'xx:xx:xx:xx:53:24': Device(mac='xx:xx:xx:xx:53:24', ip=None, name=None), 'xx:xx:xx:xx:D8:0D': Device(mac='xx:xx:xx:xx:D8:0D', ip=None, name=None), 'xx:xx:xx:xx:9D:59': Device(mac='xx:xx:xx:xx:9D:59', ip=None, name=None), 'xx:xx:xx:xx:BA:34': Device(mac='xx:xx:xx:xx:BA:34', ip=None, name=None), 'xx:xx:xx:xx:98:B6': Device(mac='xx:xx:xx:xx:98:B6', ip=None, name=None)}
DEBUG:__main__:arp
DEBUG:__main__:['? (192.168.2.200) at xx:xx:xx:xx:6e:5a [ether]  on br0', '? (192.168.2.90) at xx:xx:xx:xx:6f:0b [ether]  on br0', '? (192.168.2.249) at xx:xx:xx:xx:b6:aa [ether]  on br0', '? (192.168.2.110) at xx:xx:xx:xx:95:ef [ether]  on br0', '? (192.168.2.240) at xx:xx:xx:xx:89:00 [ether]  on br0', '? (192.168.2.40) at xx:xx:xx:xx:56:f4 [ether]  on br0', '? (192.168.2.150) at xx:xx:xx:xx:d8:0d [ether]  on br0', '? (192.168.2.47) at <incomplete>  on br0', '? (192.168.2.115) at xx:xx:xx:xx:9d:59 [ether]  on br0', '? (192.168.2.80) at <incomplete>  on br0', '? (192.168.2.100) at xx:xx:xx:xx:c0:9d [ether]  on br0', '? (192.168.2.3) at xx:xx:xx:xx:07:0d [ether]  on br0', '? (192.168.2.246) at xx:xx:xx:xx:91:ea [ether]  on br0', '? (192.168.2.220) at xx:xx:xx:xx:97:61 [ether]  on br0', '? (192.168.2.170) at xx:xx:xx:xx:ba:34 [ether]  on br0', '? (192.168.2.254) at xx:xx:xx:xx:07:fc [ether]  on br0', '? (192.168.2.2) at xx:xx:xx:xx:b9:9e [ether]  on br0', '? (192.168.2.60) at xx:xx:xx:xx:fe:c4 [ether]  on br0', '? (192.168.2.245) at xx:xx:xx:xx:24:75 [ether]  on br0', '? (192.168.2.210) at <incomplete>  on br0', '? (192.168.1.6) at <incomplete>  on eth0', '? (192.168.2.10) at xx:xx:xx:xx:e3:bd [ether]  on br0', '? (192.168.2.253) at xx:xx:xx:xx:0c:fa [ether]  on br0', '? (192.168.2.160) at xx:xx:xx:xx:91:84 [ether]  on br0', '? (192.168.2.121) at <incomplete>  on br0', '? (192.168.2.244) at <incomplete>  on br0', '? (192.168.2.50) at xx:xx:xx:xx:1e:fb [ether]  on br0', '? (192.168.2.243) at xx:xx:xx:xx:7c:81 [ether]  on br0', '? (192.168.2.120) at xx:xx:xx:xx:98:b6 [ether]  on br0', '? (192.168.2.140) at <incomplete>  on br0', '? (192.168.2.30) at xx:xx:xx:xx:8f:78 [ether]  on br0', '? (192.168.2.189) at <incomplete>  on br0', '? (192.168.2.251) at xx:xx:xx:xx:af:c6 [ether]  on br0', '? (192.168.1.1) at xx:xx:xx:xx:77:56 [ether]  on eth0', '? (192.168.2.174) at <incomplete>  on br0', '? (192.168.2.242) at <incomplete>  on br0', '? (192.168.2.130) at xx:xx:xx:xx:53:24 [ether]  on br0', '? (192.168.2.250) at xx:xx:xx:xx:20:26 [ether]  on br0', '? (192.168.2.20) at xx:xx:xx:xx:9b:3c [ether]  on br0', '? (192.168.2.56) at <incomplete>  on br0', '? (192.168.2.241) at xx:xx:xx:xx:26:04 [ether]  on br0', '']
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.47) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.80) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.210) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.1.6) at <incomplete>  on eth0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.121) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.244) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.140) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.189) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.174) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.242) at <incomplete>  on br0
DEBUG:aioasuswrt.asuswrt:Could not parse row: ? (192.168.2.56) at <incomplete>  on br0
DEBUG:__main__:{'xx:xx:xx:xx:C0:9D': Device(mac='xx:xx:xx:xx:C0:9D', ip='192.168.2.100', name=None), 'xx:xx:xx:xx:6F:0B': Device(mac='xx:xx:xx:xx:6F:0B', ip='192.168.2.90', name=None), 'xx:xx:xx:xx:91:84': Device(mac='xx:xx:xx:xx:91:84', ip='192.168.2.160', name=None), 'xx:xx:xx:xx:95:EF': Device(mac='xx:xx:xx:xx:95:EF', ip='192.168.2.110', name=None), 'xx:xx:xx:xx:97:61': Device(mac='xx:xx:xx:xx:97:61', ip='192.168.2.220', name=None), 'xx:xx:xx:xx:7C:81': Device(mac='xx:xx:xx:xx:7C:81', ip='192.168.2.243', name=None), 'xx:xx:xx:xx:24:75': Device(mac='xx:xx:xx:xx:24:75', ip='192.168.2.245', name=None), 'xx:xx:xx:xx:26:04': Device(mac='xx:xx:xx:xx:26:04', ip='192.168.2.241', name=None), 'xx:xx:xx:xx:89:00': Device(mac='xx:xx:xx:xx:89:00', ip='192.168.2.240', name=None), 'xx:xx:xx:xx:91:EA': Device(mac='xx:xx:xx:xx:91:EA', ip='192.168.2.246', name=None), 'xx:xx:xx:xx:0C:FA': Device(mac='xx:xx:xx:xx:0C:FA', ip='192.168.2.253', name=None), 'xx:xx:xx:xx:20:26': Device(mac='xx:xx:xx:xx:20:26', ip='192.168.2.250', name=None), 'xx:xx:xx:xx:07:FC': Device(mac='xx:xx:xx:xx:07:FC', ip='192.168.2.254', name=None), 'xx:xx:xx:xx:53:24': Device(mac='xx:xx:xx:xx:53:24', ip='192.168.2.130', name=None), 'xx:xx:xx:xx:D8:0D': Device(mac='xx:xx:xx:xx:D8:0D', ip='192.168.2.150', name=None), 'xx:xx:xx:xx:9D:59': Device(mac='xx:xx:xx:xx:9D:59', ip='192.168.2.115', name=None), 'xx:xx:xx:xx:BA:34': Device(mac='xx:xx:xx:xx:BA:34', ip='192.168.2.170', name=None), 'xx:xx:xx:xx:98:B6': Device(mac='xx:xx:xx:xx:98:B6', ip='192.168.2.120', name=None), 'xx:xx:xx:xx:6E:5A': Device(mac='xx:xx:xx:xx:6E:5A', ip='192.168.2.200', name=None), 'xx:xx:xx:xx:B6:AA': Device(mac='xx:xx:xx:xx:B6:AA', ip='192.168.2.249', name=None), 'xx:xx:xx:xx:56:F4': Device(mac='xx:xx:xx:xx:56:F4', ip='192.168.2.40', name=None), 'xx:xx:xx:xx:07:0D': Device(mac='xx:xx:xx:xx:07:0D', ip='192.168.2.3', name=None), 'xx:xx:xx:xx:B9:9E': Device(mac='xx:xx:xx:xx:B9:9E', ip='192.168.2.2', name=None), 'xx:xx:xx:xx:FE:C4': Device(mac='xx:xx:xx:xx:FE:C4', ip='192.168.2.60', name=None), 'xx:xx:xx:xx:E3:BD': Device(mac='xx:xx:xx:xx:E3:BD', ip='192.168.2.10', name=None), 'xx:xx:xx:xx:1E:FB': Device(mac='xx:xx:xx:xx:1E:FB', ip='192.168.2.50', name=None), 'xx:xx:xx:xx:8F:78': Device(mac='xx:xx:xx:xx:8F:78', ip='192.168.2.30', name=None), 'xx:xx:xx:xx:AF:C6': Device(mac='xx:xx:xx:xx:AF:C6', ip='192.168.2.251', name=None), 'xx:xx:xx:xx:77:56': Device(mac='xx:xx:xx:xx:77:56', ip='192.168.1.1', name=None), 'xx:xx:xx:xx:9B:3C': Device(mac='xx:xx:xx:xx:9B:3C', ip='192.168.2.20', name=None)}
DEBUG:__main__:neigh
DEBUG:__main__:['192.168.2.200 dev br0 lladdr xx:xx:xx:xx:6e:5a STALE', '192.168.2.90 dev br0 lladdr xx:xx:xx:xx:6f:0b STALE', '192.168.2.249 dev br0 lladdr xx:xx:xx:xx:b6:aa STALE', '192.168.2.110 dev br0 lladdr xx:xx:xx:xx:95:ef REACHABLE', '192.168.2.240 dev br0 lladdr xx:xx:xx:xx:89:00 REACHABLE', '192.168.2.40 dev br0 lladdr xx:xx:xx:xx:56:f4 STALE', '192.168.2.150 dev br0 lladdr xx:xx:xx:xx:d8:0d REACHABLE', '192.168.2.47 dev br0  FAILED', '192.168.2.115 dev br0 lladdr xx:xx:xx:xx:9d:59 STALE', '192.168.2.80 dev br0  FAILED', '192.168.2.100 dev br0 lladdr xx:xx:xx:xx:c0:9d STALE', '192.168.2.3 dev br0 lladdr xx:xx:xx:xx:07:0d STALE', '192.168.2.246 dev br0 lladdr xx:xx:xx:xx:91:ea STALE', '192.168.2.220 dev br0 lladdr xx:xx:xx:xx:97:61 REACHABLE', '192.168.2.170 dev br0 lladdr xx:xx:xx:xx:ba:34 STALE', '192.168.2.254 dev br0 lladdr xx:xx:xx:xx:07:fc STALE', '192.168.2.2 dev br0 lladdr xx:xx:xx:xx:b9:9e STALE', '192.168.2.60 dev br0 lladdr xx:xx:xx:xx:fe:c4 STALE', '192.168.2.245 dev br0 lladdr xx:xx:xx:xx:24:75 STALE', '192.168.2.210 dev br0  FAILED', '192.168.1.6 dev eth0  FAILED', '192.168.2.10 dev br0 lladdr xx:xx:xx:xx:e3:bd STALE', '192.168.2.253 dev br0 lladdr xx:xx:xx:xx:0c:fa REACHABLE', '192.168.2.160 dev br0 lladdr xx:xx:xx:xx:91:84 STALE', '192.168.2.121 dev br0  FAILED', '192.168.2.244 dev br0  FAILED', '192.168.2.50 dev br0 lladdr xx:xx:xx:xx:1e:fb STALE', '192.168.2.243 dev br0 lladdr xx:xx:xx:xx:7c:81 STALE', '192.168.2.120 dev br0 lladdr xx:xx:xx:xx:98:b6 REACHABLE', '192.168.2.140 dev br0  FAILED', '192.168.2.30 dev br0 lladdr xx:xx:xx:xx:8f:78 REACHABLE', '192.168.2.189 dev br0  FAILED', '192.168.2.251 dev br0 lladdr xx:xx:xx:xx:af:c6 STALE', '192.168.1.1 dev eth0 lladdr xx:xx:xx:xx:77:56 DELAY', '192.168.2.174 dev br0  FAILED', '192.168.2.242 dev br0  FAILED', '192.168.2.130 dev br0 lladdr xx:xx:xx:xx:53:24 STALE', '192.168.2.250 dev br0 lladdr xx:xx:xx:xx:20:26 REACHABLE', '192.168.2.20 dev br0 lladdr xx:xx:xx:xx:9b:3c STALE', '192.168.2.56 dev br0  FAILED', '192.168.2.241 dev br0 lladdr xx:xx:xx:xx:26:04 STALE', '']
DEBUG:__main__:{'xx:xx:xx:xx:C0:9D': Device(mac='xx:xx:xx:xx:C0:9D', ip='192.168.2.100', name=None), 'xx:xx:xx:xx:6F:0B': Device(mac='xx:xx:xx:xx:6F:0B', ip='192.168.2.90', name=None), 'xx:xx:xx:xx:91:84': Device(mac='xx:xx:xx:xx:91:84', ip='192.168.2.160', name=None), 'xx:xx:xx:xx:95:EF': Device(mac='xx:xx:xx:xx:95:EF', ip='192.168.2.110', name=None), 'xx:xx:xx:xx:97:61': Device(mac='xx:xx:xx:xx:97:61', ip='192.168.2.220', name=None), 'xx:xx:xx:xx:7C:81': Device(mac='xx:xx:xx:xx:7C:81', ip='192.168.2.243', name=None), 'xx:xx:xx:xx:24:75': Device(mac='xx:xx:xx:xx:24:75', ip='192.168.2.245', name=None), 'xx:xx:xx:xx:26:04': Device(mac='xx:xx:xx:xx:26:04', ip='192.168.2.241', name=None), 'xx:xx:xx:xx:89:00': Device(mac='xx:xx:xx:xx:89:00', ip='192.168.2.240', name=None), 'xx:xx:xx:xx:91:EA': Device(mac='xx:xx:xx:xx:91:EA', ip='192.168.2.246', name=None), 'xx:xx:xx:xx:0C:FA': Device(mac='xx:xx:xx:xx:0C:FA', ip='192.168.2.253', name=None), 'xx:xx:xx:xx:20:26': Device(mac='xx:xx:xx:xx:20:26', ip='192.168.2.250', name=None), 'xx:xx:xx:xx:07:FC': Device(mac='xx:xx:xx:xx:07:FC', ip='192.168.2.254', name=None), 'xx:xx:xx:xx:53:24': Device(mac='xx:xx:xx:xx:53:24', ip='192.168.2.130', name=None), 'xx:xx:xx:xx:D8:0D': Device(mac='xx:xx:xx:xx:D8:0D', ip='192.168.2.150', name=None), 'xx:xx:xx:xx:9D:59': Device(mac='xx:xx:xx:xx:9D:59', ip='192.168.2.115', name=None), 'xx:xx:xx:xx:BA:34': Device(mac='xx:xx:xx:xx:BA:34', ip='192.168.2.170', name=None), 'xx:xx:xx:xx:98:B6': Device(mac='xx:xx:xx:xx:98:B6', ip='192.168.2.120', name=None), 'xx:xx:xx:xx:6E:5A': Device(mac='xx:xx:xx:xx:6E:5A', ip='192.168.2.200', name=None), 'xx:xx:xx:xx:B6:AA': Device(mac='xx:xx:xx:xx:B6:AA', ip='192.168.2.249', name=None), 'xx:xx:xx:xx:56:F4': Device(mac='xx:xx:xx:xx:56:F4', ip='192.168.2.40', name=None), 'xx:xx:xx:xx:07:0D': Device(mac='xx:xx:xx:xx:07:0D', ip='192.168.2.3', name=None), 'xx:xx:xx:xx:B9:9E': Device(mac='xx:xx:xx:xx:B9:9E', ip='192.168.2.2', name=None), 'xx:xx:xx:xx:FE:C4': Device(mac='xx:xx:xx:xx:FE:C4', ip='192.168.2.60', name=None), 'xx:xx:xx:xx:E3:BD': Device(mac='xx:xx:xx:xx:E3:BD', ip='192.168.2.10', name=None), 'xx:xx:xx:xx:1E:FB': Device(mac='xx:xx:xx:xx:1E:FB', ip='192.168.2.50', name=None), 'xx:xx:xx:xx:8F:78': Device(mac='xx:xx:xx:xx:8F:78', ip='192.168.2.30', name=None), 'xx:xx:xx:xx:AF:C6': Device(mac='xx:xx:xx:xx:AF:C6', ip='192.168.2.251', name=None), 'xx:xx:xx:xx:77:56': Device(mac='xx:xx:xx:xx:77:56', ip='192.168.1.1', name=None), 'xx:xx:xx:xx:9B:3C': Device(mac='xx:xx:xx:xx:9B:3C', ip='192.168.2.20', name=None)}
DEBUG:__main__:leases
DEBUG:__main__:['81300 xx:xx:xx:xx:8f:78 192.168.2.30 stacjonarny xx:xx:xx:xx:20:8f:78', '66229 xx:xx:xx:xx:af:c6 192.168.2.251 yeelight-color-v2-bulb *', '66229 xx:xx:xx:xx:b6:aa 192.168.2.249 yeelight-color-bulb-1 *', '43335 xx:xx:xx:xx:b9:9e 192.168.2.2 switch *', '58399 xx:xx:xx:xx:07:0d 192.168.2.3 fingbox xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:4d:25:e0', '50062 xx:xx:xx:xx:56:f4 192.168.2.40 denon xx:xx:xx:xx:45:56:f4', '47420 xx:xx:xx:xx:95:ef 192.168.2.110 harmony xx:xx:xx:xx:fb:95:ef', '53562 xx:xx:xx:xx:26:04 192.168.2.241 shelly2-5b2604 *', '81300 xx:xx:xx:xx:6f:0b 192.168.2.90 migateway *', '45714 xx:xx:xx:xx:20:26 192.168.2.250 yeelight-color-bulb-2 *', '49516 xx:xx:xx:xx:89:00 192.168.2.240 shelly1-328900 *', '46045 xx:xx:xx:xx:0c:fa 192.168.2.253 yeelight-lightstrip-1 *', '45617 xx:xx:xx:xx:07:fc 192.168.2.254 yeelight-lightstrip-2 *', '79862 xx:xx:xx:xx:97:61 192.168.2.220 mihumidifier *', '69946 xx:xx:xx:xx:1e:fb 192.168.2.50 playstation xx:xx:xx:xx:5f:1e:fb', '56383 xx:xx:xx:xx:24:75 192.168.2.245 sonoff-s26-182475 *', '67469 xx:xx:xx:xx:91:ea 192.168.2.246 wemos-d1-mini-1c91ea *', '76330 xx:xx:xx:xx:c0:9d 192.168.2.100 brother xx:xx:xx:xx:33:c0:9d', '47210 xx:xx:xx:xx:98:b6 192.168.2.120 androidtv xx:xx:xx:xx:95:98:b6', '50243 xx:xx:xx:xx:53:24 192.168.2.130 dafang xx:xx:xx:xx:e5:53:24', '56136 xx:xx:xx:xx:7c:81 192.168.2.243 sonoff-basic-067c81 *', '48747 xx:xx:xx:xx:e3:bd 192.168.2.10 synology xx:xx:xx:xx:0a:e3:bd', '56122 xx:xx:xx:xx:9b:3c 192.168.2.20 raspberry xx:xx:xx:xx:28:9b:3c', '61531 xx:xx:xx:xx:83:e1 192.168.2.140 oneplus xx:xx:xx:xx:31:83:e1', '52998 xx:xx:xx:xx:ba:34 192.168.2.170 ipad xx:xx:xx:xx:df:ba:34', '68120 xx:xx:xx:xx:9d:59 192.168.2.115 iPad-Edyta xx:xx:xx:xx:4b:9d:59', '78620 xx:xx:xx:xx:d8:0d 192.168.2.150 iphone xx:xx:xx:xx:e7:d8:0d', '61788 xx:xx:xx:xx:91:84 192.168.2.160 lumia xx:xx:xx:xx:8c:91:84', '']
DEBUG:__main__:{'xx:xx:xx:xx:C0:9D': Device(mac='xx:xx:xx:xx:C0:9D', ip='192.168.2.100', name='brother'), 'xx:xx:xx:xx:6F:0B': Device(mac='xx:xx:xx:xx:6F:0B', ip='192.168.2.90', name='migateway'), 'xx:xx:xx:xx:91:84': Device(mac='xx:xx:xx:xx:91:84', ip='192.168.2.160', name='lumia'), 'xx:xx:xx:xx:95:EF': Device(mac='xx:xx:xx:xx:95:EF', ip='192.168.2.110', name='harmony'), 'xx:xx:xx:xx:97:61': Device(mac='xx:xx:xx:xx:97:61', ip='192.168.2.220', name='mihumidifier'), 'xx:xx:xx:xx:7C:81': Device(mac='xx:xx:xx:xx:7C:81', ip='192.168.2.243', name='sonoff-basic-067c81'), 'xx:xx:xx:xx:24:75': Device(mac='xx:xx:xx:xx:24:75', ip='192.168.2.245', name='sonoff-s26-182475'), 'xx:xx:xx:xx:26:04': Device(mac='xx:xx:xx:xx:26:04', ip='192.168.2.241', name='shelly2-5b2604'), 'xx:xx:xx:xx:89:00': Device(mac='xx:xx:xx:xx:89:00', ip='192.168.2.240', name='shelly1-328900'), 'xx:xx:xx:xx:91:EA': Device(mac='xx:xx:xx:xx:91:EA', ip='192.168.2.246', name='wemos-d1-mini-1c91ea'), 'xx:xx:xx:xx:0C:FA': Device(mac='xx:xx:xx:xx:0C:FA', ip='192.168.2.253', name='yeelight-lightstrip-1'), 'xx:xx:xx:xx:20:26': Device(mac='xx:xx:xx:xx:20:26', ip='192.168.2.250', name='yeelight-color-bulb-2'), 'xx:xx:xx:xx:07:FC': Device(mac='xx:xx:xx:xx:07:FC', ip='192.168.2.254', name='yeelight-lightstrip-2'), 'xx:xx:xx:xx:53:24': Device(mac='xx:xx:xx:xx:53:24', ip='192.168.2.130', name='dafang'), 'xx:xx:xx:xx:D8:0D': Device(mac='xx:xx:xx:xx:D8:0D', ip='192.168.2.150', name='iphone'), 'xx:xx:xx:xx:9D:59': Device(mac='xx:xx:xx:xx:9D:59', ip='192.168.2.115', name='iPad-Edyta'), 'xx:xx:xx:xx:BA:34': Device(mac='xx:xx:xx:xx:BA:34', ip='192.168.2.170', name='ipad'), 'xx:xx:xx:xx:98:B6': Device(mac='xx:xx:xx:xx:98:B6', ip='192.168.2.120', name='androidtv'), 'xx:xx:xx:xx:6E:5A': Device(mac='xx:xx:xx:xx:6E:5A', ip='192.168.2.200', name=None), 'xx:xx:xx:xx:B6:AA': Device(mac='xx:xx:xx:xx:B6:AA', ip='192.168.2.249', name='yeelight-color-bulb-1'), 'xx:xx:xx:xx:56:F4': Device(mac='xx:xx:xx:xx:56:F4', ip='192.168.2.40', name='denon'), 'xx:xx:xx:xx:07:0D': Device(mac='xx:xx:xx:xx:07:0D', ip='192.168.2.3', name='fingbox'), 'xx:xx:xx:xx:B9:9E': Device(mac='xx:xx:xx:xx:B9:9E', ip='192.168.2.2', name='switch'), 'xx:xx:xx:xx:FE:C4': Device(mac='xx:xx:xx:xx:FE:C4', ip='192.168.2.60', name=None), 'xx:xx:xx:xx:E3:BD': Device(mac='xx:xx:xx:xx:E3:BD', ip='192.168.2.10', name='synology'), 'xx:xx:xx:xx:1E:FB': Device(mac='xx:xx:xx:xx:1E:FB', ip='192.168.2.50', name='playstation'), 'xx:xx:xx:xx:8F:78': Device(mac='xx:xx:xx:xx:8F:78', ip='192.168.2.30', name='stacjonarny'), 'xx:xx:xx:xx:AF:C6': Device(mac='xx:xx:xx:xx:AF:C6', ip='192.168.2.251', name='yeelight-color-v2-bulb'), 'xx:xx:xx:xx:77:56': Device(mac='xx:xx:xx:xx:77:56', ip='192.168.1.1', name=None), 'xx:xx:xx:xx:9B:3C': Device(mac='xx:xx:xx:xx:9B:3C', ip='192.168.2.20', name='raspberry')}

Devices xx:xx:xx:xx:FE:C4, xx:xx:xx:xx:0c:fa or xx:xx:xx:xx:20:26 are on the list from script but they are offline (physically disconnected from the network). This gives a false positive state of these devices in the Home Assistant. These devices have a static IP address from DHCP.

Python 3.7.2/aioasuswrt==1.1.21

Use /tmp/clientlist.json in async_get_connected_devices

Hi,

I just noticed that the function async_get_connected_devices shows disconnected devices as present, even if they're not. This is probably due to using the dnsmasq.leases file, which keeps the device record till the dns lease is expired.

I noticed there is a file /tmp/clientlist.json that basically shows the same information, but shows disconnected devices much quicker. In that file it also shows the clients separated by wifi "2G", "5G" and "wired_mac", which could also be used in async_get_wl to avoid the loops and multiple calls.

Is there any reason why that file has not been used for this cases?

From my tests, that file was kept updated even when no client was connected to the web admin of the router (Unless I missed out something).

Add small synchronous interface

To properly test this just via console/command line for different devices it would be nice if there would be just a small set of synchronous functions exposed in the __init__ that one can play with.

wrong data

Sporadically it happens that RX and TX Total is lower then from previous readout.

I do recommend to add in the function async def async_get_bytes_total(self, use_cache=True) in the asuswrt.py check for it to disregard corrupted updates.

image

Error on SSH connection

Hi, I've tested with an Asus AC87U with merlin firmware version 384.13_10.

  • This component worked sometime ago.
  • The error is: [Errno 104] Connection reset by peer
  • The code for the example:
    import asyncio
    import logging
    import sys
    from aioasuswrt.asuswrt import AsusWrt
    
    component = AsusWrt('192.168.1.1', 22, username='USER', password='PASS')
    logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
    logger = logging.getLogger(__name__)
    
    async def print_data():
        logger.debug(await component.connection.async_connect())  
    
    loop = asyncio.get_event_loop()
    loop.run_until_complete(print_data())
    loop.close()
  • Trace:
    DEBUG:asyncio:Using selector: EpollSelector
    Traceback (most recent call last):
      File "asus.py", line 18, in <module>
        loop.run_until_complete(print_data())
      File "/usr/local/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
        return future.result()
      File "asus.py", line 14, in print_data
        logger.debug(await component.connection.async_connect())
      File "/usr/local/lib/python3.7/site-packages/aioasuswrt/connection.py", line 75, in async_connect
        self._client = await asyncssh.connect(self._host, **kwargs)
      File "/usr/local/lib/python3.7/site-packages/asyncssh/connection.py", line 5696, in connect
        conn_factory, 'Opening SSH connection to')
      File "/usr/local/lib/python3.7/site-packages/asyncssh/connection.py", line 175, in _connect
        await conn.wait_established()
      File "/usr/local/lib/python3.7/site-packages/asyncssh/connection.py", line 1927, in wait_established
        await self._waiter
      File "/usr/local/lib/python3.7/asyncio/selector_events.py", line 814, in _read_ready__data_received
        data = self._sock.recv(self.max_size)
    ConnectionResetError: [Errno 104] Connection reset by peer
    

Thanks

await_get_nvram_info

Got sent here, with my issue, due to integration using this?!

I got the following in my log, on every boot of HA:

Logger: homeassistant.config_entries
Source: components/asuswrt/router.py:426
First occurred: 5. juni 2021, 19:01:03 (1 occurrences)
Last logged: 5. juni 2021, 19:01:03

Error setting up entry 192.168.0.1 for asuswrt
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/config_entries.py", line 293, in async_setup
result = await component.async_setup_entry(hass, self) # type: ignore
File "/usr/src/homeassistant/homeassistant/components/asuswrt/init.py", line 123, in async_setup_entry
await router.setup()
File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 230, in setup
model = await _get_nvram_info(self._api, "MODEL")
File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 426, in _get_nvram_info
info = await api.async_get_nvram(info_type)
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 275, in async_get_nvram
lines = await self.connection.async_run_command(_NVRAM_CMD)
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/connection.py", line 140, in async_run_command
return [line.decode("utf-8") for line in data]
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/connection.py", line 140, in
return [line.decode("utf-8") for line in data]
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbb in position 4: invalid start byte

Tell me if you need more then this log, and I will find.

The router is anyways a RT-N66W, and is not updated for the last months, and there isn't any available updates for it.

Anyway, this issue started with HA 2021.6.

ValueError exception on `async_get_rx` using telnet

Hi,

I've been using the asuswrt integration on homeassistant, but the logging has been overflowing with a ValueError exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 278, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 469, in async_device_update
    await self.async_update()  # type: ignore
  File "/usr/src/homeassistant/homeassistant/components/asuswrt/sensor.py", line 90, in async_update
    await super().async_update()
  File "/usr/src/homeassistant/homeassistant/components/asuswrt/sensor.py", line 68, in async_update
    self._rates = await self._api.async_get_bytes_total()
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 336, in async_get_bytes_total
    rx = await self.async_get_rx()
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 344, in async_get_rx
    return float(data[0]) if data[0] != '' else None
ValueError: could not convert string to float: '/net/eth2/statistics/rx_bytes\r'

The issue is present on the master version. I've been interfacing with an Asus RT-AC51U, firmware version '3.0.0.4.380_8591'. As this router does not support ssh (at least I cannot find it in the configuration) I've been interfacing with telnet which is supported.

I can reproduce the issue easily using this script:

#!/usr/bin/env python3
import asyncio
import logging

import sys

from aioasuswrt.asuswrt import AsusWrt

component = AsusWrt('192.168.2.1', 23, username='admin', password='....', interface='eth2', use_telnet=True)
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logger = logging.getLogger(__name__)


async def print_data():
    logger.debug("get_rx_stuff")
    logger.debug(await component.async_get_rx())


loop = asyncio.get_event_loop()

loop.run_until_complete(print_data())
loop.close()

The main issue is (as expected) in the async_run_command of the TelnetConnection class. I've added logging to the method to see what happens:

DEBUG:__main__:get_rx_stuff
The input is: (cat /sys/class/net/eth2/statistics/rx_bytes)
The send command is: (b'PATH=$PATH:/bin:/usr/sbin:/sbin && cat /sys/class/net/eth2/statistics/rx_bytes\n')
The data before splitting: b' PATH=$PATH:/bin:/usr/sbin:/sbin && cat /sys/class\r\r\n/net/eth2/statistics/rx_bytes\r\n81115610\r\nadmin@RT-AC51U:/tmp/home/root#'
The data after splitting: [b'/net/eth2/statistics/rx_bytes\r', b'81115610\r']
[b'/net/eth2/statistics/rx_bytes\r', b'81115610\r']

My expectation is that the main cause of problems is the \r\r\n (especially the \n) causing an extra unexpected split. My best guess is that this is added by someone due to a character limit of 50 per line (as it seems to happen exactly after 50 characters, if I counted correctly).

I've not had any inspiration on how to fix the split to give the correct output, especially as I'm unsure of the exact results of all the different functions calling this method.

For the rx (and probably tx) methods specifically this problem might be easily fixed in the calling method, eg. by replacing lines 344 and 350

return float(data[0]) if data[0] != '' else None

with

return float(data[-1]) if data[-1] != '' else None

Although I'm unsure whether this will cause problems for the ssh version.

asyncssh spamming log

I asked the question on the asyncssh github about this and Ron recommended adding

asyncssh.set_log_level('WARNING')

into the code.

I've inserted this into aioasuswrt.connection code and tried this on my installation at home and it's reduced the 'spamming' to just asuswrt checking devices text which is perfect.

Could this be included in the next release?

Thank you

Use rstats data for daily and monthly traffic

To obtain the data, the following command can be issued:

killall -USR2 rstats  # This asks rstats to create a JS file at `/var/spool/rstats-history.js`

Afterwards, the file at /var/spool/rstats-history.js can be read. Example contents:

daily_history = [
[0x790418,0x8f9bea0,0x90b8374],[0x790419,0x16c6f68,0x32d5ca9],[0x79041a,0x1435521,0x17f6c63],[0x79041b,0x8c97980,0xa1a4b10],[0x79041c,0x15c8771,0x150b02c],[0x79041d,0x3a6c971,0x7c0bf19],[0x79041e,0xd20a7c,0x861438],[0x79041f,0xf88093,0x1382069],[0x790501,0xc68ff6f,0xbabb5c5],[0x790502,0x1e0102b,0xfe4535],[0x790503,0x232246b,0x2a3a73b],[0x790504,0x1012b81c,0x103627bc],[0x790505,0xbf7317d,0xe576fdb],[0x790506,0x849a390,0x7b82ecc],[0x790507,0x91bb84b,0x879d320],[0x790508,0x91f9a53,0xcad3723],[0x790509,0xf4e0808,0x199dfe29],[0x79050a,0x5e40a39,0x5641d04]];

monthly_history = [
[0x790400,0x1b40d89d,0x22a23b79],[0x790500,0x5c3c2610,0x69bc8e0e]];

(The web interface deletes this file after reading it)

The data is in the format [date, rx, tx] where:

  • date is in 0xYYMMDD, where YY is years since 1900, MM is month starting from zero, and DD is the date of the month
    • Example: 0x790418 is 2021-05-24
  • rx is bytes rxed for the day in KB
  • tx is bytes txed for the day in KB

Alternative implementation

Instead, the statistics file at /var/lib/misc/rstats-history.gz can be read directly:

  1. Decompress the file
  2. Parse the raw bytes. They pretty much map to the above JavaScript almost exactly the same way (little endian), but the values are in bytes instead of kilobytes ( / 1024)

References

GPL_RT_AC1200GPlus_300438252272 / ... / release / src / router / rstats / rstats.c

On 4G-AC53U it still does not work (no wl command)

Most probably newest asus routers simply do not have a 'wl' command at all.
Even your 1.1.9 patch does not work (actually on this router it even breaks nvram, because on my router it is in /bin/nvram not /usr/sbin/nvram.

Another thing is that your script does not scan guest networks for clients (which might hand there).
So here is line for all these fixes:

for dev in nvram get wl1_vifs && nvram get wl0_vifs && nvram get wl_ifnames; do wlanconfig $dev list | awk 'FNR > 1 {print substr($1
, 0, 18)}'; done

device_tracker showing stale states

I have an AC-RT88U. Running HomeAssistant 0.82 (though I think this may have been happening from before). I perpetually see my devices as set to "home" state, even when they are disconnected. I just checked one device that's not connected, SSH'd to router, did 'ip neigh' and did not see it there.

I notice there is a flurry of activity today on this; is this a KI and is just waiting for a new HA release? Anything else I can do to be of help debugging?

Bitrates for eth0 do not reflect Internet traffic on Broadcom routers

Hello @kennedyshead ,

TL;DR: Do not expect to measure the Internet traffic when looking at eth0 of a Broadcom based Asuswrt device.

This is maybe more a clarification than a bug. I am using the ASUSWRT integration for Home Assistant and the bandwidth monitoring shows a strange behaviour when checking my gateway: Upload and download rates are all the time almost identical. Which is kind of weird, when you are downloading a file at say 200MBit/s and upload also show a rate of about 200MBit/s - which can't be, as my upload is limited to 30MBit/s.

So I started digging and checked the plugin, as well as aioasuswrt:

  • Readings are taken from the interface eth0 of the router, which is the interface connected to the Internet (WAN).
  • I am using an ASUS RT-AC66U (rev A) with the recent release of John's fork of Asuswrt-Merlin (374.43_44EAj9527).
  • OT: WiFi is disabled due to a bug in the Broadcom WiFi driver which leads to the router rebooting randomly every now and then. If this happens during a Skype meeting, it takes quite some time until the router is up again - which is very annoying. With WiFi disabled, the device is running rock-solid.

The strange behaviour is reproducable, also based on the low-level kernel statistics of the interface. But the traffic monitor feature of Asuswrt displays a reasonable graph for Internet traffic when doing a download (download rate >> upload rate). So I checked how the traffic monitor gets its numbers.

Basically it is similar to the implementation in aioasuswrt: read the total of bytes every 'x' seconds and divide the difference by 'x', but with a twist for Broadcom based routers: when doing the delta, first a difference is computed like eth0 minus vlan1 (for both TX and RX bytes).
See the function netdev_calc() in release/src/router/shared/misc.c - search for // special handle for non-tag wan of broadcom solution.

The implementation looks like this: If in NVRAM switch_wantag is set to none (and there is an interface vlan1 - see bcmvlan_models(model, modelvlan)), the special handling is activated. eth0 will become the WIRED connection, while the difference will become the INTERNET connection.

You can see the network traffic information the Traffic Monitor page gets by e.g. using the developer tools of Firefox. Look for calls to update.cgi and check the returned JSON data:

netdev = {
 'WIRED':{rx:0x694fd5a0,tx:0x38930af4}
,'INTERNET':{rx:0x5f4b4b20,tx:0x156603d5}
,'BRIDGE':{rx:0x5712764,tx:0x6545be3c}
,'WIRELESS0':{rx:0x0,tx:0x0}
,'WIRELESS1':{rx:0x0,tx:0x0}
}

So the bottom line is: if you want to measure your Internet throughput, you need to use figures from INTERNET, not WIRED (eth0). //

Unfortunately this metric is not available via aioasuswrt, as you can only give an existing interface for monitoring. A new approach would be needed. I quickly whipped up a short script to illustrate the solution (which produces sensible values for me):

#!/usr/bin/env python3

import asyncio
import logging
import re

import sys

from aioasuswrt.asuswrt import AsusWrt
from aioasuswrt.helpers import convert_size

component = AsusWrt("gateway", 22, username='admin', ssh_key='~/.ssh/gateway_rsa')
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
logger = logging.getLogger(__name__)

async def print_data():
    # sampling interval
    dtime = 5

    prevrx = None
    prevtx = None
    while True:
        eth0rx = eth0tx = 0
        vlanrx = vlantx = 0

        # based on the built-in Traffic Monitor code of AsusWrt
        # see - ej_netdev() in release/src/router/httpd/web.c
        #     - netdev_calc() in release/src/router/shared/misc.c
        #       search for '// special handle for non-tag wan of broadcom solution'

        # BONUS: gets a *consistent* snapshot of the transferred bytes across all interfaces
        netdev = await component.connection.async_run_command("cat /proc/net/dev")

        # skip the first two header lines, process each interface
        for line in netdev[2:]:
            parts = re.split('[\s:]+', line.strip())
            # NOTES:
            #  * assuming eth0 always comes before vlan1 in dev file
            #  * counted bytes wrap around at 0xFFFFFFFF
            if (parts[0] == "eth0"):
                eth0rx = int(parts[1]) # received bytes
                eth0tx = int(parts[9]) # transmitted bytes
            elif (parts[0] == "vlan1"):
                vlanrx = int(parts[1]) # received bytes
                vlantx = int(parts[9]) # transmitted bytes

        def handle32bitwrap(v):
            return v if v > 0 else v + 0xFFFFFFFF

        # the true amount of Internet related data equals eth0 - vlan1
        inetrx = handle32bitwrap(eth0rx - vlanrx)
        inettx = handle32bitwrap(eth0tx - vlantx)

        if prevrx is None or prevtx is None:
            rx = tx = 0
        else:
            rx = int(handle32bitwrap(inetrx - prevrx)/dtime)
            tx = int(handle32bitwrap(inettx - prevtx)/dtime)

        prevrx = inetrx
        prevtx = inettx

        logger.debug("DL: {}/s UL: {}/s".format(convert_size(rx), convert_size(tx)))

        await asyncio.sleep(dtime)

loop = asyncio.get_event_loop()

loop.run_until_complete(print_data())
loop.close()

Hope this helps if anybody comes across this phenomenon. Perhaps it would be great to have some kind of virtual interface like inet which could be passed to aioasuswrt which would trigger the special handling on readout?

Anyway, thanks for your work & Cheers,
tempura

stops working with "took longer than the scheduled"

Updating device list from asuswrt took longer than the scheduled scan interval 0:00:12
Need to restart Home Assistant for it to start working again.

I've enabled logs now and I'll let you know the outcome.
On the previous version (old non-async code on Home Assistant) I had to disconnect and reconnect the session when this happened, guess it still happens the same and the plugin doesn't figure out it lost the connection to the router

Full paths to binaries

I own a RT-AC68P. After a recent firmware upgrade I noticed the shell environment had changed and many of the commands were failing because it could not find them in the path. I modified my local version to use the full path name for the commands and this fixed the issue. If you want, I can do a PR to fix them in the master branch or you can fix them on the next release. It doesn't hurt to have the full path names (hopefully they are the same on most Asus routers) and hopefully will prevent other people from having the same issue when they update their router firmware.

Not really need all those stats. Just device tracker.

Recent changes force stat collection from asuswrt a mandatory .
I really have no use for the all those stats, I am just in for the device tracker.
Is there any way to avoid all those data collections?

It's a burden for the router. It produces tons of [asyncssh] logs. I am forced to disable Asuswrt components for the time being.

Closing telnet session when done

Question from a noob in this area. From what I understand Home Assistant uses aioasuswrt to pull data from asus devices. I have a RT-N66U where I use telnet to pull data from router.
The problem I have now is the router end up with ~400 telnet connections after a while and stops wotking.

Feb 17 20:00:37 disk_monitor: Got SIGALRM... 
Feb 17 20:11:49 kernel: SKIPPED false Type 6 Radar Detection. min_pw=24 pw_delta=0 pri=60119 fm_min=0 fm_max=0 nconsecq_pulses=1. Time from last detection = 1894, = 31min 34sec. Detected pulse index: 4 
Feb 17 20:28:44 telnetd[332]: vfork: Cannot allocate memory 
Feb 17 20:29:05 telnetd[332]: vfork: Cannot allocate memory

From router:
N66U:/tmp# netstat -t| grep telnet|wc -l with a result of 386.

I do have an option in the router gui to "close telnet sessions with a value between 10-99" turning that on will do some hourekeeping and everythings works again.

So my question is, where and who will close the session?

Cheers
Fredrik

Error doing job: Task exception was never retrieved

Error visible in logs (multiple instances). I have not notice impact on "end user".

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 252, in update_all
    await self.update_devices()
  File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 259, in update_devices
    wrt_devices = await self._api.async_get_connected_devices()
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 353, in async_get_connected_devices
    dev = await self.async_get_arp()
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 325, in async_get_arp
    lines = await self.connection.async_run_command(_ARP_CMD)
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/connection.py", line 34, in async_run_command
    await self.async_connect()
  File "/usr/local/lib/python3.8/site-packages/aioasuswrt/connection.py", line 77, in async_connect
    self._client = await asyncssh.connect(self._host, **kwargs)
  File "/usr/local/lib/python3.8/site-packages/asyncssh/connection.py", line 6460, in connect
    return await _connect(options.host, options.port, loop, options.tunnel,
  File "/usr/local/lib/python3.8/site-packages/asyncssh/connection.py", line 223, in _connect
    await conn.wait_established()
  File "/usr/local/lib/python3.8/site-packages/asyncssh/connection.py", line 2107, in wait_established
    await self._waiter
asyncssh.misc.ConnectionLost: Connection lost

2021-04-08 11:08:17 ERROR (MainThread) [aioasuswrt.connection] Host timeout.
2021-04-08 11:08:17 ERROR (MainThread) [homeassistant.components.asuswrt.router] Unexpected error fetching sensors_bytes data: list index out of range
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 173, in _async_refresh
self.data = await self._async_update_data()
File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 143, in _async_update_data
return await self.update_method()
File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 81, in _get_bytes
datas = await self._api.async_get_bytes_total()
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 380, in async_get_bytes_total
rx = await self.async_get_rx()
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 389, in async_get_rx
return float(data[0]) if data[0] != "" else None
IndexError: list index out of range

Index out of range error in async_get_rx

I'm getting the following error occasionally on my router. I'm guessing that data is occasionally coming back as completely empty in some form, but since I'm not sure what is triggering that response it's difficult to test.

Maybe worth adding ahead of the existing return:

if not data return None

2020-11-30 23:54:58 ERROR (MainThread) [homeassistant.helpers.entity] Update for sensor.asuswrt_upload_speed fails
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 278, in async_update_ha_state
await self.async_device_update()
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 482, in async_device_update
await task
File "/usr/src/homeassistant/homeassistant/components/asuswrt/sensor.py", line 136, in async_update
await super().async_update()
File "/usr/src/homeassistant/homeassistant/components/asuswrt/sensor.py", line 69, in async_update
self._speed = await self._api.async_get_current_transfer_rates()
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 401, in async_get_current_transfer_rates
data = await self.async_get_bytes_total(use_cache)
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 380, in async_get_bytes_total
rx = await self.async_get_rx()
File "/usr/local/lib/python3.8/site-packages/aioasuswrt/asuswrt.py", line 389, in async_get_rx
return float(data[0]) if data[0] != "" else None
IndexError: list index out of range

Library leaks SSH connections as is not Coroutine-Safe

Issue discovered when debugging home-assistant/core#103230 and should have been solved by #68 long time ago

aioasuswrt does not always close SSH connections, making remote system solely responsible for freeing up resources, which is a bad assumption, especially on AsusWRT routers, where "Idle Timeout" setting for SSH server applies only to interactive sessions, not to SSH connections with all channels closed (dropbear is always started without -I so it never times out). This behaviour quite often makes high-end routers with 1GB of memory crash in less than a week.

Points to solve:

  1. SshConnection.async_connect() should check if a connection exists before creating a new one, so it can be closed if needed; this code may be called when a connection object exists, but some error was handled and reconnect is needed

  2. entire SshConnection.async_connect() should be guarded by some form of lock, for example asyncio.Lock() so it's Coroutine-Safe; otherwise bad timing of await can create and overwrite multiple connections we no longer have access to, yet they still consume resources on a server

Could not parse row

018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=70] Requesting new SSH session
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=70]   Command: arp -n
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=70] Received exit status 0
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=70] Received channel close
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=70] Channel closed
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row: ? (172.16.10.142) at 00:18:DD:04:E2:FA [ether]  on br0
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row: ? (172.16.10.1) at 00:08:A2:0D:54:B8 [ether]  on br0
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row: ? (172.16.10.125) at 60:01:94:41:C4:21 [ether]  on br0
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row: ? (172.16.10.61) at 00:09:B0:A1:51:3C [ether]  on br0
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row: ? (172.16.10.2) at 00:25:90:12:2D:90 [ether]  on br0
2018-11-11 15:27:09 DEBUG (MainThread) [aioasuswrt.asuswrt] Could not parse row:
2018-11-11 15:27:09 DEBUG (MainThread) [asyncssh] [conn=0, chan=71] Set write buffer limits: low-water=16384, high-water=65536
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=71] Requesting new SSH session
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=71]   Command: ip neigh
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=71] Received exit status 0
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=71] Received channel close
2018-11-11 15:27:09 INFO (MainThread) [asyncssh] [conn=0, chan=71] Channel closed

I tried adding the row to the ARP_DATA tests, but its not failing, so I'm confused whats going on.

This is Home Assistant 0.82.0 which should have the new version in it.

Connected devices doesn't make sense

Hi

Thanks for providing this library , used by the Home assistant asuswrt integration.
I have several ASUS RTN-66u's devices configured as AP's.
The firmware on them is a Merlin LTS fork (based on the Merlin 374 version where power settings where still unlocked).
Although the integration can connect the AP's, the information provided by this library doesn't make any sense.

  • The connected devices number is way less than the devices present according my router. But more then the devices connected with WiFi of the AP.
  • The list of devices (used to create device trackers) isn't the WiFi list either. Several wired devices on the LAN are included for example.

I would like to see these figures based on the list of devices connected via the WiFi (when in AP mode).

Best Eric

Code assumes WAN is eth0

I have the ASUS RT-N56U router with Padavan's firmware. The firmware uses the network intervace name "eth3" for WAN.

This is a problem because aioasuswrt assumes that WAN will be "eth0" to obtain upload and download bandwidth statistics. For example:
cat /sys/class/net/eth0/statistics/rx_bytes

Could you please consider adding a config variable so that the interface name can be changed? The variable could be passed in from Home Assistant. For example:

asuswrt:
  ...
  interface: "eth3"

Add python 3.8 support

description

When adding python 3.8 to the test workflow it does not pass, there is an error when asserting so afaik there is at this moment no support for python 3.8

1.1.6 returns error codes on RT-AC53

using the testscript from #1 with python3 I get no results. The commands fail.

DEBUG:asyncio:Using selector: EpollSelector
DEBUG:__main__:wl
INFO:asyncssh:Opening SSH connection to 192.168.1.3, port 22
INFO:asyncssh:[conn=0] Connection to 192.168.1.3, port 22 succeeded
INFO:asyncssh:[conn=0]   Local address: 192.168.1.11, port 41448
DEBUG:asyncssh:[conn=0] Requesting key exchange
DEBUG:asyncssh:[conn=0] Received key exchange request
DEBUG:asyncssh:[conn=0] Beginning key exchange
DEBUG:asyncssh:[conn=0] Completed key exchange
INFO:asyncssh:[conn=0] Beginning auth for user admin
DEBUG:asyncssh:[conn=0] Trying password auth
INFO:asyncssh:[conn=0] Auth for user admin succeeded
DEBUG:asyncssh:[conn=0, chan=0] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=0] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=0]   Command: for dev in `nvram get wl_ifnames`; do wl -i $dev assoclist; done
INFO:asyncssh:[conn=0, chan=0] Received exit status 127
INFO:asyncssh:[conn=0, chan=0] Received channel close
INFO:asyncssh:[conn=0, chan=0] Channel closed
DEBUG:__main__:['']
DEBUG:asyncssh:[conn=0, chan=1] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=1] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=1]   Command: for dev in `nvram get wl_ifnames`; do wl -i $dev assoclist; done
INFO:asyncssh:[conn=0, chan=1] Received exit status 127
INFO:asyncssh:[conn=0, chan=1] Received channel close
INFO:asyncssh:[conn=0, chan=1] Channel closed
DEBUG:__main__:{}
DEBUG:__main__:arp
DEBUG:asyncssh:[conn=0, chan=2] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=2] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=2]   Command: arp -n
INFO:asyncssh:[conn=0, chan=2] Received exit status 127
INFO:asyncssh:[conn=0, chan=2] Received channel close
INFO:asyncssh:[conn=0, chan=2] Channel closed
DEBUG:__main__:['']
DEBUG:asyncssh:[conn=0, chan=3] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=3] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=3]   Command: arp -n
INFO:asyncssh:[conn=0, chan=3] Received exit status 127
INFO:asyncssh:[conn=0, chan=3] Received channel close
INFO:asyncssh:[conn=0, chan=3] Channel closed
DEBUG:__main__:{}
DEBUG:__main__:neigh
DEBUG:asyncssh:[conn=0, chan=4] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=4] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=4]   Command: ip neigh
INFO:asyncssh:[conn=0, chan=4] Received exit status 127
INFO:asyncssh:[conn=0, chan=4] Received channel close
INFO:asyncssh:[conn=0, chan=4] Channel closed
DEBUG:__main__:['']
DEBUG:asyncssh:[conn=0, chan=5] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=5] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=5]   Command: ip neigh
INFO:asyncssh:[conn=0, chan=5] Received exit status 127
INFO:asyncssh:[conn=0, chan=5] Received channel close
INFO:asyncssh:[conn=0, chan=5] Channel closed
DEBUG:__main__:{}
DEBUG:__main__:leases
DEBUG:asyncssh:[conn=0, chan=6] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=6] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=6]   Command: cat /var/lib/misc/dnsmasq.leases
INFO:asyncssh:[conn=0, chan=6] Received exit status 1
INFO:asyncssh:[conn=0, chan=6] Received channel close
INFO:asyncssh:[conn=0, chan=6] Channel closed
DEBUG:__main__:['']
DEBUG:asyncssh:[conn=0, chan=7] Set write buffer limits: low-water=16384, high-water=65536
INFO:asyncssh:[conn=0, chan=7] Requesting new SSH session
INFO:asyncssh:[conn=0, chan=7]   Command: cat /var/lib/misc/dnsmasq.leases
INFO:asyncssh:[conn=0, chan=7] Received exit status 1
INFO:asyncssh:[conn=0, chan=7] Received channel close
INFO:asyncssh:[conn=0, chan=7] Channel closed
DEBUG:__main__:{}

Output for the single commands:

admin@(none):/tmp/home/root# for dev in `nvram get wl_ifnames`; do wl -i $dev assoclist; done
-sh: wl: not found
-sh: wl: not found
admin@(none):/tmp/home/root# dev in `nvram get wl_ifnames`; do wl -i $dev assoclist; done
-sh: dev: not found
-sh: wl: not found
admin@(none):/tmp/home/root# arp -n
? (192.168.1.1) at 84:16:xx:xx:xx:xx [ether]  on br0
? (192.168.1.11) at 30:5a:xx:xx:xx:xx [ether]  on br0
? (192.168.1.4) at b8:27:xx:xx:xx:xx [ether]  on br0
admin@(none):/tmp/home/root# ip neigh
192.168.1.11 dev br0 lladdr 30:5a:xx:xx:xx:xx REACHABLE
192.168.1.4 dev br0 lladdr b8:27:xx:xx:xx:xx REACHABLE
admin@(none):/tmp/home/root# cat /var/lib/misc/dnsmasq.leases
cat: can't open '/var/lib/misc/dnsmasq.leases': No such file or directory

The test script somehow doesn't work while the commands do.

ERROR: Unable to complete integration setup: Passphrase must be specified to import encrypted private keys

Trying to setup the ASUSWRT integration using SSH to authenticate, I am running into the below error:

`Logger: homeassistant.components.asuswrt.config_flow
Source: components/asuswrt/config_flow.py:155
Integration: ASUSWRT (documentation, issues)
First occurred: 7:30:30 PM (4 occurrences)
Last logged: 8:09:00 PM

Unknown error connecting with AsusWrt router at 192.168.50.1
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/components/asuswrt/config_flow.py", line 155, in _async_check_connection
await api.connection.async_connect()
File "/usr/local/lib/python3.10/site-packages/aioasuswrt/connection.py", line 78, in async_connect
self._client = await asyncssh.connect(self._host, **kwargs)
File "/usr/local/lib/python3.10/site-packages/asyncssh/connection.py", line 8037, in connect
new_options = cast(SSHClientConnectionOptions, await _run_in_executor(
File "/usr/local/lib/python3.10/site-packages/asyncssh/connection.py", line 515, in _run_in_executor
return await loop.run_in_executor(
File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run
result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.10/site-packages/asyncssh/connection.py", line 6423, in init
super().init(options=options, last_config=last_config, **kwargs)
File "/usr/local/lib/python3.10/site-packages/asyncssh/misc.py", line 350, in init
self.prepare(**self.kwargs)
File "/usr/local/lib/python3.10/site-packages/asyncssh/connection.py", line 7282, in prepare
load_keypairs(cast(KeyPairListArg, client_keys), passphrase,
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 3470, in load_keypairs
read_private_key_and_certs(key_to_load, passphrase)
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 3284, in read_private_key_and_certs
key, cert = import_private_key_and_certs(read_file(filename), passphrase)
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 3157, in import_private_key_and_certs
key, end = _decode_private(data, passphrase)
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 2761, in _decode_private
key = _decode_pem_private(pem_name, headers, data, passphrase)
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 2672, in _decode_pem_private
return _decode_openssh_private(data, passphrase)
File "/usr/local/lib/python3.10/site-packages/asyncssh/public_key.py", line 2509, in _decode_openssh_private
raise KeyImportError('Passphrase must be specified to import '
asyncssh.public_key.KeyImportError: Passphrase must be specified to import encrypted private keys`

Note that the same SSH connection is working fine when connecting from my macOs terminal - SSH config as below

Host router
HostName 192.168.50.1
User admin
Port 1025
IdentityFile ~/.ssh/id_rsa

Settings I am trying on ASUSWRT integration wizard:
Screenshot 2023-05-09 at 20 08 58

`TypeError` in `async_get_current_transfer_rates` method

Sometimes I get this error:

2022-11-03 08:09:15.693 ERROR (MainThread) [homeassistant.components.asuswrt.router] Unexpected error fetching sensors_rates data: '<' not supported between instances of 'NoneType' and 'float'
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 205, in _async_refresh
self.data = await self._async_update_data()
File "/usr/src/homeassistant/homeassistant/helpers/update_coordinator.py", line 164, in _async_update_data
return await self.update_method()
File "/usr/src/homeassistant/homeassistant/components/asuswrt/router.py", line 105, in _get_rates
rates = await self._api.async_get_current_transfer_rates()
File "/usr/local/lib/python3.10/site-packages/aioasuswrt/asuswrt.py", line 491, in async_get_current_transfer_rates
if data[0] < self._rx_latest:
TypeError: '<' not supported between instances of 'NoneType' and 'float'

aioasuswrt==1.4.0
device: RT-AC86U with Merlin FW 386.7_2

Running without root privileges - how to set up

Hi, This suggestion may be a bit off-topic but just wanted to share with out and ask what you think.

Background:
On my earlier Asus WRT I had Asuswrt-Merlin. That included busybox which supported adding new Linux users to WRT. This way I was able to make user which did not have root privileges. I used that user for aioasuswrt. This way no need to store root password in the system where I run aioasuswrt.

Idea:
Since the router got broken and I purchased new one. I would like to keep the stock FW in there. I'm wondering if it would be possible to add user using commands in stock FW just by editing files, /etc/password etc. to create another user with limited privileges which could be used for aioasuswrt.

Request:
If you think the idea is feasible and you know how to do it, could you provide instructions how to add new user with limited privileges.

Thanks

New release

With #61 merged it would be nice to get a new release.

Thanks.

Asuswrt could not work correct with HA 108.9

The problem

Environment

  • Home Assistant Core release with the issue: asuswrt
  • Last working Home Assistant Core release (if known): 107.3
  • Operating environment (Home Assistant/Supervised/Docker/venv): Docker
  • Integration causing this issue: no
  • Link to integration documentation on our website:

Problem-relevant configuration.yaml

asuswrt:
  host: 192.168.1.1
  username: admin
  ssh_key: /config/ssh/asuswrt-rsa-key
  protocol: ssh
  port: 22
  interface: br0
  sensors:
    - upload
    - download
    - upload_speed
    - download_speed

Traceback/Error logs

Logger: homeassistant.setup
Source: components/asuswrt/__init__.py:81
First occurred: 下午9:06:48 (1 occurrences)
Last logged: 下午9:06:48

Error during setup of component asuswrt
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/setup.py", line 171, in _async_setup_component
    hass, processed_config
  File "/usr/src/homeassistant/homeassistant/components/asuswrt/__init__.py", line 81, in async_setup
    dnsmasq=conf[CONF_DNSMASQ],
TypeError: __init__() got an unexpected keyword argument 'interface'

Additional information

That's it
PLZ help me ..... thx!!!

make new release

With #6 I'd like a new release rolled out so it can be bumped in home assistant. (Maybe even one more pr for hacktober)

Lemme know if you want help configuring or automating releases.

New release

Is there a specified release cycle, or a plan for creating a new release? I'm waiting for the fixes of #52 to be included in the home assistant installation. (So both a new release, and an update of the core/home-assistant repo would be necessary).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.