elsbrock / cowboy-ha

🤠 Custom Home Assistant Integration for Cowboy Bikes 🚲💨
MIT License
15 stars 2 forks source link

Login failed with Unknown error occurred #31

Closed s-weise closed 2 weeks ago

s-weise commented 4 months ago

System Health details

System Information

version core-2024.5.3
installation_type Home Assistant Container
dev false
hassio false
docker true
user root
virtualenv false
python_version 3.12.2
os_name Linux
os_version 5.4.0-169-generic
arch x86_64
timezone Europe/Berlin
config_dir /config
Home Assistant Cloud logged_in | false -- | -- can_reach_cert_server | ok can_reach_cloud_auth | ok can_reach_cloud | ok
Dashboards dashboards | 2 -- | -- resources | 0 views | 0 mode | storage
Recorder oldest_recorder_run | 11. Mai 2024 um 11:55 -- | -- current_recorder_run | 11. Mai 2024 um 14:01 estimated_db_size | 0.23 MiB database_engine | sqlite database_version | 3.44.2

Checklist

Describe the issue

This issue happens in my main instance and in this test instance. HA runs in a docker container. The integration was copied into the config/custom_components/ path. When I fill in my credentials and hit send the error "Unknown error occurred" appears. When I use wrong credetials the correct error "Invalid authentication" appears.

Reproduction steps

  1. Search integration on the integration site
  2. Enter username + password
  3. Hit send

Debug logs

ha-test  | 2024-05-11 14:07:17.803 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Received {'type': 'config_entries/flow/progress', 'id': 76}
ha-test  | 2024-05-11 14:07:17.803 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Sending b'{"id":76,"type":"result","success":true,"result":[]}'
ha-test  | 2024-05-11 14:07:17.805 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Received {'type': 'manifest/get', 'integration': 'cowboy', 'id': 77}
ha-test  | 2024-05-11 14:07:17.805 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Sending b'{"id":77,"type":"result","success":true,"result":{"domain":"cowboy","name":"Cowboy","codeowners":["@elsbrock"],"config_flow":true,"dependencies":[],"documentation":"https://github.com/elsbrock/cowboy-ha","homekit":{},"iot_class":"cloud_polling","issue_tracker":"https://github.com/elsbrock/cowboy-ha/issues","requirements":[],"ssdp":[],"version":"v1.0.1","zeroconf":[],"is_built_in":false}}'
ha-test  | 2024-05-11 14:07:17.825 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Received {'type': 'frontend/get_translations', 'language': 'de', 'category': 'config', 'integration': ['cowboy'], 'id': 78}
ha-test  | 2024-05-11 14:07:17.825 DEBUG (MainThread) [homeassistant.helpers.translation] Cache miss for de: {'cowboy'}
ha-test  | 2024-05-11 14:07:17.826 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Received {'type': 'frontend/get_translations', 'language': 'de', 'category': 'selector', 'integration': ['cowboy'], 'id': 79}
ha-test  | 2024-05-11 14:07:17.826 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Received {'type': 'frontend/get_translations', 'language': 'de', 'category': 'title', 'integration': ['cowboy'], 'id': 80}
ha-test  | 2024-05-11 14:07:17.829 DEBUG (MainThread) [homeassistant.components.http.auth] Authenticated 192.168.1.122 for /api/config/config_entries/flow using bearer token
ha-test  | 2024-05-11 14:07:17.830 DEBUG (MainThread) [homeassistant.helpers.http] Serving /api/config/config_entries/flow to 192.168.1.122 (auth: True)
ha-test  | 2024-05-11 14:07:17.838 DEBUG (SyncWorker_1) [homeassistant.util.json] JSON file not found: /config/custom_components/cowboy/translations/de.json
ha-test  | 2024-05-11 14:07:17.841 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Sending b'[{"id":78,"type":"result","success":true,"result":{"resources":{"component.cowboy.config.abort.already_configured":"Device is already configured","component.cowboy.config.error.cannot_connect":"Failed to connect","component.cowboy.config.error.invalid_auth":"Invalid authentication","component.cowboy.config.error.unknown":"Unexpected error","component.cowboy.config.step.user.data.password":"Password","component.cowboy.config.step.user.data.username":"Username"}}},{"id":79,"type":"result","success":true,"result":{"resources":{}}}]'
ha-test  | 2024-05-11 14:07:17.842 DEBUG (MainThread) [homeassistant.components.websocket_api.http.connection] [140668467743296] sascha from 192.168.1.122 (Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0): Sending b'{"id":80,"type":"result","success":true,"result":{"resources":{"component.cowboy.title":"Cowboy"}}}'
ha-test  | 2024-05-11 14:07:17.845 DEBUG (MainThread) [homeassistant.loader] Importing platforms for cowboy executor=['config_flow'] loop=[] took 0.01s
ha-test  | 2024-05-11 14:07:36.786 DEBUG (MainThread) [homeassistant.components.http.auth] Authenticated 192.168.1.122 for /api/config/config_entries/flow/012c5fec2b17a208b448ee8a6f79e712 using bearer token
ha-test  | 2024-05-11 14:07:36.786 DEBUG (MainThread) [homeassistant.helpers.http] Serving /api/config/config_entries/flow/012c5fec2b17a208b448ee8a6f79e712 to 192.168.1.122 (auth: True)
ha-test  | 2024-05-11 14:07:37.353 ERROR (MainThread) [aiohttp.server] Error handling request
ha-test  | Traceback (most recent call last):
ha-test  |   File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request
ha-test  |     resp = await request_handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/local/lib/python3.12/site-packages/aiohttp/web_app.py", line 543, in _handle
ha-test  |     resp = await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/local/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 114, in impl
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 83, in forwarded_middleware
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 88, in ban_middleware
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/local/lib/python3.12/site-packages/aiohttp_session/__init__.py", line 199, in factory
ha-test  |     response = await handler(request)
ha-test  |                ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 295, in auth_middleware
ha-test  |     return await handler(request)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 32, in headers_middleware
ha-test  |     response = await handler(request)
ha-test  |                ^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
ha-test  |     result = await handler(request, **request.match_info)
ha-test  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 71, in with_admin
ha-test  |     return await func(self, request, *args, **kwargs)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 222, in post
ha-test  |     return await super().post(request, flow_id)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 73, in wrapper
ha-test  |     return await method(view, request, data, *args, **kwargs)
ha-test  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 122, in post
ha-test  |     result = await self._flow_mgr.async_configure(flow_id, data)
ha-test  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 368, in async_configure
ha-test  |     result = await self._async_configure(flow_id, user_input)
ha-test  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 414, in _async_configure
ha-test  |     result = await self._async_handle_step(
ha-test  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 573, in _async_handle_step
ha-test  |     result = await self.async_finish_flow(flow, result.copy())
ha-test  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ha-test  |   File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1350, in async_finish_flow
ha-test  |     title=result["title"],
ha-test  |           ~~~~~~^^^^^^^^^
ha-test  | KeyError: 'title'

Diagnostics dump

No response

elsbrock commented 4 months ago

Thanks! A bit busy at the moment, will have a look as soon as possible.

elsbrock commented 1 month ago

@s-weise Hey! It seems like for some reason the API does not return the expected JSON response when you sign in. Could you maybe do the following from the commandline?

curl -X POST -H "Content-Type: application/json" -d '{"email": "foobar", "password": "foobar"}' https://app-api.cowboy.bike/auth/sign_in

Replace foobar with your username and password. Then, share back the results. Don't forget to remove the username/password when reporting back 🙂

Thank you!

s-weise commented 3 weeks ago

Hi. here is the output of curl:

{
    "data": {
        "active_subscriptions": [
        ],
        "available_languages": [
            "en",
            "fr",
            "nl",
            "de"
        ],
        "available_plans": [
            {
                "app_texts": {
                    "asterisk_note": "* Billed annually (€240/year)",
                    "description": "Keep your bike in perfect shape with our on-demand maintenance service with Cowboy-trained technicians. Now available in 22 cities globally and expanding rapidly.",
                    "image_url": "https://s3.eu-west-3.amazonaws.com/app.cowboy.bike/assets/cowboy_care_header.webp",
                    "included": [
                        {
                            "description": "There’s no limit to the number of appointments you can book. We’ll be there.",
                            "title": "Unlimited bookings"
                        },
                        {
                            "description": "An expert technician comes to the address of choice to service your bike.",
                            "title": "Mobile Service"
                        },
                        {
                            "description": "The replacement parts required to maintain your bike (brake pads, tires, and inner tubes) are included in the cost of the subscription.",
                            "title": "Spare parts included"
                        },
                        {
                            "description": "We take care of any puncture, replacing the inner tube or the tire, depending on the damage.",
                            "title": "Flat tires covered"
                        }
                    ],
                    "purchase_text": "Subscribe for €20/month*",
                    "title": "Cowboy Care"
                },
                "currency": "EUR",
                "name": "Cowboy Care",
                "period": 12,
                "price": 24000,
                "purchase_link": "xxx",
                "qover_general_conditions_url": "xxx",
                "qover_insurance_info_url": "xxx",
                "type": "care"
            },
            {
                "app_texts": {
                    "asterisk_note": "* Billed annually (€159/year)",
                    "description": "Ride worry-free with theft insurance for your bike. Our Theft Insurance package gives you access to theft detection notifications and a convenient plan to insure your ride.",
                    "image_url": "https://s3.eu-west-3.amazonaws.com/app.cowboy.bike/assets/theft_insurance_header.webp",
                    "included": [
                        {
                            "description": "Get notified if someone tries to snatch your bike. Whenever your bike moves unexpectedly, we’ll send you real-time tracking via the app.",
                            "title": "Theft Alerts"
                        },
                        {
                            "description": "In case your bike gets stolen, we will reimburse you your full bike value. There’s no depreciation and no excess in the plan.",
                            "title": "Insurance with no depreciation or excess"
                        }
                    ],
                    "purchase_text": "Subscribe for €13.25/month*",
                    "title": "Theft Insurance"
                },
                "currency": "EUR",
                "name": "Theft Insurance",
                "period": 12,
                "price": 15900,
                "purchase_link": "xxx",
                "qover_general_conditions_url": "xxx",
                "qover_insurance_info_url": "xxx",
                "type": "theft"
            }
        ],
        "avatar_url": null,
        "avatars": null,
        "bike": {
            "activated_at": "xxx",
            "autonomies": [
                {
                    "calibrated": false,
                    "full_battery_range": 61.59,
                    "ride_mode": "adaptive_eu"
                },
                {
                    "calibrated": true,
                    "full_battery_range": 61.59,
                    "ride_mode": "static_eu"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 60.0,
                    "ride_mode": "static_offroad"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 76.99,
                    "ride_mode": "adaptive_eco_eu"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 60.0,
                    "ride_mode": "adaptive_us"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 60.0,
                    "ride_mode": "static_us"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 75.0,
                    "ride_mode": "adaptive_eco_us"
                },
                {
                    "calibrated": false,
                    "full_battery_range": 60.0,
                    "ride_mode": "assistance_off"
                }
            ],
            "autonomy": 63.09,
            "available_features": {
                "apple_health": "available",
                "auto_unlock": "available",
                "connected_ride": "available",
                "crash_detection": "available",
                "ride_mode": "hidden",
                "safety_alerts": "available",
                "strava": "available",
                "theft_alerts": "available",
                "trip_analysis": "available",
                "trip_sharing": "available",
                "watch_app": "available"
            },
            "battery_state_of_charge": 70,
            "battery_state_of_charge_updated_at": "2024-09-10T11:13:58.277+02:00",
            "crashed": false,
            "debug_logs": false,
            "duration_modifier": 1.5,
            "firmware_version": "v4.16.5",
            "has_cowboy_connect": true,
            "id": xxx,
            "insurance_conditions": {
                "min_trip_distance": 2.0,
                "passed": true,
                "starts_at": "xxx"
            },
            "last_crash_started_at": null,
            "last_ride_mode": "static_eu",
            "mac_address": "xxx",
            "model": {
                "description": "Cowboy 2",
                "name": "Cowboy 2"
            },
            "nickname": null,
            "passkey": "xxx",
            "pcb_battery_state_of_charge": 86.0,
            "pending_settings": {
            },
            "position": {
                "accuracy": xxx,
                "address": "xxx",
                "adjusted_accuracy": "xxx",
                "created_at": "2024-08-07T12:49:29.963+02:00",
                "elevation": xxx,
                "id": xxx,
                "latitude": xxx,
                "longitude": xxx,
                "received_at": "2024-08-07T12:49:21.000+02:00",
                "source": "bike",
                "type": "trip"
            },
            "seen_at": "2024-09-10T11:13:58.277+02:00",
            "serial_number": "xxx",
            "settings": {
                "auto_lock": 30,
                "auto_unlock": false,
                "brake_light_sensitivity": 10,
                "crash_detection": false,
                "default_ride_mode": null,
                "led_brightness": 100,
                "manual_unlock": 0,
                "max_speed": 28,
                "smart_lock": true,
                "theft_alerts": false
            },
            "sku": {
                "code": "xxx",
                "color": "Black",
                "color_hex": "#0C0D0D",
                "features": {
                    "available_sku_conversion": null,
                    "available_speeds": {
                        "default": 28,
                        "offroad": null
                    },
                    "battery_autonomy": 60,
                    "battery_leds": 5,
                    "default_ble_passkey": "",
                    "displayed_speeds": {
                        "default": 25,
                        "offroad": null
                    },
                    "has_wireless_charger": false,
                    "modbus_devices": [
                        1,
                        4,
                        10
                    ],
                    "throttle_off_voltage": 0.65
                },
                "grade": "No Grade",
                "market": "EU"
            },
            "sku_code": "xxx",
            "stolen": false,
            "total_co2_saved": xxx,
            "total_distance": xxx,
            "total_duration": xxx,
            "trip_sharing": false,
            "warranty_ends_at": "xxx",
            "warranty_started_at": "xxx"
        },
        "biography": null,
        "country_code": "DE",
        "cover_url": null,
        "crash_detection": {
            "contacts": [
            ],
            "max_contacts": 2
        },
        "created_at": "xxx",
        "email": "xxx",
        "emergency_phone_number": "xxx",
        "facebook_profile_url": null,
        "facebook_username": null,
        "first_bike_assigned_at": "xxx",
        "first_name": "xxx",
        "human_efficiency_factor": xxx,
        "id": xxx,
        "in_app_shop_enabled": true,
        "instagram_profile_url": null,
        "instagram_username": null,
        "intercom_token": "xxx",
        "investor_number": null,
        "last_name": "xxx",
        "nickname": "xxx",
        "phone_number": "xxx",
        "profile_link": "xxx",
        "provider": "email",
        "referral_program": {
            "campaign": "de_DE",
            "dashboard_link": "xxx",
            "enabled": true
        },
        "role": "user",
        "settings": {
            "distance_units": "kilometers",
            "referral_program": true,
            "temperature_units": "celsius",
            "weight_units": "kilograms"
        },
        "social_features": false,
        "strava_authorized": false,
        "subscription": null,
        "sync_apple_health": false,
        "sync_google_fit": false,
        "sync_strava": false,
        "total_co2_saved": xxx,
        "total_distance": xxx,
        "total_duration": xxx,
        "uid": "xxx",
        "updated_at": "2024-09-10T20:27:07.510+02:00",
        "uuid": "xxx"
    }
}
elsbrock commented 2 weeks ago

Thank you, I found the problem. The reason it failed is because nickname is null (ie. you didn't assign a name to it) – I assumed there's always a nickname.

It should be fixed with the latest release, would be great if you could confirm.

s-weise commented 2 weeks ago

Hi, now it works. Thanks. Small problem are the generated sensor names. sensor.cowboy_2_mileage -> good sensor.none_remaining_battery -> better sensor.cowboy_2_remaining_battery

elsbrock commented 2 weeks ago

Indeed, need to look into that. Thanks for confirming!