Open ei-ke opened 2 years ago
OK, so, what we need to know, is what protocol the device is talking. At a base level, we need to know if it's talking the same protocol as an ecowitt does, well, at all.
I am not familiar with tshark, or a good way to do this in wireshark, but tcpdump is my old friend here:
tcpdump -s1500 -X port 4199 (if it actually spits out ASCII, like it should you can switch that -X to -A to make it more readable)
If you can grab a bunch of data from it, we can see if it speaks the same protocol as the ecowitt. Once we have that, we can go from there to see what supporting it would look like. (ie, easy, or crazy hard)
Hi Tim,
I'll have access to something better than my mobile phone in 5 hours. I hope until than this probably not correctly formatted log helps:
13:08:06.081405 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [S], seq 921038901, win 5840, options [mss 1460], length 0
E..,.-....db...
.....f.g6..5....`....1......
13:08:06.081431 IP gaia.localdomain.4199 > 192.168.4.10.57958: Flags [S.], seq 3446050979, ack 921038902, win 64240, options [mss 1460], length 0
E..,..@.@..........
.g.f.f..6..6`....Z......
13:08:06.082475 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [.], ack 1, win 5840, length 0
E..(......de...
.....f.g6..6.f..P.......
13:08:06.259247 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [P.], seq 1:349, ack 1, win 5840, length 348
E..../....c....
.....f.g6..6.f..P..."...GET /weatherstation/updateweatherstation.php?ID=&PASSWORD=&action=updateraww&realtime=1&rtfreq=5&dateutc=now&baromin=29.86&tempf=71.9&dewptf=51.8&humidity=49&windspeedmph=0.0&windgustmph=0.0&winddir=220&rainin=0.0&dailyrainin=0.03&solarradiation=0.0&UV=0.0&indoortempf=70.5&indoorhumidity=48 HTTP/1.1
Host:192.168.2.225
Connection: keep-alive
13:08:06.259275 IP gaia.localdomain.4199 > 192.168.4.10.57958: Flags [.], ack 349, win 63892, length 0
E..(..@.@..........
.g.f.f..6...P....V..
13:08:06.259743 IP gaia.localdomain.4199 > 192.168.4.10.57958: Flags [P.], seq 1:151, ack 349, win 63892, length 150
E.....@.@..c.......
.g.f.f..6...P.......HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 2
Date: Tue, 14 Dec 2021 12:08:06 GMT
Server: Python/3.8 aiohttp/3.8.1
13:08:06.259901 IP gaia.localdomain.4199 > 192.168.4.10.57958: Flags [P.], seq 151:153, ack 349, win 63892, length 2
E..*..@.@..........
.g.f.f.:6...P....X..OK
13:08:06.265068 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [.], ack 153, win 5688, length 0
E..(.0....dc...
.....f.g6....f.<P..8.w..
13:08:06.494594 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [F.], seq 349, ack 153, win 5688, length 0
E..(.1....db...
.....f.g6....f.<P..8.v..
13:08:06.494844 IP gaia.localdomain.4199 > 192.168.4.10.57958: Flags [F.], seq 153, ack 350, win 63892, length 0
E..(..@.@..........
.g.f.f.<6...P....V..
13:08:06.496025 IP 192.168.4.10.57958 > gaia.localdomain.4199: Flags [.], ack 154, win 5687, length 0
E..(.2....da...
.....f.g6....f.=P..7.v..
13:08:18.206174 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [S], seq 921457329, win 5840, options [mss 1460], length 0
E..,.9....dV...
.....h.g6.R.....`...|.......
13:08:18.206199 IP gaia.localdomain.4199 > 192.168.4.10.57960: Flags [S.], seq 1452174607, ack 921457330, win 64240, options [mss 1460], length 0
E..,..@.@..........
.g.hV.m.6.R.`....Z......
13:08:18.207331 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [.], ack 1, win 5840, length 0
E..(.:....dY...
.....h.g6.R.V.m.P.......
13:08:18.381438 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [P.], seq 1:349, ack 1, win 5840, length 348
E....;....b....
.....h.g6.R.V.m.P...Z...GET /weatherstation/updateweatherstation.php?ID=&PASSWORD=&action=updateraww&realtime=1&rtfreq=5&dateutc=now&baromin=29.86&tempf=71.9&dewptf=51.8&humidity=49&windspeedmph=0.0&windgustmph=0.0&winddir=220&rainin=0.0&dailyrainin=0.03&solarradiation=0.0&UV=0.0&indoortempf=70.5&indoorhumidity=48 HTTP/1.1
Host:192.168.2.225
Connection: keep-alive
13:08:18.381464 IP gaia.localdomain.4199 > 192.168.4.10.57960: Flags [.], ack 349, win 63892, length 0
E..(.j@.@..*.......
.g.hV.m.6.T.P....V..
13:08:18.381909 IP gaia.localdomain.4199 > 192.168.4.10.57960: Flags [P.], seq 1:151, ack 349, win 63892, length 150
E....k@.@..........
.g.hV.m.6.T.P.......HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 2
Date: Tue, 14 Dec 2021 12:08:18 GMT
Server: Python/3.8 aiohttp/3.8.1
13:08:18.382024 IP gaia.localdomain.4199 > 192.168.4.10.57960: Flags [P.], seq 151:153, ack 349, win 63892, length 2
E..*.l@.@..&.......
.g.hV.m.6.T.P....X..OK
13:08:18.383360 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [.], ack 153, win 5688, length 0
E..(.<....dW...
.....h.g6.T.V.m.P..8._..
13:08:18.612524 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [F.], seq 349, ack 153, win 5688, length 0
E..(.=....dV...
.....h.g6.T.V.m.P..8.^..
13:08:18.612773 IP gaia.localdomain.4199 > 192.168.4.10.57960: Flags [F.], seq 153, ack 350, win 63892, length 0
E..(.m@.@..'.......
.g.hV.m.6.T.P....V..
13:08:18.613948 IP 192.168.4.10.57960 > gaia.localdomain.4199: Flags [.], ack 154, win 5687, length 0
E..(.>....dU...
.....h.g6.T.V.m.P..7.^..
The protocol looks the same, but I'm confused by the GET....
In the ecowitt setup, we setup a mini-web-server on 4199, and then the ecowitt sends data to that with a POST, where it dumps all the data onto the web server, and then we interpret that string, and update everything.
A GET is, backwards?
Oh, also, can you tell me what each of those IP's are? IE, I don't know what "gaia" is vs what 192.168.4.10 is.
Yeah, I also saw the "GET" and hust thought "whatever, if it works..." I also had a look at the different files of your plugin but programming, well, nothing that I'm really capable of until now.
Oh, sorry 192.168.2.225 (gaia) is the VM running HA on a Proxmox host. 192.168.4.10 is the Bresser base station in my "internet of shit" WLAN/VLAN :)
Edit: As soon as I'm at home I'll have a look at the FOSHKplugin. Seems that the Bresser base station spits out some weather undergroundish stuff:
FOSHKplugin acts as a web server and returns different values depending on the requested URL. In addition to "updateweatherstation" to accept a incoming data record in WU format (Weather Underground protocol) the integrated web server processes other http call parameters in GET: http://serverip:port/[URLpath]
I mean, it's not sending a ton of data, jsut a few stats, are those all of your various sensors? In theory, pyecowitt could be hacked up to take the GET params and use those instead of the POST when given.. I guess?
bresser_tcpdump.txt That's approx. 10 minutes of data sent by the station.
I'll play around with the pyecowitt library in another VM.
For testing should I just directly modify the package in /opt/homeassistant/lib/python3.8/site-packages/pyecowitt
or do the modification in the git clone and go with python setup.py install
after source /opt/homeassistant/bin/activate
?
My HA installation is just on a plain ubuntu server without docker etc.
Either way works.. the first is probably the easiest way to just try it out and see.
Changing POST to GET in pyecowitt/pyecowitt/ecowitt.py:
2021-12-14 23:12:18 INFO (MainThread) [custom_components.ecowitt] First ecowitt data recd, setting up sensors.
2021-12-14 23:12:18 ERROR (MainThread) [custom_components.ecowitt] No passkey, cannot set unique id.
Commenting out the passkey check ends with:
2021-12-14 23:42:06 ERROR (MainThread) [custom_components.ecowitt] No sensors found to monitor, check device config.
Passkey will be an issue, but we could potentially fake it..
Try this instead. In the pyecowit library, the main.py will just fire up a webserver, that prints out everything it gets. This will let you test out your GET modifications to make sure the data is actually passing through..
You might have to change a little bit in there more than just POST->GET, like how the data is pulled in... iirc I'm just using aiohttp there, so it shouldn't be super hard.
Thats how far I made it until now. So far the missing sensors show up using the fake_client with the standard POST request
Currently I'm struggling here as I assume I need to set the relative URL /weatherstation/updateweatherstation.php?
with the rel_url function of aiohttp. But I also don't know if web.TCPSite supports this at all.
For changing POST to GET I assume that request.post() must be replaced with with request.text() to be able to receive the data as GET with content type text/plain, But then I have no clue how to parse this into a MultiDict or what I would need to replace the MultiDict you use with.
Some hints what I would need to google for would be highly appreciated :)
https://docs.aiohttp.org/en/stable/web_reference.html
You want the request.query(), because that will return a multidict of the query params, which more or less should just map in. I think the server doesn't even look at the URL string at all, it just assumes whatever it got was a proper connection and parses it.
Thank you for your ongoing support. Seems to be working for the Bresser station now. Only have to add some more conversions in the ecowitt integration due to new sensor names. Would it make sense for you to also integrate that Bresser related stuff into your repo or should I keep it as a fork and rename/reduce it to Bresser only (for the integration as well as the pyecowitt library)? If you want to integrate it I'll try to clean my mess up as good as I can. For identifying Bresser stations maybe the ID property in the Bresser stations web interface should be used to identify it. Every Bresser user would need to set the Bresser article number as ID and a random password that will be used as Passkey. BTW: The Bresser stations are not from FOSHK but from CCLEL. So maybe there article number should be used.
Edit again: And is there an "easy" way to create localisations for the SENSOR_TYPES?
I think try to clean up what you can, so maybe I can pull it and work from there, rather than have to reinvent your wheel. I might not be able to get to it right away though...
My thoughts are going to be that somehow, you need to pick one of those other values, like ID, and internally in pyecowitt it will need to be remapped into PASSKEY so the integration works. I'm currently working on trying to get ecowitt into base HA, so I'm trying not to maintian both the HACS version and that one.. so there might be a time delay before I get everything working. You may want to maintain your local hack until then.
As for translations... not really, at least not yet..
https://github.com/ei-ke/pyecowitt/tree/pr-cclel No further work needed except than getting the fake client updated. Somehow I'm struggling with that.
https://github.com/ei-ke/homeassistant_ecowitt/tree/pr-cclel TODO: const.py LN55-56 should be automatically switched when the integration notices a GET instead of a POST, but I have no idea where to do this check so that the variable can be read from different parts of the programm.
Further I currently get two dewpoint sensors shown and I'm not sure how I should handle it. The station calculates the dewpoint based on the outdoor sensor.
{
"area_id": null,
"capabilities": {
"state_class": "measurement"
},
"config_entry_id": "f2047c569cd74c3c5fa5ec60a0000566",
"device_class": null,
"device_id": "e25e05dc8860b8de47ca781e2f112d78",
"disabled_by": null,
"entity_category": null,
"entity_id": "sensor.dewpoint",
"icon": null,
"id": "638f82b057eceefc54bae2ec1d3d90a3",
"name": null,
"original_device_class": "temperature",
"original_icon": "mdi:thermometer",
"original_name": "Dewpoint",
"platform": "ecowitt",
"supported_features": 0,
"unique_id": "bresser1234-dewptf",
"unit_of_measurement": "\u00b0C"
},
[....]
{
"area_id": null,
"capabilities": {
"state_class": "measurement"
},
"config_entry_id": "f2047c569cd74c3c5fa5ec60a0000566",
"device_class": null,
"device_id": "e25e05dc8860b8de47ca781e2f112d78",
"disabled_by": null,
"entity_category": null,
"entity_id": "sensor.dewpoint_2",
"icon": null,
"id": "4bb81a653dede4094b869a595e0ac3c8",
"name": null,
"original_device_class": "temperature",
"original_icon": "mdi:thermometer",
"original_name": "Dewpoint",
"platform": "ecowitt",
"supported_features": 0,
"unique_id": "bresser1234-dewpointc",
"unit_of_measurement": "\u00b0C"
}
Ahh.. right.. so one of the things the ecowitt code does, is translate any incoming F temps into C automatically. The newer code handles this differently than the older code, so if yuo are using newer pyecowitt with older HACS integration it won't all line up. Once I get a chance to sort through most of this, I can fix that up.
I think the big remaining thing is something for the unique id... hrmm
For the unique ID I would still suggest to tell the users to set the password entry on the base station to something random. Further a hint is needed that the user needs to redirect the traffic from P80 to e. g. P4199 as the base station supports no port directive. Should be no problem to do this with iptables when port 80 is not in use. Otherwise I guess if the webserver a user might run on P80 supports reverse proxying this could also be a solution.
Hrmm.. Would you mind typing up some instructions for setup... since it's a bit fiddly?
No problem. Will do so within the next days :)
First of all thank you for creating this plugin. Currently I'm trying to set it up with this Bresser weather station. The weather station seems to be manufactured by Fine Offset Electronics like the Ecowitt stations. The only difference is that I'm currently having issues to use WS view but I can use the stations web interface. It does offer custom server addresses to send data to but no port option. I'm not sure if "IP:PORT" works and thus I'm doing a port translation on my router from 80 to 4199. On the HA server I can see the traffic coming in with tshark:
But the plugin is not creating any kind of sensors. I've also set the default logging of HA to verbose but grepping for ecowitt doesn't show any useful information to me. The only result is:
I would appreciate any idea how I can further try to narrow down the reason why the plugin doesn't work for me.
Edit: I further tried if enabling HACS option "AppDaemon" or "NetDaemon" changes this behaviour, but it doesn't seem to make a diference
System Health
Home Assistant Community Store
GitHub API | ok -- | -- Github API Calls Remaining | 4969 Installed Version | 1.18.0 Stage | running Available Repositories | 970 Installed Repositories | 1Home Assistant Cloud
logged_in | false -- | -- can_reach_cert_server | ok can_reach_cloud_auth | ok can_reach_cloud | okLovelace
dashboards | 2 -- | -- resources | 0 views | 3 mode | storage