Open DotNet2Web opened 1 year ago
If you can give examples of the app running the mitm proxy i'm happy to add support for these
I tried did but was not succesful doing it.
if you could tell me what and how to set up the mitm proxy then we can sort it out.
https://github.com/allenporter/pyrainbird/blob/main/CONTRIBUTING.md has a little bit of information. Happy to help if you have a more specific question/issue
I will give it a go today.
First of all I need to understand how I can setup the virtual environment on my windows machine. I found a MITM tutorial on the homeassistant forum that Im going to follow.
I recommend using mitm with the rainbird app for what it's worth to capture the traffic of valid requests/ responses.
PyTest results:
Next:
And then I'm lost, I open the rainbird app on my phone and start an irregation but nothing happens in the proxy.
I need to add the proxy between the rainbird controller, any suggestions?
You need to configure your smart phone to use your computer as a proxy, something like described here https://gaikwadchetan93.medium.com/monitoring-modifying-android-app-network-traffic-via-mitm-proxy-part-1-886f6324f705
Got up and running now, I'm capturing the traffic from my iphone to the controller.
From a terminal I run this: mitmproxy -s examples/mitm_rainbird.py
mitmproxy starts capturing all trafic.
When accessing the controller from the app, it captures for example this request:
Request:
{ "id": 1, "jsonrpc": "2.0", "method": "requestWeatherAndStatus", "params": { "Country": "NL", "StickId": "MY_STICKID", "ZipCode": "MY_ZIPCODE" } }
Response:
{ "result": { "Weather": { "city": "My_City", "timeZoneId": "Europe/Amsterdam", "forecast": [ {}, { "dateTime": 1689116400, "high": 23.0, "chanceofrain": 87, "precip": 0.0157, "low": 18.0, "icon": "10d", "description": "rain" }, { "dateTime": 1689202800, "high": 22.0, "chanceofrain": 80, "precip": 0.0315, "low": 17.0, "icon": "10d", "description": "rain" }, { "dateTime": 1689289200, "high": 21.0, "chanceofrain": 89, "precip": 0.1535, "low": 16.0, "icon": "10d", "description": "rain" }, { "dateTime": 1689375600, "high": 21.0, "chanceofrain": 88, "precip": 0.0512, "low": 16.0, "icon": "10d", "description": "rain" }, { "dateTime": 1689462000, "high": 22.0, "chanceofrain": 75, "precip": 0.0236, "low": 18.0, "icon": "10d", "description": "rain" }, { "dateTime": 1689548400, "high": 22.0, "chanceofrain": 0, "precip": 0.0, "low": 17.0, "icon": "01d", "description": "clear sky" } ], "location": "MY_ZIPCODE", "timeZoneRawOffset": 3600 }, "ForecastedRain": {}, "DuplicateMac": false, "StickId": "MY_STICKID", "Controller": {}, "ConnectedStatus": [ { "Status": 0, "CompanyId": 0, "Enabled": true, "Params": {}, "Name": "Alarm.com" }, { "Status": 0, "CompanyId": 1, "Enabled": true, "Params": {}, "Name": "Amazon Alexa" }, { "Status": 0, "CompanyId": 2, "Enabled": true, "Params": {}, "Name": "Google Assistant" }, { "Status": 0, "CompanyId": 3, "Enabled": false, "Params": {}, "Name": "Flume" } ] }, "id": 1, "jsonrpc": "2.0" }
But when I start an irrigation run it return a response that could not be parsed so mitmproxy falls back to raw.
Ok great! Now you've got the harness all setup. That first request is to their cloud API so it's simple to decide.
The requests to the rainbird need to be decoded with the password. You should see some environment variables in the mitm code that you need to set which should enable decoding of device packets.
Once you have that going you should see some partial decoding of the events, which we can then look closer at to figure out the exact way the need to be encoded / decoded into specific commands and responses.
RAINBIRD_PASSWORD
is the environment variable needed for mitm to decode.
We also have https://github.com/allenporter/pyrainbird/blob/main/CONTRIBUTING.md as an example
Setting the Rainbird_password in the python script and capturing its request/response still shows the same octet-stream that cant be decoded.
I scrolled through all response to find one or more that make some sense but they are all still in binary.
Ok I worry maybe the password didn't work. Can you share how you set the environment variable? (Minus the actual password)
In the examples/mitm_rainbird.py script, I just replace the value of the environment variable into my controller pwd.
So within the array between the two quotes I place my password.
Then I save the file and start mitmproxy using this command from a terminal:
mitmproxy -s examples/mitm_rainbird.py
OK if you do it that way then set passwd = "MY_WORKING_CONTROLLER_PASSWORD"
otherwise its looking in the environment variables for your password which won't be set.
Done, sorry for the late response was on a vacation trip.
Changed the way of setting the pwd in the script, like you said. Then I took the same steps and run the mitmproxy.
Still none understandable response. The one thing that is different now is that mitmproxy detects its HEX instead of falling back to raw.
Any advice ?
I'm not sure what you mean. is it worth sharing a little more detail? If its detecting as hex, perhaps its what we're looking for. You'll have a request and a response in hex that looks something like this: https://github.com/allenporter/pyrainbird/blob/main/tests/testdata/current_queue_me3.yaml
In that example file (and see others in that directory) you have the hex on top and the decoded message on the bottom, and so we want to start with the hex requests and figure out how to decode it (i can help do that)
StartedIrrigationRequest.txt StartedIrrigationResponse.txt
This is the first request / response when I started an irrigation run for a zone.
OK wasn't exactly the format I was expecting, but i see what you mean about it being raw hex. I worry this is the encrypted payload. I'm having trouble understanding this hex dump in the context of what mitmproxy shows when i use it myself. Perhaps you can hare more detail about the command you run or screenshots if using it in interactive mode, etc.
@allenporter, any way I can send the screenshots and screen capture to you ?
You can attach to the issue or email allen.porter@gmail.com
Hey guys can you please update the issue as I'm trying myself to understand how can i make it work with this LNK2 module.
@allenporter RAINBIRD_PASSWORD to is the local Access Point Wi-Fi password?
It's the password for the device so you can decode the packets intercepted by the proxy.
When starting a zone on the controller an error occurs
Error: Status request failed with wrong response! Requested 01 but got 00: {‘type’: ‘NotAcknowledgeResponse’, ‘commandEcho’: 57, ‘NAKCode’: 4}
Log:
`Logger: homeassistant.helpers.script.websocket_api_script Source: custom_components/rainbird/switch.py:96 Integration: Rainbird First occurred: 21 mei 2023 om 12:42:48 (1 occurrences) Last logged: 21 mei 2023 om 12:42:48
websocket_api script: Error executing script. Unexpected error for call_service at pos 1: Status request failed with wrong response! Requested 01 but got 00: {'type': 'NotAcknowledgeResponse', 'commandEcho': 57, 'NAKCode': 4} Traceback (most recent call last): File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 452, in _async_step await getattr(self, handler)() File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 685, in _async_call_service_step await service_task File "/usr/src/homeassistant/homeassistant/core.py", line 1849, in async_call task.result() File "/usr/src/homeassistant/homeassistant/core.py", line 1889, in _execute_service await cast(Callable[[ServiceCall], Awaitable[None]], handler.job.target)( File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 809, in handle_service await service.entity_service_call( File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 798, in entity_service_call future.result() # pop exception if have File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 980, in async_request_call await coro File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 838, in _handle_entity_call await result File "/config/custom_components/rainbird/switch.py", line 117, in async_start_zone await self.async_turn_on(duration=zone_run_time) File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1034, in async_turn_on await self.hass.async_add_executor_job(ft.partial(self.turn_on, *kwargs)) File "/usr/local/lib/python3.10/concurrent/futures/thread.py", line 58, in run result = self.fn(self.args, *self.kwargs) File "/config/custom_components/rainbird/switch.py", line 96, in turn_on response = self._controller.irrigate_zone(int(self._zone), int(duration // 60)) File "/usr/local/lib/python3.10/site-packages/pyrainbird/init.py", line 136, in irrigate_zone response = self._process_command( File "/usr/local/lib/python3.10/site-packages/pyrainbird/init.py", line 202, in _process_command response = self.command(cmd, args) File "/usr/local/lib/python3.10/site-packages/pyrainbird/init.py", line 188, in command raise Exception( Exception: Status request failed with wrong response! Requested 01 but got 00: {'type': 'NotAcknowledgeResponse', 'commandEcho': 57, 'NAKCode': 4}`
Version Information:
Home Assistant 2023.5.3 Supervisor 2023.04.1 Operating System 10.1 Frontend-versie: 20230503.3 - latest
Rainbird: ESP-RZXe Firmware: 2.9 LNK2 WiFi Module
Could you please add support of this device into the integration.