n8henrie / fauxmo

Emulated Belkin WeMo devices that work with the Amazon Echo
https://n8henrie.com/2016/02/fauxmo-home-automation-with-the-amazon-echo-raspberry-pi-and-homeassistant/
Other
376 stars 78 forks source link

Just asking for a little help.. #117

Closed strunker closed 1 year ago

strunker commented 1 year ago

My Issue

I cant seem to get the devices to properly discover on the echo device.

WHYT

I have tried using the below config.json and fauxmo start properly, runs on the port I chose, etc. I ensured that port 12340 is open in the firewall inbound and outbound. My understanding is that the echo devices will send get request to fauxmo for the config setup.xml once its read the echo device should send a post back to fauxmo and the switch is then added. I never seem to get anything back from the echo device. I have tried this on different machines here, one of which has the windows firewall completely turned off and I still get no post back. No one else seems to be having these types of problems so it ha to be something I am either doing wrong, or a setting some where on my network or my devices.

Just looking for a little guidance if anyone has any to offer. Thank you.

{
    "FAUXMO": {
        "ip_address": "auto"
    },
    "PLUGINS": {
        "SimpleHTTPPlugin": {
            "DEVICES": [
                {
                    "port": 12340,
                    "on_cmd": "http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/On",
                    "off_cmd": "http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/Off",
                    "on_data": {"isOn": 1},
                    "off_data": {"isOn": 0},
                    "user": "this",
                    "password": "that",
                    "method": "POST",
                    "name": "fake Indigo switch",
                    "use_fake_state": true
                }
            ]
        }
    }
}
`2022-12-31 14:19:39 fauxmo:42       INFO     Fauxmo v0.6.0
2022-12-31 14:19:39 fauxmo:43       DEBUG    3.8.10 (tags/v3.8.10:3d8993a, May  3 2021, 11:48:03) [MSC v.1928 64 bit (AMD64)]
2022-12-31 14:19:39 fauxmo:26       DEBUG    Attempting to get IP address automatically
2022-12-31 14:19:39 fauxmo:41       DEBUG    Using IP address: 10.1.1.10
2022-12-31 14:19:39 fauxmo:112      DEBUG    plugin_vars: {}
2022-12-31 14:19:39 fauxmo:118      DEBUG    device config: {'port': 12340, 'on_cmd': 'http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/On', 'off_cmd': 'http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/Off', 'on_data': {'isOn': 1}, 'off_data': {'isOn': 0}, 'user': 'this', 'password': 'that', 'method': 'POST', 'name': 'fake Indigo switch', 'use_fake_state': True}
2022-12-31 14:19:39 asyncio:1490     INFO     <Server sockets=(<asyncio.TransportSocket fd=176, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.1.1.10', 12340)>,)> is serving
2022-12-31 14:19:39 fauxmo:133      DEBUG    Started fauxmo device: {'name': 'fake Indigo switch', 'plugin': SimpleHTTPPlugin(method='POST', state_method='GET', headers={}, on_cmd='http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/On', off_cmd='http://10.1.1.10:60700/AuthMeVirtualSwitch/VirtualSwitch1/Off', state_cmd=None, on_data=b'isOn=1', off_data=b'isOn=0', state_data=None, state_response_on=None, state_response_off=None, urlopen=<bound method OpenerDirector.open of <urllib.request.OpenerDirector object at 0x0000021B26EA3850>>, use_fake_state=True, _name='fake Indigo switch', _port=12340, _latest_action='off')}
2022-12-31 14:19:39 fauxmo:135      INFO     Starting UDP server
2022-12-31 14:19:39 asyncio:1344     DEBUG    Datagram endpoint remote_addr=None created: (<_ProactorDatagramTransport fd=616>, <fauxmo.protocols.SSDPServer object at 0x0000021B26EA3340>)
2022-12-31 14:19:43 fauxmo:344      DEBUG    Received data below from ('10.1.1.10', 50055):
2022-12-31 14:19:45 fauxmo:345      DEBUG    M-SEARCH * HTTP/1.1
MX: 1
ST: upnp:rootdevice
MAN: "ssdp:discover"
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Host: 239.255.255.250:1900
Connection: close

2022-12-31 14:19:45 asyncio:1854     WARNING  Executing <Handle _ProactorDatagramTransport._loop_reading(<_OverlappedF...events.py:508>) created at C:\Python38\lib\asyncio\windows_events.py:87> took 2.078 seconds
2022-12-31 14:19:45 fauxmo:344      DEBUG    Received data below from ('10.1.1.10', 50055):
2022-12-31 14:19:45 fauxmo:345      DEBUG    M-SEARCH * HTTP/1.1
MX: 1
ST: upnp:rootdevice
MAN: "ssdp:discover"
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Host: 239.255.255.250:1900
Connection: close

2022-12-31 14:19:45 fauxmo:420      DEBUG    Sending response to ('10.1.1.10', 50055) with mx 1.0:
b'HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=86400\r\nDATE: Sat, 31 Dec 2022 19:19:45 GMT\r\nEXT:\r\nLOCATION: http://10.1.1.10:12340/setup.xml\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 7e047630-5bb9-4e1c-bde8-93315bb88fb7\r\nSERVER: Fauxmo, UPnP/1.0, Unspecified\r\nST: upnp:rootdevice\r\nUSN: uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c::upnp:rootdevice\r\n\r\n'
2022-12-31 14:19:45 fauxmo:420      DEBUG    Sending response to ('10.1.1.10', 50055) with mx 1.0:
b'HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=86400\r\nDATE: Sat, 31 Dec 2022 19:19:45 GMT\r\nEXT:\r\nLOCATION: http://10.1.1.10:12340/setup.xml\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 9ee261d6-ed32-4448-87ac-5ce9821da427\r\nSERVER: Fauxmo, UPnP/1.0, Unspecified\r\nST: upnp:rootdevice\r\nUSN: uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c::upnp:rootdevice\r\n\r\n'
2022-12-31 14:19:46 asyncio:820      DEBUG    <Server sockets=(<asyncio.TransportSocket fd=176, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.1.1.10', 12340)>,)> got a new connection from ('10.1.1.10', 47183): <socket.socket fd=580, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.1.1.10', 12340), raddr=('10.1.1.10', 47183)>
2022-12-31 14:19:46 fauxmo:43       DEBUG    Connection made with: ('10.1.1.10', 47183)
2022-12-31 14:19:46 fauxmo:55       DEBUG    Received message:
GET /setup.xml HTTP/1.1
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Host: 10.1.1.10:12340

2022-12-31 14:19:46 fauxmo:57       INFO     setup.xml requested by Echo
2022-12-31 14:19:46 fauxmo:103      DEBUG    Fauxmo response to setup request:
HTTP/1.1 200 OK
CONTENT-LENGTH: 958
CONTENT-TYPE: text/xml
DATE: Sat, 31 Dec 2022 19:19:46 GMT
LAST-MODIFIED: Sat, 01 Jan 2000 00:01:15 GMT
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: Fauxmo
CONNECTION: close

<?xml version="1.0"?><root><specVersion><major>1</major><minor>0</minor></specVersion><device><deviceType>urn:Belkin:device:controllee:1</deviceType><friendlyName>fake Indigo switch</friendlyName><manufacturer>Belkin International Inc.</manufacturer><modelName>Emulated Socket</modelName><modelNumber>3.1415</modelNumber><UDN>uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c</UDN><serviceList><service><serviceType>urn:Belkin:service:basicevent:1</serviceType><serviceId>urn:Belkin:serviceId:basicevent1</serviceId><controlURL>/upnp/control/basicevent1</controlURL><eventSubURL>/upnp/event/basicevent1</eventSubURL><SCPDURL>/eventservice.xml</SCPDURL></service><service><serviceType>urn:Belkin:service:metainfo:1</serviceType><serviceId>urn:Belkin:serviceId:metainfo1</serviceId><controlURL>/upnp/control/metainfo1</controlURL><eventSubURL>/upnp/event/metainfo1</eventSubURL><SCPDURL>/metainfoservice.xml</SCPDURL></service></serviceList></device></root>
2022-12-31 14:20:17 fauxmo:344      DEBUG    Received data below from ('127.0.0.1', 4963):
2022-12-31 14:20:17 fauxmo:345      DEBUG    M-SEARCH * HTTP/1.1
MX: 5
ST: upnp:rootdevice
MAN: "ssdp:discover"
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Connection: close
Host: 239.255.255.250:1900

2022-12-31 14:20:17 fauxmo:344      DEBUG    Received data below from ('127.0.0.1', 4963):
2022-12-31 14:20:17 fauxmo:345      DEBUG    M-SEARCH * HTTP/1.1
MX: 5
ST: upnp:rootdevice
MAN: "ssdp:discover"
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Connection: close
Host: 239.255.255.250:1900

2022-12-31 14:20:17 fauxmo:420      DEBUG    Sending response to ('127.0.0.1', 4963) with mx 5.0:
b'HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=86400\r\nDATE: Sat, 31 Dec 2022 19:20:17 GMT\r\nEXT:\r\nLOCATION: http://10.1.1.10:12340/setup.xml\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 65cf4e48-b96e-46f2-9441-eee82af5b0fa\r\nSERVER: Fauxmo, UPnP/1.0, Unspecified\r\nST: upnp:rootdevice\r\nUSN: uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c::upnp:rootdevice\r\n\r\n'
2022-12-31 14:20:17 fauxmo:420      DEBUG    Sending response to ('127.0.0.1', 4963) with mx 5.0:
b'HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=86400\r\nDATE: Sat, 31 Dec 2022 19:20:17 GMT\r\nEXT:\r\nLOCATION: http://10.1.1.10:12340/setup.xml\r\nOPT: "http://schemas.upnp.org/upnp/1/0/"; ns=01\r\n01-NLS: 89a0e4c2-9184-494e-ab1f-ad67b8aac5b0\r\nSERVER: Fauxmo, UPnP/1.0, Unspecified\r\nST: upnp:rootdevice\r\nUSN: uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c::upnp:rootdevice\r\n\r\n'
2022-12-31 14:20:17 asyncio:820      DEBUG    <Server sockets=(<asyncio.TransportSocket fd=176, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.1.1.10', 12340)>,)> got a new connection from ('10.1.1.10', 47373): <socket.socket fd=676, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.1.1.10', 12340), raddr=('10.1.1.10', 47373)>
2022-12-31 14:20:18 fauxmo:43       DEBUG    Connection made with: ('10.1.1.10', 47373)
2022-12-31 14:20:18 fauxmo:55       DEBUG    Received message:
GET /setup.xml HTTP/1.1
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Host: 10.1.1.10:12340

2022-12-31 14:20:18 fauxmo:57       INFO     setup.xml requested by Echo
2022-12-31 14:20:18 fauxmo:103      DEBUG    Fauxmo response to setup request:
HTTP/1.1 200 OK
CONTENT-LENGTH: 958
CONTENT-TYPE: text/xml
DATE: Sat, 31 Dec 2022 19:20:18 GMT
LAST-MODIFIED: Sat, 01 Jan 2000 00:01:15 GMT
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: Fauxmo
CONNECTION: close

<?xml version="1.0"?><root><specVersion><major>1</major><minor>0</minor></specVersion><device><deviceType>urn:Belkin:device:controllee:1</deviceType><friendlyName>fake Indigo switch</friendlyName><manufacturer>Belkin International Inc.</manufacturer><modelName>Emulated Socket</modelName><modelNumber>3.1415</modelNumber><UDN>uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c</UDN><serviceList><service><serviceType>urn:Belkin:service:basicevent:1</serviceType><serviceId>urn:Belkin:serviceId:basicevent1</serviceId><controlURL>/upnp/control/basicevent1</controlURL><eventSubURL>/upnp/event/basicevent1</eventSubURL><SCPDURL>/eventservice.xml</SCPDURL></service><service><serviceType>urn:Belkin:service:metainfo:1</serviceType><serviceId>urn:Belkin:serviceId:metainfo1</serviceId><controlURL>/upnp/control/metainfo1</controlURL><eventSubURL>/upnp/event/metainfo1</eventSubURL><SCPDURL>/metainfoservice.xml</SCPDURL></service></serviceList></device></root>
2022-12-31 14:20:20 asyncio:820      DEBUG    <Server sockets=(<asyncio.TransportSocket fd=176, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.1.1.10', 12340)>,)> got a new connection from ('10.1.1.10', 47376): <socket.socket fd=532, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.1.1.10', 12340), raddr=('10.1.1.10', 47376)>
2022-12-31 14:20:20 fauxmo:43       DEBUG    Connection made with: ('10.1.1.10', 47376)
2022-12-31 14:20:20 fauxmo:55       DEBUG    Received message:
GET /setup.xml HTTP/1.1
User-Agent: UPnP/1.0 DLNADOC/1.50 Platinum/1.0.5.13
Host: 10.1.1.10:12340

2022-12-31 14:20:20 fauxmo:57       INFO     setup.xml requested by Echo
2022-12-31 14:20:20 fauxmo:103      DEBUG    Fauxmo response to setup request:
HTTP/1.1 200 OK
CONTENT-LENGTH: 958
CONTENT-TYPE: text/xml
DATE: Sat, 31 Dec 2022 19:20:20 GMT
LAST-MODIFIED: Sat, 01 Jan 2000 00:01:15 GMT
SERVER: Unspecified, UPnP/1.0, Unspecified
X-User-Agent: Fauxmo
CONNECTION: close

<?xml version="1.0"?><root><specVersion><major>1</major><minor>0</minor></specVersion><device><deviceType>urn:Belkin:device:controllee:1</deviceType><friendlyName>fake Indigo switch</friendlyName><manufacturer>Belkin International Inc.</manufacturer><modelName>Emulated Socket</modelName><modelNumber>3.1415</modelNumber><UDN>uuid:Socket-1_0-85a333cd-bad0-370b-b7d0-0d63a93d3c5c</UDN><serviceList><service><serviceType>urn:Belkin:service:basicevent:1</serviceType><serviceId>urn:Belkin:serviceId:basicevent1</serviceId><controlURL>/upnp/control/basicevent1</controlURL><eventSubURL>/upnp/event/basicevent1</eventSubURL><SCPDURL>/eventservice.xml</SCPDURL></service><service><serviceType>urn:Belkin:service:metainfo:1</serviceType><serviceId>urn:Belkin:serviceId:metainfo1</serviceId><controlURL>/upnp/control/metainfo1</controlURL><eventSubURL>/upnp/event/metainfo1</eventSubURL><SCPDURL>/metainfoservice.xml</SCPDURL></service></serviceList></device></root>`

Please make sure you've taken these steps before submitting a new issue:

n8henrie commented 1 year ago

This may be a useful reference: https://fauxmo.readthedocs.io/en/latest/md/protocol_notes.html

My understanding is that the echo devices will send get request to fauxmo for the config setup.xml once its read the echo device should send a post back to fauxmo and the switch is then added. I never seem to get anything back from the echo device

I think it should be:

  1. echo requests setup.xml after you've asked it to ("alexa find connected devices")
  2. fauxmo responds as per above
  3. (nothing expected back from the echo)

With a quick review, everything above looks to be working correctly, I'm not sure why the devices aren't getting added to your Alexa device. I've never used the show or studio, so I don't know if there presence in your network changes anything. Which device are you using to make the "find connected devices" request?

strunker commented 1 year ago

This may be a useful reference: https://fauxmo.readthedocs.io/en/latest/md/protocol_notes.html

My understanding is that the echo devices will send get request to fauxmo for the config setup.xml once its read the echo device should send a post back to fauxmo and the switch is then added. I never seem to get anything back from the echo device

I think it should be:

  1. echo requests setup.xml after you've asked it to ("alexa find connected devices")
  2. fauxmo responds as per above
  3. (nothing expected back from the echo)

With a quick review, everything above looks to be working correctly, I'm not sure why the devices aren't getting added to your Alexa device. I've never used the show or studio, so I don't know if there presence in your network changes anything. Which device are you using to make the "find connected devices" request?

Thanks for the reference. And I have 4 devices in total, two echo gen 4s, one echo studio, one echo show. When I ask the studio, usually because its closest to me on my work desk, they all seem to go into discovery mode so it isnt just one device. I could try unplugging the others and forcing discovery on only one and see what happens. I dont think there is a way to control discovery from just a specific echo device that I have seen.

From the docs above, there is a POST back that the echo does to getbinarystate. It can serve as an acknowledgement that the device was properly added. Mine never seem to do that, my echo devices never send back that post acknowledging the switch\plug was added properly. I can try to unplug some of the devices and see if that makes a difference.

I can go to a browser from a different computer and reach the port properly in a browser and view the setup xml. Are there any other port requiremnts im maybe not thinking of or understanding?

Thanks much, really hope I can get this working, but in any case this entire project is good work and super cool. I have a lot of use cases for this so really been trying to persist in getting it fixed.

image

n8henrie commented 1 year ago

I could try unplugging the others and forcing discovery on only one and see what happens. I dont think there is a way to control discovery from just a specific echo device that I have seen.

That's probably what I would do, I also don't know how to force requests from a device. I don't know if it will make a difference, I don't have those other devices to test, but that's probably what I would try next.

From the docs above, there is a POST back that the echo does to getbinarystate

As it says, this is "when viewing a device" -- since your devices aren't getting added (yet) I would not expect to see this. (Conversely, if you saw this, it would be evidence that your devices had already been added by the echo).

I can go to a browser from a different computer and reach the port properly in a browser and view the setup xml. Are there any other port requiremnts im maybe not thinking of or understanding?

No, it sounds like this is correct.

Thanks much, really hope I can get this working, but in any case this entire project is good work and super cool. I have a lot of use cases for this so really been trying to persist in getting it fixed.

Hopefully we can sort it out, thanks for the kind words!

I have an echo 4 (one of the big round ones) and it seemed to be adding new devices without trouble last week, so I think it should still work for you as well.

strunker commented 1 year ago

I just ran around the apartment, unplugged all but the studio. Sadly, didnt seem to help. Its kind of interesting too because I see discovery requests flying over to fauxmo regularly even when I dont do device discovery its sending those replies. I actually just unplugged the studio, and I am still seeing requests hit fauxmo so there must be something else on my network doing ssdp discovery requests. Perhaps that could be messing with things.

It would be interesting perhaps for me to on the line below "requested by Echo" to understand what the originating IP address is of the requesting device. To try and nail down which requests are coming from where.

2023-01-01 12:02:12 fauxmo:57 INFO setup.xml requested by Echo 2023-01-01 12:02:12 fauxmo:103 DEBUG Fauxmo response to setup request: HTTP/1.1 200 OK CONTENT-LENGTH: 958 CONTENT-TYPE: text/xml DATE: Sun, 01 Jan 2023 17:02:12 GMT LAST-MODIFIED: Sat, 01 Jan 2000 00:01:15 GMT SERVER: Unspecified, UPnP/1.0, Unspecified X-User-Agent: Fauxmo CONNECTION: close

strunker commented 1 year ago

It is responding back to requests from the hue bridge image

as well as my printer image

n8henrie commented 1 year ago

Sadly, didnt seem to help

Bummer, was worth a shot

Its kind of interesting too because I see discovery requests flying over to fauxmo regularly even when I dont do device discovery its sending those replies.

Yes this is normal, just less reliable than manually triggering it

I actually just unplugged the studio, and I am still seeing requests hit fauxmo so there must be something else on my network doing ssdp discovery requests. Perhaps that could be messing with things.

Shouldn't be a problem, I think this is normal with UPnP discovery

It would be interesting perhaps for me to on the line below "requested by Echo" to understand what the originating IP address is of the requesting device. To try and nail down which requests are coming from where.

Unfortunately I don't think that data is available; the debug info comes from the data_received method which only has access to the data it is sent: https://docs.python.org/3.11/library/asyncio-protocol.html#asyncio.Protocol.data_received

strunker commented 1 year ago

Sadly, didnt seem to help

Bummer, was worth a shot

Its kind of interesting too because I see discovery requests flying over to fauxmo regularly even when I dont do device discovery its sending those replies.

Yes this is normal, just less reliable than manually triggering it

I actually just unplugged the studio, and I am still seeing requests hit fauxmo so there must be something else on my network doing ssdp discovery requests. Perhaps that could be messing with things.

Shouldn't be a problem, I think this is normal with UPnP discovery

It would be interesting perhaps for me to on the line below "requested by Echo" to understand what the originating IP address is of the requesting device. To try and nail down which requests are coming from where.

Unfortunately I don't think that data is available; the debug info comes from the data_received method which only has access to the data it is sent: https://docs.python.org/3.11/library/asyncio-protocol.html#asyncio.Protocol.data_received

So just for fun. I made a global var in protocols py that only contains the ip addresses that I want to allow for discovery. Is there a reason that the server itself 127 is sending and responding to requests? Seems a bit off to me. 10.1.1.10 is my server ip and the loop back, its sending and responding back to broadcasts from itself. My idea here is that Ill allow it to reply only from the echo ip address so I can kind of limit all these requests that are flying around.

image

strunker commented 1 year ago

So, kind of intrestingly I dont actually see any ssdp requests coming from my echo device. I only have the one plugged in right now, the studio, and when I ask it to discover devices im not seeing an incoming requests from its address. I only see the ones coming from and then back to the server itself, which is odd and obviously not expected.

strunker commented 1 year ago

Anyway, ill continue to tinker and close this out shortly here. Just opened it to ensure there was nothing I was missing here.

strunker commented 1 year ago

So determined that the ssdp/upnp requests were coming from the fact I have subsonic/plex also running on that server. I killed the processes for that and it cleaned up those requests. Something maybe of some interest, when you have more than one device it looks like literally all of them send out ssdp discovery requests. You can see here 4 distinct ips, 18,20,19,23, which all correlate back to my varing echo devices. image

image

strunker commented 1 year ago

So that is my ultimate issue here, in my scenario. All 4 of my echo devices are sending out ssdp discovery requests, but as you can see in the below image only the printer on .4 and the hue bridge on .6 ever reply. There is no response from fauxmo, and there should be to advertise the buttons.

image

strunker commented 1 year ago

I give up for now, truly doesnt make sense why I cant get it going on Windows. Thanks for the guidance here.

skorokithakis commented 1 year ago

@strunker I have the same problem. Devices that used to be recognized fine are now gone. I even tried the sample config, and alexa discovered only one of the three devices (the fake Indigo switch one). Very odd.

n8henrie commented 1 year ago

@skorokithakis also on windows?

skorokithakis commented 1 year ago

@n8henrie no, on Linux. Oddly, whenever I use set_fake_state, it discovers the switches. Otherwise, it doesn't find any of them. Very odd.

n8henrie commented 1 year ago

@skorokithakis ah, I bet you're running into this: https://github.com/n8henrie/fauxmo-plugins/issues/26

What are you using to determine state?

skorokithakis commented 1 year ago

@n8henrie right now, nothing. I never query the state anyway, so I don't really care about it, but suddenly Alexa stopped discovering devices for my previous script, and now the only thing that works is Fauxmo with the default config, but with fake state.

Ideally, I'd like the MQTT plugin to work, but let's see how it goes. I'll try the resolution in the linked issue, thanks!

n8henrie commented 1 year ago

Yeah, that's probably the issue. At some point it seems like Alexa stopped recognizing devices that don't present a state, and Fauxmo expects devices to determine their own state whenever possible.

I consider use_fake_state to be a bit of a kludge and potential footgun, but if Alexa now requires state perhaps I should feature it (and an option for initial_state more prominently).

skorokithakis commented 1 year ago

@n8henrie it looks like it does, I used use_fake_state and it seems to work perfectly. Thank you!

I would recommend at least not returning "unknown" for initial discovery ever, as debugging "why doesn't it work" is much easier than "why doesn't it discover".

n8henrie commented 1 year ago

It's tough, my goal is for it to "fail early and fail loudly" if people have a config error, but this change in Alexa behavior may change my mind on things.

skorokithakis commented 1 year ago

Yeah, this isn't so much a config error, I don't think, as a bug that doesn't let devices with fake state ever be discovered.

jdodgen commented 1 year ago

@skorokithakis ah, I bet you're running into this: n8henrie/fauxmo-plugins#26

What are you using to determine state?

My version has been working fine now for a couple of months. a bit of a work-around but it works. I for MQTT am replacing use_fake_state with the more MQTTish qos. Currently it defaul;ts to qos=0 I will add qos=1 as well as "retain" in the future. I do not think my changes hurt the normal use of state.

here is my current config

{
    "FAUXMO": {
        "ip_address": "auto"
    },
    "PLUGINS": {
        "MQTTPlugin": {
            "path": "mqttplugin.py",
            "DEVICES": [
                {
                    "port": 52511,
                    "name": "hot",
                    "on_cmd": [ "jhw/button", "pressed" ],
                    "off_cmd": [ "jhw/button", "pressed" ],
                    "mqtt_server": "home-broker.local",
                    "mqtt_port": 1883
                },
                {
                    "port": 52011,
                    "name": "lower heater",
                    "on_cmd": [ "jed/relay2", "on" ],
                    "off_cmd": [ "jed/relay2", "off" ],
                    "mqtt_server": "home-broker.local",
                    "mqtt_port": 1883
                },
                {
                    "port": 52015,
                    "name": "upper heater",
                    "on_cmd": [ "jed/relay1", "on" ],
                    "off_cmd": [ "jed/relay1", "off" ],
                    "mqtt_server": "home-broker.local",
                    "mqtt_port": 1883
                }
            ]
        }
    }
}
n8henrie commented 1 year ago

@skorokithakis i didn't mean a bug in your config specifically, rather in any config in which the state_cmd was misconfigured and therefore not returning meaningful data, which I would prefer to fail by default (instead of letting a user discover days or weeks later that their device state is out of sync with reality).

Using a proper way to query device state is strongly preferred whenever possible, but I've opened a new issue as this new Alexa behavior makes (at the very least) my existing readme incorrect.

Glad I didn't go 1.0 yet 😛

I'm away from home for a couple weeks, will address this soon.

skorokithakis commented 1 year ago

Oh, I agree, but for when the state command is missing, it should return "on" so the device doesn't fail to pair.

About the stare command being present but not working, I'd maybe think that letting the device pair successfully and fail when turning on/off is better UX. It would be surprising if discovery failed because of the state, but much less surprising if it failed because of the state when turning on or off.

jdodgen commented 1 year ago

My patch returns a "on" when no status was given. It is pairing nice. Also all ways runs the loop. Some changes are made to make it more MQTT specific in the future.

jdodgen commented 1 year ago

@skorokithakis Here is the complete version I am using. I am treating "state" as a option not as a requirement. use_fake_state is ignored. If you need the state command it should still work as before. MQTT QoS=0 is the default and I have not implemented QoS=1 or retain yet. It works fine during device discovery, which was the problem I was originally addressing. In the process of getting that to work I added some stuff to make it a little more fault tolerant. The loop is fixed and runs all the time now. This is the currently running version, it has been running for over a month. I need to change some of the comments as well as the QoS stuff. Too many irons in the fire at the moment.

"""Fauxmo plugin for simple MQTT requests.

The on and off methods publish a value to the given MQTT queue. The get_status
method subscribes to an MQTT queue to asynchronously receive the status
published from the device. If the device doesn’t publish a status via MQTT then
omit the state_cmd and the plugin will return a status of “unknown”. The status
received from the device is passed back unchanged to fauxmo which is expecting
“on”, “off” or “unknown”.

Behaviour of the plugin is not entirely predictable if mqttserver and mqttport
are omitted, please make sure to set in your config.

Example config:

{ "FAUXMO": { "ip_address": "auto"

},
"PLUGINS": {
    "MQTTPlugin": {
        "path": "/path/to/mqttplugin.py",
        "DEVICES": [
            {
                "port": 12349,
                "on_cmd": [ "Home/Light/Study01", "1" ],
                "off_cmd": [ "Home/Light/Study01", "0" ],
                "state_cmd": "Home/Light/Study01",
                "name":"MQTT Study Light 1",
                "mqtt_server": "test.mosquitto.org",
                "mqtt_client_id": "study_light_one",
                "mqtt_port": 1883
            },
            {
                "port": 12350,
                "on_cmd": [ "Home/Light/Study02", "1" ],
                "off_cmd": [ "Home/Light/Study02", "0" ],
                "state_cmd": "Home/Light/Study02",
                "name":"MQTT Study Light 2",
                "mqtt_server": "test.mosquitto.org",
                "mqtt_port": 1883
            },
            {
                "port": 12351,
                "on_cmd": [
                    "home-assistant/devices/cmnd/sonoff1/POWER",
                    "ON"
                ],
                "off_cmd": [
                    "home-assistant/devices/cmnd/sonoff1/POWER",
                    "OFF"
                ],
                "state_cmd": "home-assistant/devices/stat/sonoff1/POWER",
                "name":"Hass MQTT device",
                "mqtt_server": "192.168.1.108",
                "mqtt_port": 1883,
                "mqtt_user": "MyHassUser",
                "mqtt_pw": "MySecretP@ssword"
            }
        ]
    }
}

}


Dependencies:
    paho-mqtt==1.3.1
"""

from typing import List, Sequence

from fauxmo.plugins import FauxmoPlugin
from paho.mqtt.client import Client, MQTTMessage

class MQTTPlugin(FauxmoPlugin):
    """Fauxmo plugin to interact with an MQTT server by way of paho."""

    def __init__(
        self,
        *,
        name: str,
        port: int,
        off_cmd: Sequence[str],
        on_cmd: Sequence[str],
        mqtt_port: int = 1883,
        mqtt_pw: str = None,
        mqtt_user: str = None,
        mqtt_server: str = "127.0.0.1",
        mqtt_client_id: str = "",
        state_cmd: str = None,
        qos: int = 0,
        retain: int = 0,
    ) -> None:
        """Initialize an MQTTPlugin instance.

        Kwargs:
            name: device name
            port: Port for Fauxmo to make this device avail to Echo

            mqttport: MQTT server port
            mqttserver: MQTT server address
            mqttclientid: MQTT client id
            mqttuser: MQTT username
            mqttpw: MQTT password
            off_cmd: [ MQTT topic, value to be publshed as str ] to turn off
            on_cmd: [ MQTT topic, value to be publshed as str ] to turn on
            state_cmd: MQTT Message to get state
            qos: MQTT Quality of Service
            retain: MQTT retain
        """
        self.on_cmd, self.on_value = on_cmd[0], on_cmd[1]
        self.off_cmd, self.off_value = off_cmd[0], off_cmd[1]
        self.state_cmd = state_cmd
        self.default_state = "off"  # discovery needs a valid state, this gets set with on and off 
        self.qos = qos
        self.retain = retain
        self.status = "unknown"
        self._subscribed = False

        self.client = Client(client_id=mqtt_client_id)
        if mqtt_user or mqtt_pw:
            self.client.username_pw_set(mqtt_user, mqtt_pw)
        self.client.on_connect = self.on_connect
        self.client.on_subscribe = self.on_subscribe
        self.client.on_message = self.on_message

        try:
            self.client.connect(mqtt_server, mqtt_port, 60)
        except Exception as e:
            print("connect failed", e) 
            # this is not fatal for paho, just a warning 
            # When broker comes alive it reconnects
            # handled in the loop thread
            # if it is not trapped it terminates fauxmo

        super().__init__(name=name, port=port)

        self.client.loop_start() 
        # this is needed for the on_* routines 
        # as well as the other tasks like reconnect
        # and mqtt handshakes

    @property
    def subscribed(self) -> bool:
        """Property to return whether the subscription has completed."""
        return self._subscribed

    def on_subscribe(
        self, client: Client, userdata: str, mid: int, granted_qos: List[int]
    ) -> None:
        """Set attribute to show that initial subscription is complete."""
        self._subscribed = True

    def on_connect(
        self, client: Client, userdata: str, flags: dict, rc: int
    ) -> None:
        """Subscribe to state command on connect (or reconnect)."""
        if self.state_cmd is not None:
            self.client.subscribe(self.state_cmd)

    def on_message(
        self, client: Client, userdata: str, message: MQTTMessage
    ) -> None:
        """Process an incoming message."""
        status = message.payload.decode("utf-8")

        if status == self.off_value:
            self.status = "off"
        elif status == self.on_value:
            self.status = "on"

    def _publish(self, topic: str, value: str) -> bool: 
        print("topic", topic, "value", value)
        try:
            msg = self.client.publish(topic, value)
            # msg = self.client.publish(topic, value, qos=0, retain=self.retain)
            # qos other than 0 have not been implemented yet -- self.qos
            print("published")
            try:
                msg.wait_for_publish()
                print("wait returned")
            except ValueError:
                return False
        except:
            return False
        return True

    def on(self) -> bool:
        """Turn on MQTT device.

        Returns:
            True if device seems to have been turned on.

        """
        self.default_state = "on"
        print("turn on")
        return self._publish(self.on_cmd, self.on_value)

    def off(self) -> bool:
        """Turn off MQTT device.

        Returns:
            True if device seems to have been turned off.

        """
        self.default_state = "off"
        return self._publish(self.off_cmd, self.off_value)

    def get_state(self) -> str:
        """Return the self.status attribute.

        `self.status` is set asynchronously in on_message, so it may not
        immediately reflect state changed.

        Returns:
            State if known, else "unknown".
        """
        """
        the following is a hack to handle when
        it was crashing when no state needed
        and a "Alexa discovery devices" is done 
        """
        print("getting state")
        if self.state_cmd is None:
            return self.default_state

        return self.status
skorokithakis commented 1 year ago

Thanks @jdodgen, that helps. I made similar changes to get mine to run, glad to hear it's been working well for you!