From 08984e22ef57caccba595fc9db961ed42ce3c089 Mon Sep 17 00:00:00 2001 From: Florian Bezannier Date: Wed, 16 Mar 2022 19:57:56 +0100 Subject: [PATCH] refacto structure --- .coveragerc | 2 +- .github/workflows/main.yml | 1 + .pre-commit-config.yaml | 4 +- .prospector.yaml | 8 +- Dockerfile | 11 +- FAQ.md | 13 +- README.md | 2 +- config.ini | 17 ++ docker_files/init.sh | 2 +- docs/Install.md | 4 +- docs/api/TripsApi.md | 252 ++++++++++-------- docs/api/UserApi.md | 7 +- docs/api/VehiclesApi.md | 206 +++++++------- libs/car_model.py | 79 ------ libs/charging.py | 72 ----- libs/elec_price.py | 107 -------- libs/utils.py | 74 ----- otp/__init__.py | 1 - psa-car-controller.service | 2 +- server.py => psa-car-controller/__main__.py | 24 +- .../common}/__init__.py | 0 .../common/mylogger.py | 2 +- psa-car-controller/common/utils.py | 46 ++++ .../psa/AccountInformation.py | 2 +- .../psa/RemoteClient.py | 25 +- .../psa/RemoteCredentials.py | 0 {web => psa-car-controller/psa}/__init__.py | 0 .../psa/connected_car_api/__init__.py | 155 +++++++++++ .../psa/connected_car_api/api/__init__.py | 8 + .../psa/connected_car_api}/api/trips_api.py | 2 +- .../psa/connected_car_api}/api/user_api.py | 2 +- .../connected_car_api}/api/vehicles_api.py | 2 +- .../psa/connected_car_api}/api_client.py | 8 +- .../psa/connected_car_api}/configuration.py | 2 +- .../psa/connected_car_api/models/__init__.py | 146 ++++++++++ .../psa/connected_car_api}/models/adas.py | 4 +- .../models/adas_park_assist.py | 0 .../psa/connected_car_api}/models/alert.py | 0 .../models/alert_end_position.py | 0 .../connected_car_api}/models/alert_links.py | 0 .../models/alert_msg_enum.py | 0 .../psa/connected_car_api}/models/alerts.py | 0 .../models/alerts_embedded.py | 0 .../psa/connected_car_api}/models/battery.py | 0 .../models/bounded_program.py | 0 .../models/charging_status_enum.py | 0 .../connected_car_api}/models/circle_zone.py | 0 .../models/circle_zone_coordinates.py | 0 .../models/collection_result.py | 0 .../connected_car_api}/models/collision.py | 0 .../models/collision_links.py | 0 .../models/collision_obj.py | 0 .../models/collision_obj_front.py | 0 .../connected_car_api}/models/collisions.py | 0 .../models/collisions_embedded.py | 0 .../models/created_at_field.py | 0 .../models/data_monitor_trigger.py | 0 .../connected_car_api}/models/data_trigger.py | 0 .../models/default_alert_push.py | 0 .../models/default_alert_push_attributes.py | 0 .../connected_car_api}/models/doors_state.py | 0 .../models/doors_state_opening.py | 0 .../connected_car_api}/models/e_coaching.py | 0 .../models/e_coaching_links.py | 0 .../models/e_coaching_scores.py | 0 .../psa/connected_car_api}/models/energy.py | 0 .../models/energy_battery.py | 0 .../models/energy_battery_health.py | 0 .../models/energy_charging.py | 0 .../psa/connected_car_api}/models/engine.py | 0 .../connected_car_api}/models/engine_oil.py | 0 .../connected_car_api}/models/environment.py | 0 .../models/environment_luminosity.py | 0 .../psa/connected_car_api}/models/event.py | 0 .../connected_car_api}/models/event_links.py | 0 .../connected_car_api}/models/extension.py | 0 .../models/extension_type.py | 0 .../psa/connected_car_api}/models/geometry.py | 0 .../psa/connected_car_api}/models/ignition.py | 0 .../connected_car_api}/models/index_range.py | 0 .../psa/connected_car_api}/models/kinetic.py | 0 .../psa/connected_car_api}/models/lighting.py | 0 .../psa/connected_car_api}/models/link.py | 0 .../connected_car_api}/models/maintenance.py | 0 .../models/maintenance_links.py | 0 .../models/maintenance_obj.py | 0 .../psa/connected_car_api}/models/monitor.py | 0 .../connected_car_api}/models/monitor_id.py | 0 .../models/monitor_links.py | 0 .../models/monitor_parameter.py | 0 .../models/monitor_parameter_trigger_param.py | 0 .../connected_car_api}/models/monitor_ref.py | 0 .../models/monitor_ref_links.py | 0 .../models/monitor_status.py | 0 .../models/monitor_status_setter.py | 0 .../models/monitor_subscribe.py | 0 .../models/monitor_subscribe_batch_notify.py | 0 .../models/monitor_subscribe_retry_policy.py | 0 .../models/monitor_trigger.py | 0 .../models/monitor_webhook.py | 0 .../models/monitor_webhook_attributes.py | 0 .../psa/connected_car_api}/models/monitors.py | 0 .../models/monitors_embedded.py | 0 .../models/overall_autonomy.py | 0 .../psa/connected_car_api}/models/point.py | 0 .../connected_car_api}/models/polygon_zone.py | 0 .../psa/connected_car_api}/models/position.py | 0 .../models/position_properties.py | 0 .../models/preconditioning.py | 0 .../preconditioning_air_conditioning.py | 0 .../models/preconditioning_program.py | 0 .../psa/connected_car_api}/models/privacy.py | 0 .../psa/connected_car_api}/models/program.py | 0 .../models/program_occurence.py | 0 .../psa/connected_car_api}/models/safety.py | 0 .../connected_car_api}/models/service_type.py | 0 .../psa/connected_car_api}/models/status.py | 0 .../models/status_embedded.py | 0 .../models/status_extension_type.py | 0 .../connected_car_api}/models/status_links.py | 0 .../connected_car_api}/models/tab_links.py | 0 .../connected_car_api}/models/telemetry.py | 0 .../models/telemetry_embedded.py | 0 .../models/telemetry_enum.py | 0 .../models/telemetry_extension.py | 0 .../models/telemetry_extension_type.py | 0 .../models/telemetry_message.py | 0 .../models/telemetry_message_embedded.py | 0 .../models/telemetry_message_vehicle.py | 0 ...elemetry_message_vehicle_braking_system.py | 0 .../telemetry_message_vehicle_transmission.py | 0 ...ry_message_vehicle_transmission_gearbox.py | 0 ...ssage_vehicle_transmission_gearbox_gear.py | 0 ...ssage_vehicle_transmission_gearbox_mode.py | 0 .../models/time_monitor_trigger.py | 0 .../connected_car_api}/models/time_range.py | 0 .../connected_car_api}/models/time_stamped.py | 0 .../connected_car_api}/models/time_trigger.py | 0 .../models/time_zone_monitor_trigger.py | 0 .../models/time_zone_trigger.py | 0 .../psa/connected_car_api}/models/trip.py | 0 .../models/trip_avg_consumption.py | 0 .../connected_car_api}/models/trip_links.py | 0 .../psa/connected_car_api}/models/trips.py | 0 .../models/trips_embedded.py | 0 .../models/updated_field.py | 0 .../psa/connected_car_api}/models/url.py | 0 .../psa/connected_car_api}/models/user.py | 0 .../models/user_embedded.py | 0 .../connected_car_api}/models/user_links.py | 0 .../psa/connected_car_api}/models/vect2_d.py | 0 .../psa/connected_car_api}/models/vehicle.py | 0 .../models/vehicle_engine.py | 0 .../models/vehicle_links.py | 0 .../models/vehicle_odometer.py | 0 .../psa/connected_car_api}/models/vehicles.py | 0 .../models/vehicles_embedded.py | 0 .../connected_car_api}/models/way_points.py | 0 .../models/way_points_embedded.py | 0 .../psa/connected_car_api}/models/x_error.py | 0 .../models/zone_monitor_trigger.py | 0 .../connected_car_api}/models/zone_trigger.py | 0 .../models/zone_trigger_place.py | 0 .../models/zone_trigger_place_center.py | 0 .../psa/connected_car_api}/rest.py | 0 {libs => psa-car-controller}/psa/constants.py | 0 .../psa/mqtt_request.py | 6 +- {libs => psa-car-controller}/psa/oauth.py | 14 +- psa-car-controller/psa/otp/__init__.py | 0 {otp => psa-car-controller/psa/otp}/load.py | 3 +- {otp => psa-car-controller/psa/otp}/oaep.py | 0 {otp => psa-car-controller/psa/otp}/otp.py | 15 +- .../psa/otp}/tokenizer.py | 0 .../psa/setup/apk_parser.py | 2 +- .../psa/setup/app_decoder.py | 20 +- .../psa/setup/github.py | 3 +- psa-car-controller/psacc/__init__.py | 0 .../psacc/application/__init__.py | 0 .../psacc/application}/abrp.py | 5 +- .../psacc/application/battery_charge_curve.py | 58 ++++ .../psacc/application/charge_control.py | 18 +- .../psacc/application/charging.py | 100 +++++++ .../psacc/application/ecomix.py | 7 +- .../psacc/application/psa_car_controller.py | 35 +-- .../psacc/application/psa_client.py | 46 ++-- .../psacc/application/trip_parser.py | 5 +- psa-car-controller/psacc/model/__init__.py | 0 .../psacc/model/battery_curve.py | 6 + .../psacc/model}/car.py | 13 +- psa-car-controller/psacc/model/car_model.py | 78 ++++++ .../psacc/model}/car_status.py | 15 +- psa-car-controller/psacc/model/charge.py | 28 ++ psa-car-controller/psacc/model/trip.py | 104 ++++++++ .../psacc/repository/car_model.py | 36 +++ .../psacc/repository/config_repository.py | 205 ++++++++++++++ .../psacc/repository}/db.py | 72 ++++- .../psacc/repository/trips.py | 131 ++------- .../psacc/resources/car_models.yml | 198 ++++++++++++++ .../psacc/utils}/requirements.py | 3 +- psa-car-controller/psacc/utils/utils.py | 38 +++ psa-car-controller/web/__init__.py | 0 {web => psa-car-controller/web}/app.py | 2 +- .../web}/assets/clientside.js | 25 +- .../assets/images/battery-charge-line.svg | 0 .../web}/assets/images/battery-charge.svg | 0 .../web}/assets/images/consumption.svg | 0 .../web}/assets/images/electricity bill.svg | 0 .../web}/assets/images/mileage.svg | 0 .../web}/assets/images/pollution.svg | 0 .../web}/assets/images/settings.svg | 0 .../web}/assets/images/sync.svg | 0 .../web}/assets/sprites/osm-liberty.json | 0 .../web}/assets/sprites/osm-liberty.png | Bin .../web}/assets/sprites/osm-liberty@2x.json | 0 .../web}/assets/sprites/osm-liberty@2x.png | Bin .../web}/assets/style.json | 0 .../web}/dash_custom.py | 1 + {web => psa-car-controller/web}/figures.py | 63 +---- .../web}/tools/Button.py | 0 .../web}/tools/Switch.py | 0 .../web}/tools/figurefilter.py | 4 +- .../web/tools}/utils.py | 0 psa-car-controller/web/view/__init__.py | 0 .../web}/view/config_views.py | 29 +- .../web}/view/control.py | 11 +- {web => psa-car-controller/web}/view/views.py | 86 +++--- psa_connectedcar/__init__.py | 155 ----------- psa_connectedcar/api/__init__.py | 8 - psa_connectedcar/models/__init__.py | 146 ---------- requirements.txt | 4 +- test/test_config.py | 47 ++++ test/test_unit.py | 93 ++++--- test/utils.py | 7 +- 233 files changed, 1934 insertions(+), 1303 deletions(-) create mode 100644 config.ini delete mode 100644 libs/car_model.py delete mode 100644 libs/charging.py delete mode 100644 libs/elec_price.py delete mode 100644 libs/utils.py delete mode 100644 otp/__init__.py rename server.py => psa-car-controller/__main__.py (55%) rename {test => psa-car-controller/common}/__init__.py (100%) rename mylogger.py => psa-car-controller/common/mylogger.py (97%) create mode 100644 psa-car-controller/common/utils.py rename {libs => psa-car-controller}/psa/AccountInformation.py (89%) rename {libs => psa-car-controller}/psa/RemoteClient.py (94%) rename {libs => psa-car-controller}/psa/RemoteCredentials.py (100%) rename {web => psa-car-controller/psa}/__init__.py (100%) create mode 100644 psa-car-controller/psa/connected_car_api/__init__.py create mode 100644 psa-car-controller/psa/connected_car_api/api/__init__.py rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/api/trips_api.py (99%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/api/user_api.py (98%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/api/vehicles_api.py (99%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/api_client.py (99%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/configuration.py (99%) create mode 100644 psa-car-controller/psa/connected_car_api/models/__init__.py rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/adas.py (99%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/adas_park_assist.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alert.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alert_end_position.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alert_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alert_msg_enum.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alerts.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/alerts_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/battery.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/bounded_program.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/charging_status_enum.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/circle_zone.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/circle_zone_coordinates.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collection_result.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collision.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collision_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collision_obj.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collision_obj_front.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collisions.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/collisions_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/created_at_field.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/data_monitor_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/data_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/default_alert_push.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/default_alert_push_attributes.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/doors_state.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/doors_state_opening.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/e_coaching.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/e_coaching_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/e_coaching_scores.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/energy.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/energy_battery.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/energy_battery_health.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/energy_charging.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/engine.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/engine_oil.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/environment.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/environment_luminosity.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/event.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/event_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/extension.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/extension_type.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/geometry.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/ignition.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/index_range.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/kinetic.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/lighting.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/link.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/maintenance.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/maintenance_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/maintenance_obj.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_id.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_parameter.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_parameter_trigger_param.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_ref.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_ref_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_status.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_status_setter.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_subscribe.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_subscribe_batch_notify.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_subscribe_retry_policy.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_webhook.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitor_webhook_attributes.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitors.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/monitors_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/overall_autonomy.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/point.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/polygon_zone.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/position.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/position_properties.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/preconditioning.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/preconditioning_air_conditioning.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/preconditioning_program.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/privacy.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/program.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/program_occurence.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/safety.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/service_type.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/status.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/status_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/status_extension_type.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/status_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/tab_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_enum.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_extension.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_extension_type.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle_braking_system.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle_transmission.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle_transmission_gearbox.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle_transmission_gearbox_gear.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/telemetry_message_vehicle_transmission_gearbox_mode.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_monitor_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_range.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_stamped.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_zone_monitor_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/time_zone_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/trip.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/trip_avg_consumption.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/trip_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/trips.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/trips_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/updated_field.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/url.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/user.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/user_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/user_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vect2_d.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicle.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicle_engine.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicle_links.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicle_odometer.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicles.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/vehicles_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/way_points.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/way_points_embedded.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/x_error.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/zone_monitor_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/zone_trigger.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/zone_trigger_place.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/models/zone_trigger_place_center.py (100%) rename {psa_connectedcar => psa-car-controller/psa/connected_car_api}/rest.py (100%) rename {libs => psa-car-controller}/psa/constants.py (100%) rename {libs => psa-car-controller}/psa/mqtt_request.py (84%) rename {libs => psa-car-controller}/psa/oauth.py (93%) create mode 100644 psa-car-controller/psa/otp/__init__.py rename {otp => psa-car-controller/psa/otp}/load.py (97%) rename {otp => psa-car-controller/psa/otp}/oaep.py (100%) rename {otp => psa-car-controller/psa/otp}/otp.py (97%) rename {otp => psa-car-controller/psa/otp}/tokenizer.py (100%) rename {libs => psa-car-controller}/psa/setup/apk_parser.py (98%) rename {libs => psa-car-controller}/psa/setup/app_decoder.py (88%) rename {libs => psa-car-controller}/psa/setup/github.py (97%) create mode 100644 psa-car-controller/psacc/__init__.py create mode 100644 psa-car-controller/psacc/application/__init__.py rename {web => psa-car-controller/psacc/application}/abrp.py (96%) create mode 100644 psa-car-controller/psacc/application/battery_charge_curve.py rename charge_control.py => psa-car-controller/psacc/application/charge_control.py (92%) create mode 100644 psa-car-controller/psacc/application/charging.py rename ecomix.py => psa-car-controller/psacc/application/ecomix.py (96%) rename libs/config.py => psa-car-controller/psacc/application/psa_car_controller.py (84%) rename my_psacc.py => psa-car-controller/psacc/application/psa_client.py (89%) rename trip_parser.py => psa-car-controller/psacc/application/trip_parser.py (96%) create mode 100644 psa-car-controller/psacc/model/__init__.py create mode 100644 psa-car-controller/psacc/model/battery_curve.py rename {libs => psa-car-controller/psacc/model}/car.py (92%) create mode 100644 psa-car-controller/psacc/model/car_model.py rename {libs => psa-car-controller/psacc/model}/car_status.py (76%) create mode 100644 psa-car-controller/psacc/model/charge.py create mode 100644 psa-car-controller/psacc/model/trip.py create mode 100644 psa-car-controller/psacc/repository/car_model.py create mode 100644 psa-car-controller/psacc/repository/config_repository.py rename {web => psa-car-controller/psacc/repository}/db.py (81%) rename trip.py => psa-car-controller/psacc/repository/trips.py (56%) create mode 100644 psa-car-controller/psacc/resources/car_models.yml rename {libs => psa-car-controller/psacc/utils}/requirements.py (94%) create mode 100644 psa-car-controller/psacc/utils/utils.py create mode 100644 psa-car-controller/web/__init__.py rename {web => psa-car-controller/web}/app.py (98%) rename {web => psa-car-controller/web}/assets/clientside.js (94%) rename {web => psa-car-controller/web}/assets/images/battery-charge-line.svg (100%) rename {web => psa-car-controller/web}/assets/images/battery-charge.svg (100%) rename {web => psa-car-controller/web}/assets/images/consumption.svg (100%) rename {web => psa-car-controller/web}/assets/images/electricity bill.svg (100%) rename {web => psa-car-controller/web}/assets/images/mileage.svg (100%) rename {web => psa-car-controller/web}/assets/images/pollution.svg (100%) rename {web => psa-car-controller/web}/assets/images/settings.svg (100%) rename {web => psa-car-controller/web}/assets/images/sync.svg (100%) rename {web => psa-car-controller/web}/assets/sprites/osm-liberty.json (100%) rename {web => psa-car-controller/web}/assets/sprites/osm-liberty.png (100%) rename {web => psa-car-controller/web}/assets/sprites/osm-liberty@2x.json (100%) rename {web => psa-car-controller/web}/assets/sprites/osm-liberty@2x.png (100%) rename {web => psa-car-controller/web}/assets/style.json (100%) rename {web => psa-car-controller/web}/dash_custom.py (99%) rename {web => psa-car-controller/web}/figures.py (79%) rename {web => psa-car-controller/web}/tools/Button.py (100%) rename {web => psa-car-controller/web}/tools/Switch.py (100%) rename {web => psa-car-controller/web}/tools/figurefilter.py (98%) rename {web => psa-car-controller/web/tools}/utils.py (100%) create mode 100644 psa-car-controller/web/view/__init__.py rename {web => psa-car-controller/web}/view/config_views.py (90%) rename {web => psa-car-controller/web}/view/control.py (93%) rename {web => psa-car-controller/web}/view/views.py (86%) delete mode 100644 psa_connectedcar/__init__.py delete mode 100644 psa_connectedcar/api/__init__.py delete mode 100644 psa_connectedcar/models/__init__.py create mode 100644 test/test_config.py diff --git a/.coveragerc b/.coveragerc index b0338d0..a876be6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -2,6 +2,6 @@ parallel=True concurrency=thread omit = - psa_connectedcar/* + psa-car-controller/psa/connected_car_api/* venv/* test/* diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8304518..f9d870c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,5 +32,6 @@ jobs: CODACY_PROJECT_TOKEN: ${{ secrets.CODACY_PROJECT_TOKEN }} run: | echo Test + prospector coverage run -m unittest || exit 1 [ -n "$CODACY_PROJECT_TOKEN" ] && coverage combine && coverage xml -o cobertura.xml && bash <(curl -Ls https://coverage.codacy.com/get.sh) report -r cobertura.xml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 411f528..d71bd0d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,6 @@ -default_language_version: - python: python3.6 repos: - repo: https://github.com/PyCQA/prospector - rev: 1.3.1 # The version of Prospector to use, at least 1.1.7 + rev: 1.7.7 # The version of Prospector to use, if not 'master' for latest hooks: - id: prospector language: system \ No newline at end of file diff --git a/.prospector.yaml b/.prospector.yaml index d68319b..bfae8bf 100644 --- a/.prospector.yaml +++ b/.prospector.yaml @@ -1,10 +1,9 @@ doc-warnings: false -use: flask max-line-length: 120 ignore-paths: - - psa_connectedcar - test -pep8: + - connected_car_api +pycodestyle: disable: - E722 pyflakes: @@ -19,5 +18,4 @@ pylint: - W0603 - I0011 - W0511 - - consider-using-f-string - + - consider-using-f-string \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index f3c564e..7ee219f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,13 @@ -ARG PYTHON_DEP='python3 python3-wheel python3-typing-extensions python3-pandas python3-six python3-dateutil python3-brotli python3-pycryptodome libatlas3-base python3-cryptography python3-scipy androguard python3-flask python3-paho-mqtt ca-certificates' +ARG PYTHON_DEP='python3 python3-wheel python3-typing-extensions python3-pandas python3-six python3-dateutil python3-brotli python3-pycryptodome libatlas3-base python3-cryptography python3-scipy androguard python3-flask python3-paho-mqtt python3-ruamel.yaml ca-certificates' ARG DEBIAN_FRONTEND=noninteractive FROM debian:bullseye-slim AS builder ARG PYTHON_DEP RUN BUILD_DEP='python3-pip python3-setuptools python3-dev libblas-dev liblapack-dev gfortran libatlas3-base' ; \ apt-get update && apt-get install -y --no-install-recommends $BUILD_DEP $PYTHON_DEP; -COPY . /psa_car_controller/ -RUN pip3 install --system --no-cache-dir -r /psa_car_controller/requirements.txt +COPY psa-car-controller /psa-car-controller +COPY requirements.txt /tmp/ +RUN pip3 install --system --no-cache-dir --ignore-installed -r /tmp/requirements.txt EXPOSE 5000 FROM debian:bullseye-slim @@ -19,5 +20,5 @@ COPY --from=builder /usr/local/lib /usr/local/lib RUN apt-get install -y --no-install-recommends $PYTHON_DEP && \ apt-get clean ; \ rm -rf /var/lib/apt/lists/* -COPY . /psa_car_controller/ -CMD /psa_car_controller/docker_files/init.sh \ No newline at end of file +COPY . /psa-car-controller/ +CMD /psa-car-controller/docker_files/init.sh \ No newline at end of file diff --git a/FAQ.md b/FAQ.md index 59579f9..fdb856c 100644 --- a/FAQ.md +++ b/FAQ.md @@ -2,17 +2,8 @@ ## Frequent error ### 1. Can't get car model The car model need to be known by the app. To find it, the app use the first 10 character of your VIN. -If the car isn't in the list we need to add it, to do so you have two options: -- If you have the skills : - - You can add your car to the list yourself to do so look at [this example](https://github.com/flobz/psa_car_controller/pull/112/commits/e7304ef8f4e4a4498f202a7a4a7bbe451fbfe977). -You will need the VIN of your vehicle and the car abrp name, to get it go [here](https://api.iternio.com/1/tlm/get_carmodels_list?api_key=32b2162f-9599-4647-8139-66e9f9528370). - Don't forget to do a pull request with your changes. - - -- If you don't: - - Open an issue with [this template](https://github.com/flobz/psa_car_controller/issues/new?assignees=&labels=Car_model&template=can-t-get-car-model.md&title=%5BNew+Car+model%5D+my+model) +If the car isn't in the list we need to add it, to do that you need to edit the file here: +### todo ### 2. Error during activation {'newversion': '2.0.0', 'newversionurl': 'http://m.inwebo.com/', 'err': 'NOK:FORBIDDEN'} diff --git a/README.md b/README.md index f3f1245..ccdce4d 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ A video in French was made by vlycop to explain how to use this application : ht You can add the -r argument to record the position of the vehicle and retrieve this information in a dashboard. -``python3 server.py -f config.json -c charge_config.json -r`` +``python3 psa-car-controller -f config.json -c charge_config.json -r`` You will be able to visualize your trips, your consumption and some statistics: diff --git a/config.ini b/config.ini new file mode 100644 index 0000000..2f21f22 --- /dev/null +++ b/config.ini @@ -0,0 +1,17 @@ +[General] +currency = € +# minimum trip length in km so it's added to stats and map in website +minimum trip length = 10 + +[Electricity config] +# price by kw/h +day price = 0.15 +night price = +# ex: 22h30 +night hour start = +# ex: 6h00 +night hour end = +dc charge price = 0.4 +high speed dc charge price = 0.6 +# minimum power in kW that should be delivered during a charge so it can be considered as a high speed charger +high speed dc charge threshold = 60 \ No newline at end of file diff --git a/docker_files/init.sh b/docker_files/init.sh index b88b142..a26c780 100755 --- a/docker_files/init.sh +++ b/docker_files/init.sh @@ -2,4 +2,4 @@ echo "Containerised psa_car_controller loading..." cd "$PSACC_CONFIG_DIR" ARGS="-p $PSACC_PORT -l 0.0.0.0 -b $PSACC_BASE_PATH $PSACC_OPTIONS" -python3 -u /psa_car_controller/server.py $ARGS +python3 -u /psa_car_controller $ARGS diff --git a/docs/Install.md b/docs/Install.md index 152d076..86e9dd6 100644 --- a/docs/Install.md +++ b/docs/Install.md @@ -20,10 +20,10 @@ Start the app with charge control enabled : -``python3 server.py --web-conf`` +``python3 psa-car-controller --web-conf`` At the first launch you will be asked to connect and give a code that you will receive by SMS and also give your pin code (the four-digit code that your use on the android app). If it failed you can remove the file otp.bin and retry. You can see all options available with : -``python3 server.py -h`` +``python3 psa-car-controller -h`` diff --git a/docs/api/TripsApi.md b/docs/api/TripsApi.md index 1020ce0..d22d98e 100644 --- a/docs/api/TripsApi.md +++ b/docs/api/TripsApi.md @@ -32,29 +32,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Gives the wayPoints for a specified User Trip. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) @@ -96,33 +97,34 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Gives the Vehicle's wayPoints for a specified Trip. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) tolerance = 3.4 # float | Tolerance factor is expressed in length KM unit and is used to simplify path by reducing the total number of points by is using Douglas-Peucker algorithme to find a similar curve with fewer points (find more info here: [Ramer_Douglas_Peucker_algorithm](https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm#Algorithm) ). (optional) try: @@ -166,31 +168,32 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the set of Telemetry values that occurred for a given vehicle (id) and a speific Trip (tid) during the timestamp ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) type = ['type_example'] # list[str] | Results will only contain Telemetry messages of this kind. You can add more than one message type. (optional) @@ -238,32 +241,33 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the set of Telemetry values that occurred for a given vehicle (id) and a speific Trip (tid) during the timestamp ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) type = ['type_example'] # list[str] | Results will only contain Telemetry messages of this kind. You can add more than one message type. (optional) @@ -312,29 +316,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE This method returns the Trip that matches the Trip id (tid) a given Vehicle (id) has taken. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip @@ -376,29 +381,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE This method returns the Trip that matches the Trip id (tid) User has taken. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip try: @@ -438,29 +444,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Return the User Trip ECoaching evaluation. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) @@ -502,31 +509,32 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE This method returns a list of all Trips that a given Vehicle has taken. This will NOT include Trips that have not yet been completed. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -572,29 +580,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Return the Trip ECoaching evaluation. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) @@ -638,29 +647,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the Collision(cid) that occurred for a given vehicle(id) during a Trip(tid) . ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip cid = 'cid_example' # str | Results will only contain the Collision related to this Collision *id*. @@ -702,31 +712,32 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the set of Collisions that occurred for a given vehicle (id) and a speific Trip (tid) during the timestamp ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -772,29 +783,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns information about a specific alert messages for a given Trip. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip aid = 'aid_example' # str | id of the alert. locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) @@ -838,31 +850,32 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the latest alert messages during a Trip. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -910,30 +923,31 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE This method returns a list of all Trips the User has taken. This will NOT include Trips that have not yet been completed. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -978,29 +992,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the Collision(cid) that occurred for a given vehicle(id) during a Trip(tid) . ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip cid = 'cid_example' # str | Results will only contain the Collision related to this Collision *id*. @@ -1044,32 +1059,33 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the set of Collisions that occurred for a given vehicle (id) and a speific Trip (tid) during the timestamp ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -1116,29 +1132,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns information about a specific alert messages for a given Vehicle and Trip. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip aid = 'aid_example' # str | id of the alert. @@ -1184,32 +1201,33 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the latest alert messages for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.TripsApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.TripsApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. tid = 'tid_example' # str | the *id* of Trip -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) diff --git a/docs/api/UserApi.md b/docs/api/UserApi.md index 26a4435..5e7be97 100644 --- a/docs/api/UserApi.md +++ b/docs/api/UserApi.md @@ -15,15 +15,16 @@ User's information Returns the User's information. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # create an instance of the API class -api_instance = psa_connectedcar.UserApi() +api_instance = connected_car_api.UserApi() try: # User's information diff --git a/docs/api/VehiclesApi.md b/docs/api/VehiclesApi.md index 0d6560a..09a85ee 100644 --- a/docs/api/VehiclesApi.md +++ b/docs/api/VehiclesApi.md @@ -30,29 +30,30 @@ Delete a Monitor. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Stop (disable) an existing Monitor. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. mid = 'mid_example' # str | id of the alert. @@ -93,29 +94,30 @@ Last position identified Returns the latest GPS Position of the Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. try: @@ -155,29 +157,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the latest Telemetry messages that occurred during a selective timestamp-ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. type = ['type_example'] # list[str] | Results will only contain Telemetry messages of this kind. You can add more than one message type. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) @@ -229,31 +232,32 @@ Name | Type | Description | Notes Returns the latest alert messages for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -302,29 +306,30 @@ Name | Type | Description | Notes Returns information about a specific alert messages for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. aid = 'aid_example' # str | id of the alert. locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) @@ -367,29 +372,30 @@ Details of vehicule Returns detailed information about a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. try: @@ -429,31 +435,32 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the set of Collisions that occurred for a given vehicle (id) during the timestamp ranges and bounded by an index range. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. -timestamps = [psa_connectedcar.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) +timestamps = [connected_car_api.TimeRange()] # list[TimeRange] | Array of **\"timestamp\"** ranges. Results will contain results whose timestamps are included in those date-time ranges (see **timestamp** data model).**\"timestamp\"** items should be expressed as in '[RFC3339](https://www.ietf.org/rfc/rfc3339.txt)'. (optional) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) page_token = 'page_token_example' # str | Start-Page marker, the token for continuing a previous list request on the next page. It is built and used **only** by the server. (optional) @@ -499,29 +506,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the Collision that matches the vehicle id and the Collision cid. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. cid = 'cid_example' # str | Results will only contain the Collision related to this Collision *id*. @@ -563,29 +571,30 @@ Name | Type | Description | Notes Returns the latest Maintenance information for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. try: @@ -624,29 +633,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns the list of subscribed Monitors for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) @@ -692,29 +702,30 @@ OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Returns information about a specific Monitor for a Vehicle. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. mid = 'mid_example' # str | id of the alert. @@ -756,29 +767,30 @@ Vehicle status. Returns the latest vehicle status. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. extension = ['extension_example'] # list[str] | Additional data set that will be included in embedded field * _Disclaimer_: **Enabling ```odometer``` extension will automatically disable ```kinetic``` telemetry message** (optional) @@ -820,29 +832,30 @@ List of vehicules Returns the Vehicles associated with the User. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) index_range = '0-' # str | Results indexes will be included in this range (see **indexRange** model). default: 0- example: 0-, 0-5 (optional) (default to 0-) page_size = 60 # int | The maximum number of results (for a collection results response) to return per page. When not set, at most 60 results will be returned. (optional) (default to 60) locale = 'locale_example' # str | Locale is used for rendering text, correctly displaying regional monetary values, time and date formats. Respect REGEX \\w(-\\w)? (optional) @@ -888,18 +901,19 @@ Set a new monitor status. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Set monitor status. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi() +api_instance = connected_car_api.VehiclesApi() id = 'id_example' # str | Results will only be related to this Vehicle *id*. mid = 'mid_example' # str | id of the alert. -body = psa_connectedcar.MonitorStatusSetter() # MonitorStatusSetter | (optional) +body = connected_car_api.MonitorStatusSetter() # MonitorStatusSetter | (optional) try: # Set a new monitor status. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE @@ -940,31 +954,32 @@ Create a new Monitor. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE >Create a Monitor for a Vehicle. This is a kind of vehicle monitor that generates an event following the transition state of one of the (monitored) data of the vehicles. As for example the fuel level, the moving out of a defined geographical area. >When the the trigger occurs, the built event expressed as a JSON object will be sent over the callback. ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # Configure OAuth2 access token for authorization: Vehicle_auth -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' # Configure API key authorization: client_id -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['client_id'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['client_id'] = 'Bearer' # Configure API key authorization: realm -configuration = psa_connectedcar.Configuration() +configuration = connected_car_api.Configuration() configuration.api_key['x-introspect-realm'] = 'YOUR_API_KEY' # Uncomment below to setup prefix (e.g. Bearer) for API key, if needed # configuration.api_key_prefix['x-introspect-realm'] = 'Bearer' # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi(psa_connectedcar.ApiClient(configuration)) +api_instance = connected_car_api.VehiclesApi(connected_car_api.ApiClient(configuration)) id = 'id_example' # str | Results will only be related to this Vehicle *id*. -body = psa_connectedcar.MonitorParameter() # MonitorParameter | (optional) +body = connected_car_api.MonitorParameter() # MonitorParameter | (optional) try: # Create a new Monitor. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE @@ -1004,18 +1019,19 @@ Update and existing Monitor. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE Update an existing ```Monitor``` that has been posted (and accepted previously) for this vehicle. The monitor object (body) provided should be complete because the aggregation is not supported for the update of the ```monitor```. you can retrieve this object using the ```GET /monitor/{mid}``` API then modify it and finally publish it (via this ```PUT API```) ### Example + ```python from __future__ import print_function import time -import psa_connectedcar -from psa_connectedcar.rest import ApiException +import connected_car_api +from connected_car_api.rest import ApiException from pprint import pprint # create an instance of the API class -api_instance = psa_connectedcar.VehiclesApi() +api_instance = connected_car_api.VehiclesApi() mid = 'mid_example' # str | id of the alert. id = 'id_example' # str | Results will only be related to this Vehicle *id*. -body = psa_connectedcar.MonitorParameter() # MonitorParameter | (optional) +body = connected_car_api.MonitorParameter() # MonitorParameter | (optional) try: # Update and existing Monitor. OUT OF 1ST RELEASE (R-LEV 1.1) SCOPE diff --git a/libs/car_model.py b/libs/car_model.py deleted file mode 100644 index 2fe57fb..0000000 --- a/libs/car_model.py +++ /dev/null @@ -1,79 +0,0 @@ -import re - -from mylogger import logger - -DEFAULT_BATTERY_POWER = 46 -DEFAULT_FUEL_CAPACITY = 0 -DEFAULT_MAX_ELEC_CONSUMPTION = 70 -DEFAULT_MAX_FUEL_CONSUMPTION = 30 - - -class CarModel: - # pylint: disable=too-many-arguments - def __init__(self, name, battery_power, fuel_capacity, abrp_name=None, reg=None, - max_elec_consumption=DEFAULT_MAX_ELEC_CONSUMPTION, max_fuel_consumption=DEFAULT_MAX_FUEL_CONSUMPTION): - self.name = name - self.battery_power = battery_power - self.fuel_capacity = fuel_capacity - self.abrp_name = abrp_name - self.reg = reg - self.max_elec_consumption = max_elec_consumption - self.max_fuel_consumption = max_fuel_consumption - - def match(self, vin): - if self.reg is None: - return False - return re.match(self.reg, vin) is not None - - @staticmethod - def find_model_by_vin(vin): - if vin != "vin": - for car_model in car_models: - if car_model.match(vin): - return car_model - logger.warning("Can't get car model, please report an issue on github with your car model" - " and first ten letter of your VIN : %s", vin[:10]) - return CarModel("unknown", DEFAULT_BATTERY_POWER, DEFAULT_FUEL_CAPACITY) - - @staticmethod - def find_model_by_name(name): - for car_model in car_models: - if car_model.name == name: - return car_model - return None - - -class ElecModel(CarModel): - # pylint: disable=too-many-arguments - def __init__(self, name, battery_power, abrp_name=None, reg=None, - max_elec_consumption=DEFAULT_MAX_ELEC_CONSUMPTION): - super().__init__(name, battery_power, 0, abrp_name, reg, max_elec_consumption, 0) - - -car_models = [ - ElecModel("e-208", 46, "peugeot:e208:20:50", r"VR3UHZKX.*"), - ElecModel("e-2008", 46, "peugeot:e2008:20:48", r"VR3UKZKX.*"), - ElecModel("e-Spacetourer", 46, "peugeot:etraveler:21:50:citroen", r"VF7VZZKX.*"), - ElecModel("e-Traveller", 46, "peugeot:etraveler:21:50", r"VF3VZZKX.*"), - ElecModel("corsa-e", 46, "opel:corsae:20:50", r"VXKUHZKX.*"), - ElecModel("DS3 Crossback e-tense", 46, "ds:3crossback:20:48", r"VR1UJZKX.*"), # VR1UJZKXZL - ElecModel("Mokka-e", 46, "opel:mokkae:20:48", r"VXKUKZKX.*"), # VXKUKZKXZM - ElecModel("Zaphira-e", 68, "peugeot:etraveler:21:75:opel", r"VXEVZZKX.*"), # VXEVZZKXZMZ - ElecModel("E-C4", 46, "citroen:ec4:21:50", r"VR7BCZKX.*"), # VR7BCZKXCM - CarModel("SUV 3008 Hybrid 225", 13.2, 43, reg=r"VF3M4DGZ.*"), # VF3M4DGZUMS - CarModel("SUV 3008", 0, 53, reg=r"VF3MJEHZ.*"), # VF3MJEHZRJ - CarModel("308", 0, 56, reg=r"VF3L35GG.*"), - CarModel("208", 0, 44, reg=r"VR3UPHN[SE].*"), # VR3UPHNSSM VR3UPHNEKM - CarModel("2008", 0, 44, reg=r"VR3USHNS.*"), # VR3USHNSKM - CarModel("2008 II", 0, 45, reg=r"VR3USHNK.*"), # VR3USHNKKL - CarModel("SUV 5008 II", 0, 56, reg=r"VF3MRHNS.*"), # vf3mrhnsum - CarModel("SUV 5008 II 2018", 0, 56, reg=r"VF3MRHNY.*"), # VF3MRHNYHH - CarModel("N5008 GT-LINE 1.6L", 0, 60, reg=r"VF3MCBHZ.*"), # VF3MCBHZWJ - CarModel("C5 Aircross Hybrid", 13.2, 43, reg=r"VR7A4DGZ.*"), # VR7A4DGZSM - CarModel("DS7 Crossback E-Tense 300 4x4", 11.5, 43, reg="VR1J45GB.*"), # VR1J45GBUM VR1J45GBUL VR1J45GBUK - CarModel("508 SW Hybrid", 11.5, 45, reg=r"VR3F4DGZ.*"), # VR3F4DGZTL - CarModel("508 Hybrid", 11.5, 43, reg=r"VR3F3DGZ.*"), # VR3F3DGZTM - CarModel("508 SW 2.0 HDI 163CV", 0, 72, reg=r"VF38ERHH.*"), # VF38ERHH - CarModel("Grandland X Hybrid", 13.2, 43, reg=r"W0VZ4DGZ.*"), # W0VZ4DGZ2L - CarModel("Grandland X Hybrid 4x4", 13.2, 43, reg=r"W0VZ45GB.*") # W0VZ45GB3L -] diff --git a/libs/charging.py b/libs/charging.py deleted file mode 100644 index 9b432ec..0000000 --- a/libs/charging.py +++ /dev/null @@ -1,72 +0,0 @@ -from datetime import datetime -from sqlite3 import IntegrityError - -from typing import List - -from ecomix import Ecomix -from libs.elec_price import ElecPrice -from mylogger import logger -from web.db import Database - - -class Charging: - elec_price: ElecPrice = ElecPrice(None) - - @staticmethod - def get_chargings() -> List[dict]: - conn = Database.get_db() - res = conn.execute("select * from battery ORDER BY start_at").fetchall() - conn.close() - return list(map(dict, res)) - - @staticmethod - def set_default_price(): - if Charging.elec_price.is_enable(): - conn = Database.get_db() - charge_list = list(map(dict, conn.execute("SELECT * FROM battery WHERE price IS NULL").fetchall())) - for charge in charge_list: - charge["price"] = Charging.elec_price.get_price(charge["start_at"], charge["stop_at"], charge["kw"]) - Database.set_chargings_price(conn, charge["start_at"], charge["price"]) - conn.close() - - # pylint: disable=too-many-arguments - @staticmethod - def update_chargings(conn, start_at, stop_at, level, co2_per_kw, consumption_kw, vin): - price = Charging.elec_price.get_price(start_at, stop_at, consumption_kw) - conn.execute( - "UPDATE battery set stop_at=?, end_level=?, co2=?, kw=?, price=? WHERE start_at=? and VIN=?", - (stop_at, level, co2_per_kw, consumption_kw, price, start_at, vin)) - Database.clean_battery(conn) - - @staticmethod - def record_charging(car, charging_status, charge_date: datetime, level, latitude, # pylint: disable=too-many-locals - longitude, country_code, charging_mode, charging_rate, autonomy): - conn = Database.get_db() - charge_date = charge_date.replace(microsecond=0) - if charging_status == "InProgress": - stop_at, start_at = conn.execute("SELECT stop_at, start_at FROM battery WHERE VIN=? ORDER BY start_at " - "DESC limit 1", (car.vin,)).fetchone() or [False, None] - try: - conn.execute("INSERT INTO battery_curve(start_at,VIN,date,level,rate,autonomy) VALUES(?,?,?,?,?,?)", - (start_at, car.vin, charge_date, level, charging_rate, autonomy)) - except IntegrityError: - logger.debug("level already stored") - if stop_at is not None: - conn.execute("INSERT INTO battery(start_at,start_level,charging_mode,VIN) VALUES(?,?,?,?)", - (charge_date, level, charging_mode, car.vin)) - Ecomix.get_data_from_co2_signal(latitude, longitude, country_code) - else: - try: - start_at, stop_at, start_level = conn.execute( - "SELECT start_at, stop_at, start_level from battery WHERE VIN=? ORDER BY start_at DESC limit 1", - (car.vin,)).fetchone() - in_progress = stop_at is None - except TypeError: - logger.debug("battery table is probably empty :", exc_info=True) - in_progress = False - if in_progress: - co2_per_kw = Ecomix.get_co2_per_kw(start_at, charge_date, latitude, longitude, country_code) - consumption_kw = (level - start_level) / 100 * car.battery_power - Charging.update_chargings(conn, start_at, charge_date, level, co2_per_kw, consumption_kw, car.vin) - conn.commit() - conn.close() diff --git a/libs/elec_price.py b/libs/elec_price.py deleted file mode 100644 index a0147ed..0000000 --- a/libs/elec_price.py +++ /dev/null @@ -1,107 +0,0 @@ -from datetime import datetime, timezone, timedelta -import configparser -from statistics import mean, StatisticsError - -from mylogger import logger - - - -def set_number(value): - try: - return float(value) - except (ValueError, TypeError): - return None - - -def utc_to_local(utc_dt): - return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None) - - -class ElecPrice: - currency = "" - CONFIG_FILENAME = "config.ini" - - def __init__(self, day_price, night_price=None, nights_hours=None): - self.day_price = set_number(day_price) - self.night_price = set_number(night_price) - self.nights_hour = None - self.set_night_hour(nights_hours) - self.config_filename = ElecPrice.CONFIG_FILENAME - - def set_night_hour(self, value): - if value is not None and isinstance(value, list): - self.nights_hour = [] - for hours in value: - self.nights_hour.append(list(map(int, hours))) - - @staticmethod - def compare_hour(date: datetime, hour, minute): - if date.hour < hour: - return False - if date.hour == hour and date.minute < minute: - return False - return True - - def get_instant_price(self, date): - local_date = utc_to_local(date) - if self.night_price is None: - return self.day_price - if self.compare_hour(local_date, self.nights_hour[0][0], self.nights_hour[0][1]) or \ - not self.compare_hour(local_date, self.nights_hour[1][0], self.nights_hour[1][1]): - return self.night_price - return self.day_price - - def get_price(self, start, end, consumption): - prices = [] - date = start - res = None - if not (start is None or end is None): - while date < end: - prices.append(self.get_instant_price(date)) - date = date + timedelta(minutes=30) - try: - res = round(consumption * mean(prices), 2) - except (TypeError, StatisticsError): - logger.error("Can't get_price of charge, check config") - return res - - def is_enable(self): - return self.day_price is not None - - @staticmethod - def read_config(name=None): - if name is None: - name = ElecPrice.CONFIG_FILENAME - config = configparser.ConfigParser() - if len(config.read(name)) == 0: - ElecPrice.write_default_config(name) - config.read(name) - elec_config = config["Electricity config"] - if len(elec_config["night price"]) > 0: - night_hours = [] - night_price = elec_config["night price"] - for hour in [elec_config["night hour start"], elec_config["night hour end"]]: - night_hours.append(hour.split("h")) - else: - night_hours = None - night_price = None - ElecPrice.currency = config["General"]["currency"] - return ElecPrice(elec_config["day price"], night_price, night_hours) - - @staticmethod - def write_default_config(name=None): - if name is None: - name = ElecPrice.CONFIG_FILENAME - config = configparser.ConfigParser() - config["General"] = { - "currency": "€" - } - config["Electricity config"] = { - "day price": "", - "night price": "", - "night hour start": "", - "night hour end": "" - } - - with open(name, "w") as f: - config.write(f) diff --git a/libs/utils.py b/libs/utils.py deleted file mode 100644 index 9db078e..0000000 --- a/libs/utils.py +++ /dev/null @@ -1,74 +0,0 @@ -from functools import wraps -from threading import Semaphore, Timer -import socket - -import requests -from typing import List - -from mylogger import logger - - -def get_temp(latitude: str, longitude: str, api_key: str) -> float: - try: - if not (latitude is None or longitude is None or api_key is None): - weather_rep = requests.get("https://api.openweathermap.org/data/2.5/onecall", - params={"lat": latitude, "lon": longitude, - "exclude": "minutely,hourly,daily,alerts", - "appid": api_key, - "units": "metric"}) - temp = weather_rep.json()["current"]["temp"] - logger.debug("Temperature :%fc", temp) - return temp - except ConnectionError: - logger.error("Can't connect to openweathermap :", exc_info=True) - except KeyError: - logger.error("Unable to get temperature from openweathermap :", exc_info=True) - return None - - -class RateLimitException(Exception): - pass - - -def rate_limit(limit, every): - def limit_decorator(func): - semaphore = Semaphore(limit) - - @wraps(func) - def wrapper(*args, **kwargs): - if semaphore.acquire(blocking=False): - try: - return func(*args, **kwargs) - finally: # don't catch but ensure semaphore release - timer = Timer(every, semaphore.release) - timer.setDaemon(True) # allows the timer to be canceled on exit - timer.start() - else: - raise RateLimitException - - return wrapper - - return limit_decorator - - -def is_port_in_use(ip, port): - with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: - return s.connect_ex((ip, port)) == 0 - - -def parse_hour(s): - s = s[2:] - separators = ("H", "M", "S") - res: List[int] = [] - for sep in separators: - if sep in s: - n, s = s.split(sep) - else: - n = 0 - res.append(int(n)) - if s.isnumeric(): - res.append(int(s)) - break - if len(res) == 2: - res.append(0) - return res diff --git a/otp/__init__.py b/otp/__init__.py deleted file mode 100644 index 43972af..0000000 --- a/otp/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from .otp import Otp diff --git a/psa-car-controller.service b/psa-car-controller.service index f251332..084b907 100644 --- a/psa-car-controller.service +++ b/psa-car-controller.service @@ -4,7 +4,7 @@ Description=PSA Controller After=network-online.target [Service] -ExecStart=/opt/psa_car_controller/server.py -c -r -d +ExecStart=/opt/psa_car_controller/__main__.py -c -r -d Restart=on-failure RestartSec=1m Environment=PYTHONUNBUFFERED=true diff --git a/server.py b/psa-car-controller/__main__.py similarity index 55% rename from server.py rename to psa-car-controller/__main__.py index 905e20c..80eff8f 100755 --- a/server.py +++ b/psa-car-controller/__main__.py @@ -1,28 +1,28 @@ #!/usr/bin/env python3 +import logging import os import sys from threading import Thread -from libs.requirements import TestRequirements - DIR = os.path.dirname(os.path.realpath(__file__)) if sys.version_info < (3, 6): raise RuntimeError("This application requires Python 3.6+") - -TestRequirements(DIR + "/requirements.txt").test_requirements() - # pylint: disable=wrong-import-position +from psacc.utils.requirements import TestRequirements + +TestRequirements(DIR + "/../requirements.txt").test_requirements() + import web.app -from libs.config import Config -from mylogger import logger +from psacc.application.psa_car_controller import PSACarController + +logger = logging.getLogger(__name__) # noqa: MC0001 if __name__ == "__main__": - conf = Config() - conf.load_app() - args = conf.args + app = PSACarController() + app.load_app() + args = app.args t1 = Thread(target=web.app.start_app, - args=["My car info", args.base_path, logger.level < 20, args.listen, int(args.port)]) - t1.setDaemon(True) + args=["My car info", args.base_path, logger.level < 20, args.listen, int(args.port)], daemon=True) t1.start() t1.join() diff --git a/test/__init__.py b/psa-car-controller/common/__init__.py similarity index 100% rename from test/__init__.py rename to psa-car-controller/common/__init__.py diff --git a/mylogger.py b/psa-car-controller/common/mylogger.py similarity index 97% rename from mylogger.py rename to psa-car-controller/common/mylogger.py index 27d8248..4847064 100644 --- a/mylogger.py +++ b/psa-car-controller/common/mylogger.py @@ -26,7 +26,7 @@ class CustomLogger(logging.Logger): logging.setLoggerClass(CustomLogger) -logger = logging.getLogger("log") +logger = logging.getLogger() file_handler = RotatingFileHandler(LOG_FILE, 'a', 1000000, 1, encoding='utf8') formatter = logging.Formatter('%(asctime)s :: %(levelname)s :: %(message)s') diff --git a/psa-car-controller/common/utils.py b/psa-car-controller/common/utils.py new file mode 100644 index 0000000..d734139 --- /dev/null +++ b/psa-car-controller/common/utils.py @@ -0,0 +1,46 @@ +from functools import wraps +from threading import Semaphore, Timer +from typing import List + + +def rate_limit(limit, every): + def limit_decorator(func): + semaphore = Semaphore(limit) + + @wraps(func) + def wrapper(*args, **kwargs): + if semaphore.acquire(blocking=False): # pylint: disable=consider-using-with + try: + return func(*args, **kwargs) + finally: # don't catch but ensure semaphore release + timer = Timer(every, semaphore.release) + timer.setDaemon(True) # pylint: disable=deprecated-method + timer.start() + else: + raise RateLimitException + + return wrapper + + return limit_decorator + + +def parse_hour(s): + s = s[2:] + separators = ("H", "M", "S") + res: List[int] = [] + for sep in separators: + if sep in s: + n, s = s.split(sep) + else: + n = 0 + res.append(int(n)) + if s.isnumeric(): + res.append(int(s)) + break + if len(res) == 2: + res.append(0) + return res + + +class RateLimitException(Exception): + pass diff --git a/libs/psa/AccountInformation.py b/psa-car-controller/psa/AccountInformation.py similarity index 89% rename from libs/psa/AccountInformation.py rename to psa-car-controller/psa/AccountInformation.py index 9c8945a..48de9f6 100644 --- a/libs/psa/AccountInformation.py +++ b/psa-car-controller/psa/AccountInformation.py @@ -1,4 +1,4 @@ -from libs.psa.constants import MQTT_BRANDCODE +from psa.constants import MQTT_BRANDCODE class AccountInformation: diff --git a/libs/psa/RemoteClient.py b/psa-car-controller/psa/RemoteClient.py similarity index 94% rename from libs/psa/RemoteClient.py rename to psa-car-controller/psa/RemoteClient.py index 502877a..8eb885f 100644 --- a/libs/psa/RemoteClient.py +++ b/psa-car-controller/psa/RemoteClient.py @@ -1,4 +1,5 @@ import json +import logging import threading from datetime import datetime from os import environ @@ -7,15 +8,16 @@ from time import sleep import paho.mqtt.client as mqtt from requests import RequestException -from libs.car import Cars -from libs.psa.AccountInformation import AccountInformation -from libs.psa.RemoteCredentials import RemoteCredentials -from libs.psa.constants import INPROGRESS, DEFAULT_PRECONDITIONING_PROGRAM, IMMEDIATE_CHARGE, DELAYED_CHARGE, REMOTE_URL -from libs.psa.mqtt_request import MQTTRequest -from libs.psa.oauth import OpenIdCredentialManager -from libs.utils import RateLimitException, rate_limit, parse_hour -from mylogger import logger -from otp.otp import ConfigException, save_otp, load_otp +from psacc.model.car import Cars +from psa.AccountInformation import AccountInformation +from psa.RemoteCredentials import RemoteCredentials +from psa.constants import INPROGRESS, DEFAULT_PRECONDITIONING_PROGRAM, IMMEDIATE_CHARGE, DELAYED_CHARGE, REMOTE_URL +from psa.mqtt_request import MQTTRequest +from psa.oauth import OpenIdCredentialManager +from common.utils import RateLimitException, rate_limit, parse_hour +from psa.otp.otp import ConfigException, save_otp, load_otp + +logger = logging.getLogger(__name__) MQTT_SERVER = "mwa.mpsa.com" MQTT_RESP_TOPIC = "psa/RemoteServices/to/cid/" @@ -57,10 +59,9 @@ class RemoteClient: else: logger.warning(mqtt.error_string(result_code)) - def __on_mqtt_message(self, client, userdata, msg): + def __on_mqtt_message(self, client, userdata, msg): # pylint: disable=unused-argument try: logger.info("mqtt msg received: %s %s", msg.topic, msg.payload) - logger.debug("client: %s userdata: %s", client, userdata) data = json.loads(msg.payload) charge_info = None if msg.topic.startswith(MQTT_RESP_TOPIC): @@ -118,7 +119,7 @@ class RemoteClient: except RateLimitException: logger.exception("__keep_mqtt") t = threading.Timer(timeout, self.__keep_mqtt) - t.setDaemon(True) + t.setDaemon(True) # pylint: disable=deprecated-method t.start() def veh_charge_request(self, vin, hour, minute, charge_type): diff --git a/libs/psa/RemoteCredentials.py b/psa-car-controller/psa/RemoteCredentials.py similarity index 100% rename from libs/psa/RemoteCredentials.py rename to psa-car-controller/psa/RemoteCredentials.py diff --git a/web/__init__.py b/psa-car-controller/psa/__init__.py similarity index 100% rename from web/__init__.py rename to psa-car-controller/psa/__init__.py diff --git a/psa-car-controller/psa/connected_car_api/__init__.py b/psa-car-controller/psa/connected_car_api/__init__.py new file mode 100644 index 0000000..769dafd --- /dev/null +++ b/psa-car-controller/psa/connected_car_api/__init__.py @@ -0,0 +1,155 @@ +# coding: utf-8 + +# flake8: noqa + +""" + Groupe PSA Connected Car - WEB API B2C + + *PSA B2C Connected Car API* # Introduction This is the description of the *Groupe PSA Connected Car V2 API*. The speccification is is based on **OpenAPI Specification version 3** and can be displayed via [ReDoc](https://github.com/Rebilly/ReDoc)a or [Swagger](http://swagger.io). This API allows applications to fetch data from the connected Vehicles data platform. # Authentication PSA Connected Car APIs uses the [OAuth 2.0](https://tools.ietf.org/html/rfc6749) protocol for authentication and Authorization. any application require a valid [Access Token](https://tools.ietf.org/html/rfc6749#section-1.4) to access to user data. # Errors Error codes returned by all REST APIs comply with the standard. Nevertheless, PSA Services (callers) need to have more complete data structures (even when the answer is not Http-OK) to better detail the type of error by providing application code, message and a debugging code(for investigation purposes). The http code of the response is managed by the protocol itself (in the header). **Errors are returned as a generic error response:** * ```xError``` object model. # noqa: E501 + + OpenAPI spec version: 4.0 + + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + + +from __future__ import absolute_import + +# import apis into sdk package +from psa.connected_car_api.api.trips_api import TripsApi +from psa.connected_car_api.api.user_api import UserApi +from psa.connected_car_api.api.vehicles_api import VehiclesApi + +# import ApiClient +from psa.connected_car_api.api_client import ApiClient +from psa.connected_car_api.configuration import Configuration +# import models into sdk package +from psa.connected_car_api.models.adas import Adas +from psa.connected_car_api.models.adas_park_assist import AdasParkAssist +from psa.connected_car_api.models.alert import Alert +from psa.connected_car_api.models.alert_end_position import AlertEndPosition +from psa.connected_car_api.models.alert_links import AlertLinks +from psa.connected_car_api.models.alert_msg_enum import AlertMsgEnum +from psa.connected_car_api.models.alerts import Alerts +from psa.connected_car_api.models.alerts_embedded import AlertsEmbedded +from psa.connected_car_api.models.battery import Battery +from psa.connected_car_api.models.bounded_program import BoundedProgram +from psa.connected_car_api.models.charging_status_enum import ChargingStatusEnum +from psa.connected_car_api.models.circle_zone import CircleZone +from psa.connected_car_api.models.circle_zone_coordinates import CircleZoneCoordinates +from psa.connected_car_api.models.collection_result import CollectionResult +from psa.connected_car_api.models.collision import Collision +from psa.connected_car_api.models.collision_links import CollisionLinks +from psa.connected_car_api.models.collision_obj import CollisionObj +from psa.connected_car_api.models.collision_obj_front import CollisionObjFront +from psa.connected_car_api.models.collisions import Collisions +from psa.connected_car_api.models.collisions_embedded import CollisionsEmbedded +from psa.connected_car_api.models.created_at_field import CreatedAtField +from psa.connected_car_api.models.data_monitor_trigger import DataMonitorTrigger +from psa.connected_car_api.models.data_trigger import DataTrigger +from psa.connected_car_api.models.default_alert_push import DefaultAlertPush +from psa.connected_car_api.models.default_alert_push_attributes import DefaultAlertPushAttributes +from psa.connected_car_api.models.doors_state import DoorsState +from psa.connected_car_api.models.doors_state_opening import DoorsStateOpening +from psa.connected_car_api.models.e_coaching import ECoaching +from psa.connected_car_api.models.e_coaching_links import ECoachingLinks +from psa.connected_car_api.models.e_coaching_scores import ECoachingScores +from psa.connected_car_api.models.energy import Energy +from psa.connected_car_api.models.energy_battery import EnergyBattery +from psa.connected_car_api.models.energy_battery_health import EnergyBatteryHealth +from psa.connected_car_api.models.energy_charging import EnergyCharging +from psa.connected_car_api.models.engine import Engine +from psa.connected_car_api.models.engine_oil import EngineOil +from psa.connected_car_api.models.environment import Environment +from psa.connected_car_api.models.environment_luminosity import EnvironmentLuminosity +from psa.connected_car_api.models.event import Event +from psa.connected_car_api.models.event_links import EventLinks +from psa.connected_car_api.models.extension import Extension +from psa.connected_car_api.models.extension_type import ExtensionType +from psa.connected_car_api.models.geometry import Geometry +from psa.connected_car_api.models.ignition import Ignition +from psa.connected_car_api.models.index_range import IndexRange +from psa.connected_car_api.models.kinetic import Kinetic +from psa.connected_car_api.models.lighting import Lighting +from psa.connected_car_api.models.link import Link +from psa.connected_car_api.models.maintenance import Maintenance +from psa.connected_car_api.models.maintenance_links import MaintenanceLinks +from psa.connected_car_api.models.maintenance_obj import MaintenanceObj +from psa.connected_car_api.models.monitor import Monitor +from psa.connected_car_api.models.monitor_id import MonitorId +from psa.connected_car_api.models.monitor_links import MonitorLinks +from psa.connected_car_api.models.monitor_parameter import MonitorParameter +from psa.connected_car_api.models.monitor_parameter_trigger_param import MonitorParameterTriggerParam +from psa.connected_car_api.models.monitor_ref import MonitorRef +from psa.connected_car_api.models.monitor_ref_links import MonitorRefLinks +from psa.connected_car_api.models.monitor_status import MonitorStatus +from psa.connected_car_api.models.monitor_status_setter import MonitorStatusSetter +from psa.connected_car_api.models.monitor_subscribe import MonitorSubscribe +from psa.connected_car_api.models.monitor_subscribe_batch_notify import MonitorSubscribeBatchNotify +from psa.connected_car_api.models.monitor_subscribe_retry_policy import MonitorSubscribeRetryPolicy +from psa.connected_car_api.models.monitor_trigger import MonitorTrigger +from psa.connected_car_api.models.monitor_webhook import MonitorWebhook +from psa.connected_car_api.models.monitor_webhook_attributes import MonitorWebhookAttributes +from psa.connected_car_api.models.monitors import Monitors +from psa.connected_car_api.models.monitors_embedded import MonitorsEmbedded +from psa.connected_car_api.models.overall_autonomy import OverallAutonomy +from psa.connected_car_api.models.point import Point +from psa.connected_car_api.models.polygon_zone import PolygonZone +from psa.connected_car_api.models.position import Position +from psa.connected_car_api.models.position_properties import PositionProperties +from psa.connected_car_api.models.preconditioning import Preconditioning +from psa.connected_car_api.models.preconditioning_air_conditioning import PreconditioningAirConditioning +from psa.connected_car_api.models.preconditioning_program import PreconditioningProgram +from psa.connected_car_api.models.privacy import Privacy +from psa.connected_car_api.models.program import Program +from psa.connected_car_api.models.program_occurence import ProgramOccurence +from psa.connected_car_api.models.safety import Safety +from psa.connected_car_api.models.service_type import ServiceType +from psa.connected_car_api.models.status import Status +from psa.connected_car_api.models.status_embedded import StatusEmbedded +from psa.connected_car_api.models.status_extension_type import StatusExtensionType +from psa.connected_car_api.models.status_links import StatusLinks +from psa.connected_car_api.models.tab_links import TabLinks +from psa.connected_car_api.models.telemetry import Telemetry +from psa.connected_car_api.models.telemetry_embedded import TelemetryEmbedded +from psa.connected_car_api.models.telemetry_enum import TelemetryEnum +from psa.connected_car_api.models.telemetry_extension import TelemetryExtension +from psa.connected_car_api.models.telemetry_extension_type import TelemetryExtensionType +from psa.connected_car_api.models.telemetry_message import TelemetryMessage +from psa.connected_car_api.models.telemetry_message_embedded import TelemetryMessageEmbedded +from psa.connected_car_api.models.telemetry_message_vehicle import TelemetryMessageVehicle +from psa.connected_car_api.models.telemetry_message_vehicle_braking_system import TelemetryMessageVehicleBrakingSystem +from psa.connected_car_api.models.telemetry_message_vehicle_transmission import TelemetryMessageVehicleTransmission +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox import TelemetryMessageVehicleTransmissionGearbox +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox_gear import TelemetryMessageVehicleTransmissionGearboxGear +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox_mode import TelemetryMessageVehicleTransmissionGearboxMode +from psa.connected_car_api.models.time_monitor_trigger import TimeMonitorTrigger +from psa.connected_car_api.models.time_range import TimeRange +from psa.connected_car_api.models.time_stamped import TimeStamped +from psa.connected_car_api.models.time_trigger import TimeTrigger +from psa.connected_car_api.models.time_zone_monitor_trigger import TimeZoneMonitorTrigger +from psa.connected_car_api.models.time_zone_trigger import TimeZoneTrigger +from psa.connected_car_api.models.trip import Trip +from psa.connected_car_api.models.trip_avg_consumption import TripAvgConsumption +from psa.connected_car_api.models.trip_links import TripLinks +from psa.connected_car_api.models.trips import Trips +from psa.connected_car_api.models.trips_embedded import TripsEmbedded +from psa.connected_car_api.models.updated_field import UpdatedField +from psa.connected_car_api.models.url import Url +from psa.connected_car_api.models.user import User +from psa.connected_car_api.models.user_embedded import UserEmbedded +from psa.connected_car_api.models.user_links import UserLinks +from psa.connected_car_api.models.vect2_d import Vect2D +from psa.connected_car_api.models.vehicle import Vehicle +from psa.connected_car_api.models.vehicle_engine import VehicleEngine +from psa.connected_car_api.models.vehicle_links import VehicleLinks +from psa.connected_car_api.models.vehicle_odometer import VehicleOdometer +from psa.connected_car_api.models.vehicles import Vehicles +from psa.connected_car_api.models.vehicles_embedded import VehiclesEmbedded +from psa.connected_car_api.models.way_points import WayPoints +from psa.connected_car_api.models.way_points_embedded import WayPointsEmbedded +from psa.connected_car_api.models.x_error import XError +from psa.connected_car_api.models.zone_monitor_trigger import ZoneMonitorTrigger +from psa.connected_car_api.models.zone_trigger import ZoneTrigger +from psa.connected_car_api.models.zone_trigger_place import ZoneTriggerPlace +from psa.connected_car_api.models.zone_trigger_place_center import ZoneTriggerPlaceCenter diff --git a/psa-car-controller/psa/connected_car_api/api/__init__.py b/psa-car-controller/psa/connected_car_api/api/__init__.py new file mode 100644 index 0000000..231613e --- /dev/null +++ b/psa-car-controller/psa/connected_car_api/api/__init__.py @@ -0,0 +1,8 @@ +from __future__ import absolute_import + +# flake8: noqa + +# import apis into api package +from psa.connected_car_api.api.trips_api import TripsApi +from psa.connected_car_api.api.user_api import UserApi +from psa.connected_car_api.api.vehicles_api import VehiclesApi diff --git a/psa_connectedcar/api/trips_api.py b/psa-car-controller/psa/connected_car_api/api/trips_api.py similarity index 99% rename from psa_connectedcar/api/trips_api.py rename to psa-car-controller/psa/connected_car_api/api/trips_api.py index 9d49381..06b8a2f 100644 --- a/psa_connectedcar/api/trips_api.py +++ b/psa-car-controller/psa/connected_car_api/api/trips_api.py @@ -18,7 +18,7 @@ import re # noqa: F401 # python 2 and python 3 compatibility library import six -from psa_connectedcar.api_client import ApiClient +from psa.connected_car_api.api_client import ApiClient class TripsApi(object): diff --git a/psa_connectedcar/api/user_api.py b/psa-car-controller/psa/connected_car_api/api/user_api.py similarity index 98% rename from psa_connectedcar/api/user_api.py rename to psa-car-controller/psa/connected_car_api/api/user_api.py index b6be478..580cc36 100644 --- a/psa_connectedcar/api/user_api.py +++ b/psa-car-controller/psa/connected_car_api/api/user_api.py @@ -18,7 +18,7 @@ import re # noqa: F401 # python 2 and python 3 compatibility library import six -from psa_connectedcar.api_client import ApiClient +from psa.connected_car_api.api_client import ApiClient class UserApi(object): diff --git a/psa_connectedcar/api/vehicles_api.py b/psa-car-controller/psa/connected_car_api/api/vehicles_api.py similarity index 99% rename from psa_connectedcar/api/vehicles_api.py rename to psa-car-controller/psa/connected_car_api/api/vehicles_api.py index aba9e0a..b035a60 100644 --- a/psa_connectedcar/api/vehicles_api.py +++ b/psa-car-controller/psa/connected_car_api/api/vehicles_api.py @@ -18,7 +18,7 @@ import re # noqa: F401 # python 2 and python 3 compatibility library import six -from psa_connectedcar.api_client import ApiClient +from psa.connected_car_api.api_client import ApiClient class VehiclesApi(object): diff --git a/psa_connectedcar/api_client.py b/psa-car-controller/psa/connected_car_api/api_client.py similarity index 99% rename from psa_connectedcar/api_client.py rename to psa-car-controller/psa/connected_car_api/api_client.py index 4eda0c1..e418f81 100644 --- a/psa_connectedcar/api_client.py +++ b/psa-car-controller/psa/connected_car_api/api_client.py @@ -23,9 +23,9 @@ import tempfile import six from six.moves.urllib.parse import quote -from psa_connectedcar.configuration import Configuration -import psa_connectedcar.models -from psa_connectedcar import rest +import psa +from psa.connected_car_api.configuration import Configuration +from psa.connected_car_api import rest class ApiClient(object): @@ -266,7 +266,7 @@ class ApiClient(object): if klass in self.NATIVE_TYPES_MAPPING: klass = self.NATIVE_TYPES_MAPPING[klass] else: - klass = getattr(psa_connectedcar.models, klass) + klass = getattr(psa.connected_car_api.models, klass) if klass in self.PRIMITIVE_TYPES: return self.__deserialize_primitive(data, klass) diff --git a/psa_connectedcar/configuration.py b/psa-car-controller/psa/connected_car_api/configuration.py similarity index 99% rename from psa_connectedcar/configuration.py rename to psa-car-controller/psa/connected_car_api/configuration.py index d83f138..5f02ed1 100644 --- a/psa_connectedcar/configuration.py +++ b/psa-car-controller/psa/connected_car_api/configuration.py @@ -61,7 +61,7 @@ class Configuration(object): # Logging Settings self.logger = {} - self.logger["package_logger"] = logging.getLogger("psa_connectedcar") + self.logger["package_logger"] = logging.getLogger("connected_car_api") self.logger["urllib3_logger"] = logging.getLogger("urllib3") # Log format self.logger_format = '%(asctime)s %(levelname)s %(message)s' diff --git a/psa-car-controller/psa/connected_car_api/models/__init__.py b/psa-car-controller/psa/connected_car_api/models/__init__.py new file mode 100644 index 0000000..1f159ea --- /dev/null +++ b/psa-car-controller/psa/connected_car_api/models/__init__.py @@ -0,0 +1,146 @@ +# coding: utf-8 + +# flake8: noqa +""" + Groupe PSA Connected Car - WEB API B2C + + *PSA B2C Connected Car API* # Introduction This is the description of the *Groupe PSA Connected Car V2 API*. The speccification is is based on **OpenAPI Specification version 3** and can be displayed via [ReDoc](https://github.com/Rebilly/ReDoc)a or [Swagger](http://swagger.io). This API allows applications to fetch data from the connected Vehicles data platform. # Authentication PSA Connected Car APIs uses the [OAuth 2.0](https://tools.ietf.org/html/rfc6749) protocol for authentication and Authorization. any application require a valid [Access Token](https://tools.ietf.org/html/rfc6749#section-1.4) to access to user data. # Errors Error codes returned by all REST APIs comply with the standard. Nevertheless, PSA Services (callers) need to have more complete data structures (even when the answer is not Http-OK) to better detail the type of error by providing application code, message and a debugging code(for investigation purposes). The http code of the response is managed by the protocol itself (in the header). **Errors are returned as a generic error response:** * ```xError``` object model. # noqa: E501 + + OpenAPI spec version: 4.0 + + Generated by: https://github.com/swagger-api/swagger-codegen.git +""" + + +from __future__ import absolute_import + +# import models into model package +from psa.connected_car_api.models.adas import Adas +from psa.connected_car_api.models.adas_park_assist import AdasParkAssist +from psa.connected_car_api.models.alert import Alert +from psa.connected_car_api.models.alert_end_position import AlertEndPosition +from psa.connected_car_api.models.alert_links import AlertLinks +from psa.connected_car_api.models.alert_msg_enum import AlertMsgEnum +from psa.connected_car_api.models.alerts import Alerts +from psa.connected_car_api.models.alerts_embedded import AlertsEmbedded +from psa.connected_car_api.models.battery import Battery +from psa.connected_car_api.models.bounded_program import BoundedProgram +from psa.connected_car_api.models.charging_status_enum import ChargingStatusEnum +from psa.connected_car_api.models.circle_zone import CircleZone +from psa.connected_car_api.models.circle_zone_coordinates import CircleZoneCoordinates +from psa.connected_car_api.models.collection_result import CollectionResult +from psa.connected_car_api.models.collision import Collision +from psa.connected_car_api.models.collision_links import CollisionLinks +from psa.connected_car_api.models.collision_obj import CollisionObj +from psa.connected_car_api.models.collision_obj_front import CollisionObjFront +from psa.connected_car_api.models.collisions import Collisions +from psa.connected_car_api.models.collisions_embedded import CollisionsEmbedded +from psa.connected_car_api.models.created_at_field import CreatedAtField +from psa.connected_car_api.models.data_monitor_trigger import DataMonitorTrigger +from psa.connected_car_api.models.data_trigger import DataTrigger +from psa.connected_car_api.models.default_alert_push import DefaultAlertPush +from psa.connected_car_api.models.default_alert_push_attributes import DefaultAlertPushAttributes +from psa.connected_car_api.models.doors_state import DoorsState +from psa.connected_car_api.models.doors_state_opening import DoorsStateOpening +from psa.connected_car_api.models.e_coaching import ECoaching +from psa.connected_car_api.models.e_coaching_links import ECoachingLinks +from psa.connected_car_api.models.e_coaching_scores import ECoachingScores +from psa.connected_car_api.models.energy import Energy +from psa.connected_car_api.models.energy_battery import EnergyBattery +from psa.connected_car_api.models.energy_battery_health import EnergyBatteryHealth +from psa.connected_car_api.models.energy_charging import EnergyCharging +from psa.connected_car_api.models.engine import Engine +from psa.connected_car_api.models.engine_oil import EngineOil +from psa.connected_car_api.models.environment import Environment +from psa.connected_car_api.models.environment_luminosity import EnvironmentLuminosity +from psa.connected_car_api.models.event import Event +from psa.connected_car_api.models.event_links import EventLinks +from psa.connected_car_api.models.extension import Extension +from psa.connected_car_api.models.extension_type import ExtensionType +from psa.connected_car_api.models.geometry import Geometry +from psa.connected_car_api.models.ignition import Ignition +from psa.connected_car_api.models.index_range import IndexRange +from psa.connected_car_api.models.kinetic import Kinetic +from psa.connected_car_api.models.lighting import Lighting +from psa.connected_car_api.models.link import Link +from psa.connected_car_api.models.maintenance import Maintenance +from psa.connected_car_api.models.maintenance_links import MaintenanceLinks +from psa.connected_car_api.models.maintenance_obj import MaintenanceObj +from psa.connected_car_api.models.monitor import Monitor +from psa.connected_car_api.models.monitor_id import MonitorId +from psa.connected_car_api.models.monitor_links import MonitorLinks +from psa.connected_car_api.models.monitor_parameter import MonitorParameter +from psa.connected_car_api.models.monitor_parameter_trigger_param import MonitorParameterTriggerParam +from psa.connected_car_api.models.monitor_ref import MonitorRef +from psa.connected_car_api.models.monitor_ref_links import MonitorRefLinks +from psa.connected_car_api.models.monitor_status import MonitorStatus +from psa.connected_car_api.models.monitor_status_setter import MonitorStatusSetter +from psa.connected_car_api.models.monitor_subscribe import MonitorSubscribe +from psa.connected_car_api.models.monitor_subscribe_batch_notify import MonitorSubscribeBatchNotify +from psa.connected_car_api.models.monitor_subscribe_retry_policy import MonitorSubscribeRetryPolicy +from psa.connected_car_api.models.monitor_trigger import MonitorTrigger +from psa.connected_car_api.models.monitor_webhook import MonitorWebhook +from psa.connected_car_api.models.monitor_webhook_attributes import MonitorWebhookAttributes +from psa.connected_car_api.models.monitors import Monitors +from psa.connected_car_api.models.monitors_embedded import MonitorsEmbedded +from psa.connected_car_api.models.overall_autonomy import OverallAutonomy +from psa.connected_car_api.models.point import Point +from psa.connected_car_api.models.polygon_zone import PolygonZone +from psa.connected_car_api.models.position import Position +from psa.connected_car_api.models.position_properties import PositionProperties +from psa.connected_car_api.models.preconditioning import Preconditioning +from psa.connected_car_api.models.preconditioning_air_conditioning import PreconditioningAirConditioning +from psa.connected_car_api.models.preconditioning_program import PreconditioningProgram +from psa.connected_car_api.models.privacy import Privacy +from psa.connected_car_api.models.program import Program +from psa.connected_car_api.models.program_occurence import ProgramOccurence +from psa.connected_car_api.models.safety import Safety +from psa.connected_car_api.models.service_type import ServiceType +from psa.connected_car_api.models.status import Status +from psa.connected_car_api.models.status_embedded import StatusEmbedded +from psa.connected_car_api.models.status_extension_type import StatusExtensionType +from psa.connected_car_api.models.status_links import StatusLinks +from psa.connected_car_api.models.tab_links import TabLinks +from psa.connected_car_api.models.telemetry import Telemetry +from psa.connected_car_api.models.telemetry_embedded import TelemetryEmbedded +from psa.connected_car_api.models.telemetry_enum import TelemetryEnum +from psa.connected_car_api.models.telemetry_extension import TelemetryExtension +from psa.connected_car_api.models.telemetry_extension_type import TelemetryExtensionType +from psa.connected_car_api.models.telemetry_message import TelemetryMessage +from psa.connected_car_api.models.telemetry_message_embedded import TelemetryMessageEmbedded +from psa.connected_car_api.models.telemetry_message_vehicle import TelemetryMessageVehicle +from psa.connected_car_api.models.telemetry_message_vehicle_braking_system import TelemetryMessageVehicleBrakingSystem +from psa.connected_car_api.models.telemetry_message_vehicle_transmission import TelemetryMessageVehicleTransmission +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox import TelemetryMessageVehicleTransmissionGearbox +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox_gear import TelemetryMessageVehicleTransmissionGearboxGear +from psa.connected_car_api.models.telemetry_message_vehicle_transmission_gearbox_mode import TelemetryMessageVehicleTransmissionGearboxMode +from psa.connected_car_api.models.time_monitor_trigger import TimeMonitorTrigger +from psa.connected_car_api.models.time_range import TimeRange +from psa.connected_car_api.models.time_stamped import TimeStamped +from psa.connected_car_api.models.time_trigger import TimeTrigger +from psa.connected_car_api.models.time_zone_monitor_trigger import TimeZoneMonitorTrigger +from psa.connected_car_api.models.time_zone_trigger import TimeZoneTrigger +from psa.connected_car_api.models.trip import Trip +from psa.connected_car_api.models.trip_avg_consumption import TripAvgConsumption +from psa.connected_car_api.models.trip_links import TripLinks +from psa.connected_car_api.models.trips import Trips +from psa.connected_car_api.models.trips_embedded import TripsEmbedded +from psa.connected_car_api.models.updated_field import UpdatedField +from psa.connected_car_api.models.url import Url +from psa.connected_car_api.models.user import User +from psa.connected_car_api.models.user_embedded import UserEmbedded +from psa.connected_car_api.models.user_links import UserLinks +from psa.connected_car_api.models.vect2_d import Vect2D +from psa.connected_car_api.models.vehicle import Vehicle +from psa.connected_car_api.models.vehicle_engine import VehicleEngine +from psa.connected_car_api.models.vehicle_links import VehicleLinks +from psa.connected_car_api.models.vehicle_odometer import VehicleOdometer +from psa.connected_car_api.models.vehicles import Vehicles +from psa.connected_car_api.models.vehicles_embedded import VehiclesEmbedded +from psa.connected_car_api.models.way_points import WayPoints +from psa.connected_car_api.models.way_points_embedded import WayPointsEmbedded +from psa.connected_car_api.models.x_error import XError +from psa.connected_car_api.models.zone_monitor_trigger import ZoneMonitorTrigger +from psa.connected_car_api.models.zone_trigger import ZoneTrigger +from psa.connected_car_api.models.zone_trigger_place import ZoneTriggerPlace +from psa.connected_car_api.models.zone_trigger_place_center import ZoneTriggerPlaceCenter diff --git a/psa_connectedcar/models/adas.py b/psa-car-controller/psa/connected_car_api/models/adas.py similarity index 99% rename from psa_connectedcar/models/adas.py rename to psa-car-controller/psa/connected_car_api/models/adas.py index 64996da..c1d10d7 100644 --- a/psa_connectedcar/models/adas.py +++ b/psa-car-controller/psa/connected_car_api/models/adas.py @@ -307,7 +307,7 @@ class Adas(object): def fse(self): """Gets the fse of this Adas. # noqa: E501 - Electric brake service # noqa: E501 + Electric brake application # noqa: E501 :return: The fse of this Adas. # noqa: E501 :rtype: bool @@ -318,7 +318,7 @@ class Adas(object): def fse(self, fse): """Sets the fse of this Adas. - Electric brake service # noqa: E501 + Electric brake application # noqa: E501 :param fse: The fse of this Adas. # noqa: E501 :type: bool diff --git a/psa_connectedcar/models/adas_park_assist.py b/psa-car-controller/psa/connected_car_api/models/adas_park_assist.py similarity index 100% rename from psa_connectedcar/models/adas_park_assist.py rename to psa-car-controller/psa/connected_car_api/models/adas_park_assist.py diff --git a/psa_connectedcar/models/alert.py b/psa-car-controller/psa/connected_car_api/models/alert.py similarity index 100% rename from psa_connectedcar/models/alert.py rename to psa-car-controller/psa/connected_car_api/models/alert.py diff --git a/psa_connectedcar/models/alert_end_position.py b/psa-car-controller/psa/connected_car_api/models/alert_end_position.py similarity index 100% rename from psa_connectedcar/models/alert_end_position.py rename to psa-car-controller/psa/connected_car_api/models/alert_end_position.py diff --git a/psa_connectedcar/models/alert_links.py b/psa-car-controller/psa/connected_car_api/models/alert_links.py similarity index 100% rename from psa_connectedcar/models/alert_links.py rename to psa-car-controller/psa/connected_car_api/models/alert_links.py diff --git a/psa_connectedcar/models/alert_msg_enum.py b/psa-car-controller/psa/connected_car_api/models/alert_msg_enum.py similarity index 100% rename from psa_connectedcar/models/alert_msg_enum.py rename to psa-car-controller/psa/connected_car_api/models/alert_msg_enum.py diff --git a/psa_connectedcar/models/alerts.py b/psa-car-controller/psa/connected_car_api/models/alerts.py similarity index 100% rename from psa_connectedcar/models/alerts.py rename to psa-car-controller/psa/connected_car_api/models/alerts.py diff --git a/psa_connectedcar/models/alerts_embedded.py b/psa-car-controller/psa/connected_car_api/models/alerts_embedded.py similarity index 100% rename from psa_connectedcar/models/alerts_embedded.py rename to psa-car-controller/psa/connected_car_api/models/alerts_embedded.py diff --git a/psa_connectedcar/models/battery.py b/psa-car-controller/psa/connected_car_api/models/battery.py similarity index 100% rename from psa_connectedcar/models/battery.py rename to psa-car-controller/psa/connected_car_api/models/battery.py diff --git a/psa_connectedcar/models/bounded_program.py b/psa-car-controller/psa/connected_car_api/models/bounded_program.py similarity index 100% rename from psa_connectedcar/models/bounded_program.py rename to psa-car-controller/psa/connected_car_api/models/bounded_program.py diff --git a/psa_connectedcar/models/charging_status_enum.py b/psa-car-controller/psa/connected_car_api/models/charging_status_enum.py similarity index 100% rename from psa_connectedcar/models/charging_status_enum.py rename to psa-car-controller/psa/connected_car_api/models/charging_status_enum.py diff --git a/psa_connectedcar/models/circle_zone.py b/psa-car-controller/psa/connected_car_api/models/circle_zone.py similarity index 100% rename from psa_connectedcar/models/circle_zone.py rename to psa-car-controller/psa/connected_car_api/models/circle_zone.py diff --git a/psa_connectedcar/models/circle_zone_coordinates.py b/psa-car-controller/psa/connected_car_api/models/circle_zone_coordinates.py similarity index 100% rename from psa_connectedcar/models/circle_zone_coordinates.py rename to psa-car-controller/psa/connected_car_api/models/circle_zone_coordinates.py diff --git a/psa_connectedcar/models/collection_result.py b/psa-car-controller/psa/connected_car_api/models/collection_result.py similarity index 100% rename from psa_connectedcar/models/collection_result.py rename to psa-car-controller/psa/connected_car_api/models/collection_result.py diff --git a/psa_connectedcar/models/collision.py b/psa-car-controller/psa/connected_car_api/models/collision.py similarity index 100% rename from psa_connectedcar/models/collision.py rename to psa-car-controller/psa/connected_car_api/models/collision.py diff --git a/psa_connectedcar/models/collision_links.py b/psa-car-controller/psa/connected_car_api/models/collision_links.py similarity index 100% rename from psa_connectedcar/models/collision_links.py rename to psa-car-controller/psa/connected_car_api/models/collision_links.py diff --git a/psa_connectedcar/models/collision_obj.py b/psa-car-controller/psa/connected_car_api/models/collision_obj.py similarity index 100% rename from psa_connectedcar/models/collision_obj.py rename to psa-car-controller/psa/connected_car_api/models/collision_obj.py diff --git a/psa_connectedcar/models/collision_obj_front.py b/psa-car-controller/psa/connected_car_api/models/collision_obj_front.py similarity index 100% rename from psa_connectedcar/models/collision_obj_front.py rename to psa-car-controller/psa/connected_car_api/models/collision_obj_front.py diff --git a/psa_connectedcar/models/collisions.py b/psa-car-controller/psa/connected_car_api/models/collisions.py similarity index 100% rename from psa_connectedcar/models/collisions.py rename to psa-car-controller/psa/connected_car_api/models/collisions.py diff --git a/psa_connectedcar/models/collisions_embedded.py b/psa-car-controller/psa/connected_car_api/models/collisions_embedded.py similarity index 100% rename from psa_connectedcar/models/collisions_embedded.py rename to psa-car-controller/psa/connected_car_api/models/collisions_embedded.py diff --git a/psa_connectedcar/models/created_at_field.py b/psa-car-controller/psa/connected_car_api/models/created_at_field.py similarity index 100% rename from psa_connectedcar/models/created_at_field.py rename to psa-car-controller/psa/connected_car_api/models/created_at_field.py diff --git a/psa_connectedcar/models/data_monitor_trigger.py b/psa-car-controller/psa/connected_car_api/models/data_monitor_trigger.py similarity index 100% rename from psa_connectedcar/models/data_monitor_trigger.py rename to psa-car-controller/psa/connected_car_api/models/data_monitor_trigger.py diff --git a/psa_connectedcar/models/data_trigger.py b/psa-car-controller/psa/connected_car_api/models/data_trigger.py similarity index 100% rename from psa_connectedcar/models/data_trigger.py rename to psa-car-controller/psa/connected_car_api/models/data_trigger.py diff --git a/psa_connectedcar/models/default_alert_push.py b/psa-car-controller/psa/connected_car_api/models/default_alert_push.py similarity index 100% rename from psa_connectedcar/models/default_alert_push.py rename to psa-car-controller/psa/connected_car_api/models/default_alert_push.py diff --git a/psa_connectedcar/models/default_alert_push_attributes.py b/psa-car-controller/psa/connected_car_api/models/default_alert_push_attributes.py similarity index 100% rename from psa_connectedcar/models/default_alert_push_attributes.py rename to psa-car-controller/psa/connected_car_api/models/default_alert_push_attributes.py diff --git a/psa_connectedcar/models/doors_state.py b/psa-car-controller/psa/connected_car_api/models/doors_state.py similarity index 100% rename from psa_connectedcar/models/doors_state.py rename to psa-car-controller/psa/connected_car_api/models/doors_state.py diff --git a/psa_connectedcar/models/doors_state_opening.py b/psa-car-controller/psa/connected_car_api/models/doors_state_opening.py similarity index 100% rename from psa_connectedcar/models/doors_state_opening.py rename to psa-car-controller/psa/connected_car_api/models/doors_state_opening.py diff --git a/psa_connectedcar/models/e_coaching.py b/psa-car-controller/psa/connected_car_api/models/e_coaching.py similarity index 100% rename from psa_connectedcar/models/e_coaching.py rename to psa-car-controller/psa/connected_car_api/models/e_coaching.py diff --git a/psa_connectedcar/models/e_coaching_links.py b/psa-car-controller/psa/connected_car_api/models/e_coaching_links.py similarity index 100% rename from psa_connectedcar/models/e_coaching_links.py rename to psa-car-controller/psa/connected_car_api/models/e_coaching_links.py diff --git a/psa_connectedcar/models/e_coaching_scores.py b/psa-car-controller/psa/connected_car_api/models/e_coaching_scores.py similarity index 100% rename from psa_connectedcar/models/e_coaching_scores.py rename to psa-car-controller/psa/connected_car_api/models/e_coaching_scores.py diff --git a/psa_connectedcar/models/energy.py b/psa-car-controller/psa/connected_car_api/models/energy.py similarity index 100% rename from psa_connectedcar/models/energy.py rename to psa-car-controller/psa/connected_car_api/models/energy.py diff --git a/psa_connectedcar/models/energy_battery.py b/psa-car-controller/psa/connected_car_api/models/energy_battery.py similarity index 100% rename from psa_connectedcar/models/energy_battery.py rename to psa-car-controller/psa/connected_car_api/models/energy_battery.py diff --git a/psa_connectedcar/models/energy_battery_health.py b/psa-car-controller/psa/connected_car_api/models/energy_battery_health.py similarity index 100% rename from psa_connectedcar/models/energy_battery_health.py rename to psa-car-controller/psa/connected_car_api/models/energy_battery_health.py diff --git a/psa_connectedcar/models/energy_charging.py b/psa-car-controller/psa/connected_car_api/models/energy_charging.py similarity index 100% rename from psa_connectedcar/models/energy_charging.py rename to psa-car-controller/psa/connected_car_api/models/energy_charging.py diff --git a/psa_connectedcar/models/engine.py b/psa-car-controller/psa/connected_car_api/models/engine.py similarity index 100% rename from psa_connectedcar/models/engine.py rename to psa-car-controller/psa/connected_car_api/models/engine.py diff --git a/psa_connectedcar/models/engine_oil.py b/psa-car-controller/psa/connected_car_api/models/engine_oil.py similarity index 100% rename from psa_connectedcar/models/engine_oil.py rename to psa-car-controller/psa/connected_car_api/models/engine_oil.py diff --git a/psa_connectedcar/models/environment.py b/psa-car-controller/psa/connected_car_api/models/environment.py similarity index 100% rename from psa_connectedcar/models/environment.py rename to psa-car-controller/psa/connected_car_api/models/environment.py diff --git a/psa_connectedcar/models/environment_luminosity.py b/psa-car-controller/psa/connected_car_api/models/environment_luminosity.py similarity index 100% rename from psa_connectedcar/models/environment_luminosity.py rename to psa-car-controller/psa/connected_car_api/models/environment_luminosity.py diff --git a/psa_connectedcar/models/event.py b/psa-car-controller/psa/connected_car_api/models/event.py similarity index 100% rename from psa_connectedcar/models/event.py rename to psa-car-controller/psa/connected_car_api/models/event.py diff --git a/psa_connectedcar/models/event_links.py b/psa-car-controller/psa/connected_car_api/models/event_links.py similarity index 100% rename from psa_connectedcar/models/event_links.py rename to psa-car-controller/psa/connected_car_api/models/event_links.py diff --git a/psa_connectedcar/models/extension.py b/psa-car-controller/psa/connected_car_api/models/extension.py similarity index 100% rename from psa_connectedcar/models/extension.py rename to psa-car-controller/psa/connected_car_api/models/extension.py diff --git a/psa_connectedcar/models/extension_type.py b/psa-car-controller/psa/connected_car_api/models/extension_type.py similarity index 100% rename from psa_connectedcar/models/extension_type.py rename to psa-car-controller/psa/connected_car_api/models/extension_type.py diff --git a/psa_connectedcar/models/geometry.py b/psa-car-controller/psa/connected_car_api/models/geometry.py similarity index 100% rename from psa_connectedcar/models/geometry.py rename to psa-car-controller/psa/connected_car_api/models/geometry.py diff --git a/psa_connectedcar/models/ignition.py b/psa-car-controller/psa/connected_car_api/models/ignition.py similarity index 100% rename from psa_connectedcar/models/ignition.py rename to psa-car-controller/psa/connected_car_api/models/ignition.py diff --git a/psa_connectedcar/models/index_range.py b/psa-car-controller/psa/connected_car_api/models/index_range.py similarity index 100% rename from psa_connectedcar/models/index_range.py rename to psa-car-controller/psa/connected_car_api/models/index_range.py diff --git a/psa_connectedcar/models/kinetic.py b/psa-car-controller/psa/connected_car_api/models/kinetic.py similarity index 100% rename from psa_connectedcar/models/kinetic.py rename to psa-car-controller/psa/connected_car_api/models/kinetic.py diff --git a/psa_connectedcar/models/lighting.py b/psa-car-controller/psa/connected_car_api/models/lighting.py similarity index 100% rename from psa_connectedcar/models/lighting.py rename to psa-car-controller/psa/connected_car_api/models/lighting.py diff --git a/psa_connectedcar/models/link.py b/psa-car-controller/psa/connected_car_api/models/link.py similarity index 100% rename from psa_connectedcar/models/link.py rename to psa-car-controller/psa/connected_car_api/models/link.py diff --git a/psa_connectedcar/models/maintenance.py b/psa-car-controller/psa/connected_car_api/models/maintenance.py similarity index 100% rename from psa_connectedcar/models/maintenance.py rename to psa-car-controller/psa/connected_car_api/models/maintenance.py diff --git a/psa_connectedcar/models/maintenance_links.py b/psa-car-controller/psa/connected_car_api/models/maintenance_links.py similarity index 100% rename from psa_connectedcar/models/maintenance_links.py rename to psa-car-controller/psa/connected_car_api/models/maintenance_links.py diff --git a/psa_connectedcar/models/maintenance_obj.py b/psa-car-controller/psa/connected_car_api/models/maintenance_obj.py similarity index 100% rename from psa_connectedcar/models/maintenance_obj.py rename to psa-car-controller/psa/connected_car_api/models/maintenance_obj.py diff --git a/psa_connectedcar/models/monitor.py b/psa-car-controller/psa/connected_car_api/models/monitor.py similarity index 100% rename from psa_connectedcar/models/monitor.py rename to psa-car-controller/psa/connected_car_api/models/monitor.py diff --git a/psa_connectedcar/models/monitor_id.py b/psa-car-controller/psa/connected_car_api/models/monitor_id.py similarity index 100% rename from psa_connectedcar/models/monitor_id.py rename to psa-car-controller/psa/connected_car_api/models/monitor_id.py diff --git a/psa_connectedcar/models/monitor_links.py b/psa-car-controller/psa/connected_car_api/models/monitor_links.py similarity index 100% rename from psa_connectedcar/models/monitor_links.py rename to psa-car-controller/psa/connected_car_api/models/monitor_links.py diff --git a/psa_connectedcar/models/monitor_parameter.py b/psa-car-controller/psa/connected_car_api/models/monitor_parameter.py similarity index 100% rename from psa_connectedcar/models/monitor_parameter.py rename to psa-car-controller/psa/connected_car_api/models/monitor_parameter.py diff --git a/psa_connectedcar/models/monitor_parameter_trigger_param.py b/psa-car-controller/psa/connected_car_api/models/monitor_parameter_trigger_param.py similarity index 100% rename from psa_connectedcar/models/monitor_parameter_trigger_param.py rename to psa-car-controller/psa/connected_car_api/models/monitor_parameter_trigger_param.py diff --git a/psa_connectedcar/models/monitor_ref.py b/psa-car-controller/psa/connected_car_api/models/monitor_ref.py similarity index 100% rename from psa_connectedcar/models/monitor_ref.py rename to psa-car-controller/psa/connected_car_api/models/monitor_ref.py diff --git a/psa_connectedcar/models/monitor_ref_links.py b/psa-car-controller/psa/connected_car_api/models/monitor_ref_links.py similarity index 100% rename from psa_connectedcar/models/monitor_ref_links.py rename to psa-car-controller/psa/connected_car_api/models/monitor_ref_links.py diff --git a/psa_connectedcar/models/monitor_status.py b/psa-car-controller/psa/connected_car_api/models/monitor_status.py similarity index 100% rename from psa_connectedcar/models/monitor_status.py rename to psa-car-controller/psa/connected_car_api/models/monitor_status.py diff --git a/psa_connectedcar/models/monitor_status_setter.py b/psa-car-controller/psa/connected_car_api/models/monitor_status_setter.py similarity index 100% rename from psa_connectedcar/models/monitor_status_setter.py rename to psa-car-controller/psa/connected_car_api/models/monitor_status_setter.py diff --git a/psa_connectedcar/models/monitor_subscribe.py b/psa-car-controller/psa/connected_car_api/models/monitor_subscribe.py similarity index 100% rename from psa_connectedcar/models/monitor_subscribe.py rename to psa-car-controller/psa/connected_car_api/models/monitor_subscribe.py diff --git a/psa_connectedcar/models/monitor_subscribe_batch_notify.py b/psa-car-controller/psa/connected_car_api/models/monitor_subscribe_batch_notify.py similarity index 100% rename from psa_connectedcar/models/monitor_subscribe_batch_notify.py rename to psa-car-controller/psa/connected_car_api/models/monitor_subscribe_batch_notify.py diff --git a/psa_connectedcar/models/monitor_subscribe_retry_policy.py b/psa-car-controller/psa/connected_car_api/models/monitor_subscribe_retry_policy.py similarity index 100% rename from psa_connectedcar/models/monitor_subscribe_retry_policy.py rename to psa-car-controller/psa/connected_car_api/models/monitor_subscribe_retry_policy.py diff --git a/psa_connectedcar/models/monitor_trigger.py b/psa-car-controller/psa/connected_car_api/models/monitor_trigger.py similarity index 100% rename from psa_connectedcar/models/monitor_trigger.py rename to psa-car-controller/psa/connected_car_api/models/monitor_trigger.py diff --git a/psa_connectedcar/models/monitor_webhook.py b/psa-car-controller/psa/connected_car_api/models/monitor_webhook.py similarity index 100% rename from psa_connectedcar/models/monitor_webhook.py rename to psa-car-controller/psa/connected_car_api/models/monitor_webhook.py diff --git a/psa_connectedcar/models/monitor_webhook_attributes.py b/psa-car-controller/psa/connected_car_api/models/monitor_webhook_attributes.py similarity index 100% rename from psa_connectedcar/models/monitor_webhook_attributes.py rename to psa-car-controller/psa/connected_car_api/models/monitor_webhook_attributes.py diff --git a/psa_connectedcar/models/monitors.py b/psa-car-controller/psa/connected_car_api/models/monitors.py similarity index 100% rename from psa_connectedcar/models/monitors.py rename to psa-car-controller/psa/connected_car_api/models/monitors.py diff --git a/psa_connectedcar/models/monitors_embedded.py b/psa-car-controller/psa/connected_car_api/models/monitors_embedded.py similarity index 100% rename from psa_connectedcar/models/monitors_embedded.py rename to psa-car-controller/psa/connected_car_api/models/monitors_embedded.py diff --git a/psa_connectedcar/models/overall_autonomy.py b/psa-car-controller/psa/connected_car_api/models/overall_autonomy.py similarity index 100% rename from psa_connectedcar/models/overall_autonomy.py rename to psa-car-controller/psa/connected_car_api/models/overall_autonomy.py diff --git a/psa_connectedcar/models/point.py b/psa-car-controller/psa/connected_car_api/models/point.py similarity index 100% rename from psa_connectedcar/models/point.py rename to psa-car-controller/psa/connected_car_api/models/point.py diff --git a/psa_connectedcar/models/polygon_zone.py b/psa-car-controller/psa/connected_car_api/models/polygon_zone.py similarity index 100% rename from psa_connectedcar/models/polygon_zone.py rename to psa-car-controller/psa/connected_car_api/models/polygon_zone.py diff --git a/psa_connectedcar/models/position.py b/psa-car-controller/psa/connected_car_api/models/position.py similarity index 100% rename from psa_connectedcar/models/position.py rename to psa-car-controller/psa/connected_car_api/models/position.py diff --git a/psa_connectedcar/models/position_properties.py b/psa-car-controller/psa/connected_car_api/models/position_properties.py similarity index 100% rename from psa_connectedcar/models/position_properties.py rename to psa-car-controller/psa/connected_car_api/models/position_properties.py diff --git a/psa_connectedcar/models/preconditioning.py b/psa-car-controller/psa/connected_car_api/models/preconditioning.py similarity index 100% rename from psa_connectedcar/models/preconditioning.py rename to psa-car-controller/psa/connected_car_api/models/preconditioning.py diff --git a/psa_connectedcar/models/preconditioning_air_conditioning.py b/psa-car-controller/psa/connected_car_api/models/preconditioning_air_conditioning.py similarity index 100% rename from psa_connectedcar/models/preconditioning_air_conditioning.py rename to psa-car-controller/psa/connected_car_api/models/preconditioning_air_conditioning.py diff --git a/psa_connectedcar/models/preconditioning_program.py b/psa-car-controller/psa/connected_car_api/models/preconditioning_program.py similarity index 100% rename from psa_connectedcar/models/preconditioning_program.py rename to psa-car-controller/psa/connected_car_api/models/preconditioning_program.py diff --git a/psa_connectedcar/models/privacy.py b/psa-car-controller/psa/connected_car_api/models/privacy.py similarity index 100% rename from psa_connectedcar/models/privacy.py rename to psa-car-controller/psa/connected_car_api/models/privacy.py diff --git a/psa_connectedcar/models/program.py b/psa-car-controller/psa/connected_car_api/models/program.py similarity index 100% rename from psa_connectedcar/models/program.py rename to psa-car-controller/psa/connected_car_api/models/program.py diff --git a/psa_connectedcar/models/program_occurence.py b/psa-car-controller/psa/connected_car_api/models/program_occurence.py similarity index 100% rename from psa_connectedcar/models/program_occurence.py rename to psa-car-controller/psa/connected_car_api/models/program_occurence.py diff --git a/psa_connectedcar/models/safety.py b/psa-car-controller/psa/connected_car_api/models/safety.py similarity index 100% rename from psa_connectedcar/models/safety.py rename to psa-car-controller/psa/connected_car_api/models/safety.py diff --git a/psa_connectedcar/models/service_type.py b/psa-car-controller/psa/connected_car_api/models/service_type.py similarity index 100% rename from psa_connectedcar/models/service_type.py rename to psa-car-controller/psa/connected_car_api/models/service_type.py diff --git a/psa_connectedcar/models/status.py b/psa-car-controller/psa/connected_car_api/models/status.py similarity index 100% rename from psa_connectedcar/models/status.py rename to psa-car-controller/psa/connected_car_api/models/status.py diff --git a/psa_connectedcar/models/status_embedded.py b/psa-car-controller/psa/connected_car_api/models/status_embedded.py similarity index 100% rename from psa_connectedcar/models/status_embedded.py rename to psa-car-controller/psa/connected_car_api/models/status_embedded.py diff --git a/psa_connectedcar/models/status_extension_type.py b/psa-car-controller/psa/connected_car_api/models/status_extension_type.py similarity index 100% rename from psa_connectedcar/models/status_extension_type.py rename to psa-car-controller/psa/connected_car_api/models/status_extension_type.py diff --git a/psa_connectedcar/models/status_links.py b/psa-car-controller/psa/connected_car_api/models/status_links.py similarity index 100% rename from psa_connectedcar/models/status_links.py rename to psa-car-controller/psa/connected_car_api/models/status_links.py diff --git a/psa_connectedcar/models/tab_links.py b/psa-car-controller/psa/connected_car_api/models/tab_links.py similarity index 100% rename from psa_connectedcar/models/tab_links.py rename to psa-car-controller/psa/connected_car_api/models/tab_links.py diff --git a/psa_connectedcar/models/telemetry.py b/psa-car-controller/psa/connected_car_api/models/telemetry.py similarity index 100% rename from psa_connectedcar/models/telemetry.py rename to psa-car-controller/psa/connected_car_api/models/telemetry.py diff --git a/psa_connectedcar/models/telemetry_embedded.py b/psa-car-controller/psa/connected_car_api/models/telemetry_embedded.py similarity index 100% rename from psa_connectedcar/models/telemetry_embedded.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_embedded.py diff --git a/psa_connectedcar/models/telemetry_enum.py b/psa-car-controller/psa/connected_car_api/models/telemetry_enum.py similarity index 100% rename from psa_connectedcar/models/telemetry_enum.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_enum.py diff --git a/psa_connectedcar/models/telemetry_extension.py b/psa-car-controller/psa/connected_car_api/models/telemetry_extension.py similarity index 100% rename from psa_connectedcar/models/telemetry_extension.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_extension.py diff --git a/psa_connectedcar/models/telemetry_extension_type.py b/psa-car-controller/psa/connected_car_api/models/telemetry_extension_type.py similarity index 100% rename from psa_connectedcar/models/telemetry_extension_type.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_extension_type.py diff --git a/psa_connectedcar/models/telemetry_message.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message.py similarity index 100% rename from psa_connectedcar/models/telemetry_message.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message.py diff --git a/psa_connectedcar/models/telemetry_message_embedded.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_embedded.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_embedded.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_embedded.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle_braking_system.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_braking_system.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle_braking_system.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_braking_system.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle_transmission.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle_transmission.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox_gear.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox_gear.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox_gear.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox_gear.py diff --git a/psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox_mode.py b/psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox_mode.py similarity index 100% rename from psa_connectedcar/models/telemetry_message_vehicle_transmission_gearbox_mode.py rename to psa-car-controller/psa/connected_car_api/models/telemetry_message_vehicle_transmission_gearbox_mode.py diff --git a/psa_connectedcar/models/time_monitor_trigger.py b/psa-car-controller/psa/connected_car_api/models/time_monitor_trigger.py similarity index 100% rename from psa_connectedcar/models/time_monitor_trigger.py rename to psa-car-controller/psa/connected_car_api/models/time_monitor_trigger.py diff --git a/psa_connectedcar/models/time_range.py b/psa-car-controller/psa/connected_car_api/models/time_range.py similarity index 100% rename from psa_connectedcar/models/time_range.py rename to psa-car-controller/psa/connected_car_api/models/time_range.py diff --git a/psa_connectedcar/models/time_stamped.py b/psa-car-controller/psa/connected_car_api/models/time_stamped.py similarity index 100% rename from psa_connectedcar/models/time_stamped.py rename to psa-car-controller/psa/connected_car_api/models/time_stamped.py diff --git a/psa_connectedcar/models/time_trigger.py b/psa-car-controller/psa/connected_car_api/models/time_trigger.py similarity index 100% rename from psa_connectedcar/models/time_trigger.py rename to psa-car-controller/psa/connected_car_api/models/time_trigger.py diff --git a/psa_connectedcar/models/time_zone_monitor_trigger.py b/psa-car-controller/psa/connected_car_api/models/time_zone_monitor_trigger.py similarity index 100% rename from psa_connectedcar/models/time_zone_monitor_trigger.py rename to psa-car-controller/psa/connected_car_api/models/time_zone_monitor_trigger.py diff --git a/psa_connectedcar/models/time_zone_trigger.py b/psa-car-controller/psa/connected_car_api/models/time_zone_trigger.py similarity index 100% rename from psa_connectedcar/models/time_zone_trigger.py rename to psa-car-controller/psa/connected_car_api/models/time_zone_trigger.py diff --git a/psa_connectedcar/models/trip.py b/psa-car-controller/psa/connected_car_api/models/trip.py similarity index 100% rename from psa_connectedcar/models/trip.py rename to psa-car-controller/psa/connected_car_api/models/trip.py diff --git a/psa_connectedcar/models/trip_avg_consumption.py b/psa-car-controller/psa/connected_car_api/models/trip_avg_consumption.py similarity index 100% rename from psa_connectedcar/models/trip_avg_consumption.py rename to psa-car-controller/psa/connected_car_api/models/trip_avg_consumption.py diff --git a/psa_connectedcar/models/trip_links.py b/psa-car-controller/psa/connected_car_api/models/trip_links.py similarity index 100% rename from psa_connectedcar/models/trip_links.py rename to psa-car-controller/psa/connected_car_api/models/trip_links.py diff --git a/psa_connectedcar/models/trips.py b/psa-car-controller/psa/connected_car_api/models/trips.py similarity index 100% rename from psa_connectedcar/models/trips.py rename to psa-car-controller/psa/connected_car_api/models/trips.py diff --git a/psa_connectedcar/models/trips_embedded.py b/psa-car-controller/psa/connected_car_api/models/trips_embedded.py similarity index 100% rename from psa_connectedcar/models/trips_embedded.py rename to psa-car-controller/psa/connected_car_api/models/trips_embedded.py diff --git a/psa_connectedcar/models/updated_field.py b/psa-car-controller/psa/connected_car_api/models/updated_field.py similarity index 100% rename from psa_connectedcar/models/updated_field.py rename to psa-car-controller/psa/connected_car_api/models/updated_field.py diff --git a/psa_connectedcar/models/url.py b/psa-car-controller/psa/connected_car_api/models/url.py similarity index 100% rename from psa_connectedcar/models/url.py rename to psa-car-controller/psa/connected_car_api/models/url.py diff --git a/psa_connectedcar/models/user.py b/psa-car-controller/psa/connected_car_api/models/user.py similarity index 100% rename from psa_connectedcar/models/user.py rename to psa-car-controller/psa/connected_car_api/models/user.py diff --git a/psa_connectedcar/models/user_embedded.py b/psa-car-controller/psa/connected_car_api/models/user_embedded.py similarity index 100% rename from psa_connectedcar/models/user_embedded.py rename to psa-car-controller/psa/connected_car_api/models/user_embedded.py diff --git a/psa_connectedcar/models/user_links.py b/psa-car-controller/psa/connected_car_api/models/user_links.py similarity index 100% rename from psa_connectedcar/models/user_links.py rename to psa-car-controller/psa/connected_car_api/models/user_links.py diff --git a/psa_connectedcar/models/vect2_d.py b/psa-car-controller/psa/connected_car_api/models/vect2_d.py similarity index 100% rename from psa_connectedcar/models/vect2_d.py rename to psa-car-controller/psa/connected_car_api/models/vect2_d.py diff --git a/psa_connectedcar/models/vehicle.py b/psa-car-controller/psa/connected_car_api/models/vehicle.py similarity index 100% rename from psa_connectedcar/models/vehicle.py rename to psa-car-controller/psa/connected_car_api/models/vehicle.py diff --git a/psa_connectedcar/models/vehicle_engine.py b/psa-car-controller/psa/connected_car_api/models/vehicle_engine.py similarity index 100% rename from psa_connectedcar/models/vehicle_engine.py rename to psa-car-controller/psa/connected_car_api/models/vehicle_engine.py diff --git a/psa_connectedcar/models/vehicle_links.py b/psa-car-controller/psa/connected_car_api/models/vehicle_links.py similarity index 100% rename from psa_connectedcar/models/vehicle_links.py rename to psa-car-controller/psa/connected_car_api/models/vehicle_links.py diff --git a/psa_connectedcar/models/vehicle_odometer.py b/psa-car-controller/psa/connected_car_api/models/vehicle_odometer.py similarity index 100% rename from psa_connectedcar/models/vehicle_odometer.py rename to psa-car-controller/psa/connected_car_api/models/vehicle_odometer.py diff --git a/psa_connectedcar/models/vehicles.py b/psa-car-controller/psa/connected_car_api/models/vehicles.py similarity index 100% rename from psa_connectedcar/models/vehicles.py rename to psa-car-controller/psa/connected_car_api/models/vehicles.py diff --git a/psa_connectedcar/models/vehicles_embedded.py b/psa-car-controller/psa/connected_car_api/models/vehicles_embedded.py similarity index 100% rename from psa_connectedcar/models/vehicles_embedded.py rename to psa-car-controller/psa/connected_car_api/models/vehicles_embedded.py diff --git a/psa_connectedcar/models/way_points.py b/psa-car-controller/psa/connected_car_api/models/way_points.py similarity index 100% rename from psa_connectedcar/models/way_points.py rename to psa-car-controller/psa/connected_car_api/models/way_points.py diff --git a/psa_connectedcar/models/way_points_embedded.py b/psa-car-controller/psa/connected_car_api/models/way_points_embedded.py similarity index 100% rename from psa_connectedcar/models/way_points_embedded.py rename to psa-car-controller/psa/connected_car_api/models/way_points_embedded.py diff --git a/psa_connectedcar/models/x_error.py b/psa-car-controller/psa/connected_car_api/models/x_error.py similarity index 100% rename from psa_connectedcar/models/x_error.py rename to psa-car-controller/psa/connected_car_api/models/x_error.py diff --git a/psa_connectedcar/models/zone_monitor_trigger.py b/psa-car-controller/psa/connected_car_api/models/zone_monitor_trigger.py similarity index 100% rename from psa_connectedcar/models/zone_monitor_trigger.py rename to psa-car-controller/psa/connected_car_api/models/zone_monitor_trigger.py diff --git a/psa_connectedcar/models/zone_trigger.py b/psa-car-controller/psa/connected_car_api/models/zone_trigger.py similarity index 100% rename from psa_connectedcar/models/zone_trigger.py rename to psa-car-controller/psa/connected_car_api/models/zone_trigger.py diff --git a/psa_connectedcar/models/zone_trigger_place.py b/psa-car-controller/psa/connected_car_api/models/zone_trigger_place.py similarity index 100% rename from psa_connectedcar/models/zone_trigger_place.py rename to psa-car-controller/psa/connected_car_api/models/zone_trigger_place.py diff --git a/psa_connectedcar/models/zone_trigger_place_center.py b/psa-car-controller/psa/connected_car_api/models/zone_trigger_place_center.py similarity index 100% rename from psa_connectedcar/models/zone_trigger_place_center.py rename to psa-car-controller/psa/connected_car_api/models/zone_trigger_place_center.py diff --git a/psa_connectedcar/rest.py b/psa-car-controller/psa/connected_car_api/rest.py similarity index 100% rename from psa_connectedcar/rest.py rename to psa-car-controller/psa/connected_car_api/rest.py diff --git a/libs/psa/constants.py b/psa-car-controller/psa/constants.py similarity index 100% rename from libs/psa/constants.py rename to psa-car-controller/psa/constants.py diff --git a/libs/psa/mqtt_request.py b/psa-car-controller/psa/mqtt_request.py similarity index 84% rename from libs/psa/mqtt_request.py rename to psa-car-controller/psa/mqtt_request.py index 0eff1b1..fc7e85a 100644 --- a/libs/psa/mqtt_request.py +++ b/psa-car-controller/psa/mqtt_request.py @@ -2,7 +2,7 @@ import json from datetime import datetime, timedelta from uuid import uuid4 -from libs.psa.constants import PSA_DATE_FORMAT, PSA_CORRELATION_DATE_FORMAT +from psa.constants import PSA_DATE_FORMAT, PSA_CORRELATION_DATE_FORMAT MQTT_REQ_TOPIC = "psa/RemoteServices/from/cid/" @@ -25,8 +25,8 @@ class MQTTRequest: date = datetime.utcnow() date_str = date.strftime(PSA_DATE_FORMAT) self.data = {"access_token": remote_access_token, "customer_id": self.customer_id, - "correlation_id": self.__gen_correlation_id(date), "req_date": date_str, "vin": self.vin, - "req_parameters": self.req_parameters} + "correlation_id": self.__gen_correlation_id(date), "req_date": date_str, "vin": self.vin, + "req_parameters": self.req_parameters} return self.data def is_expired(self): diff --git a/libs/psa/oauth.py b/psa-car-controller/psa/oauth.py similarity index 93% rename from libs/psa/oauth.py rename to psa-car-controller/psa/oauth.py index 2480046..2f46a46 100644 --- a/libs/psa/oauth.py +++ b/psa-car-controller/psa/oauth.py @@ -1,14 +1,16 @@ +import logging from http import HTTPStatus from typing import Optional from oauth2_client.credentials_manager import CredentialManager, ServiceInformation from requests import Response, RequestException -import psa_connectedcar as psac -from libs.utils import rate_limit -from mylogger import logger -from psa_connectedcar import ApiClient -from psa_connectedcar.rest import ApiException +from common.utils import rate_limit +from psa import connected_car_api +from psa.connected_car_api import ApiClient +from psa.connected_car_api.rest import ApiException + +logger = logging.getLogger(__name__) class OpenIdCredentialManager(CredentialManager): @@ -53,7 +55,7 @@ class OpenIdCredentialManager(CredentialManager): return False -class Oauth2PSACCApiConfig(psac.Configuration): +class Oauth2PSACCApiConfig(connected_car_api.Configuration): def __init__(self): super().__init__() self.refresh_callback = lambda: True diff --git a/psa-car-controller/psa/otp/__init__.py b/psa-car-controller/psa/otp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/otp/load.py b/psa-car-controller/psa/otp/load.py similarity index 97% rename from otp/load.py rename to psa-car-controller/psa/otp/load.py index 1ca1c85..29eb8cc 100644 --- a/otp/load.py +++ b/psa-car-controller/psa/otp/load.py @@ -16,8 +16,8 @@ DEFAULT_VERSION = "529" def filter_load(string: str): return string.replace("&", "&") -# pylint: disable=invalid-name,too-many-instance-attributes,too-many-branches,too-many-statements class IWData: + # pylint: disable=invalid-name,too-many-branches,too-many-statements def __init__(self, IW): self.IW = IW self.tokenizer = Tokenizer(DEFAULT_TOKEN) @@ -116,7 +116,6 @@ class IWData: self.mustupgrade = False self.datatouch = 0 - # pylint: disable=attribute-defined-outside-init def synchro(self, ixml: dict, key): aes_cipher = AES.new(bytes.fromhex(key), AES.MODE_ECB) value = ixml.get("id") diff --git a/otp/oaep.py b/psa-car-controller/psa/otp/oaep.py similarity index 100% rename from otp/oaep.py rename to psa-car-controller/psa/otp/oaep.py diff --git a/otp/otp.py b/psa-car-controller/psa/otp/otp.py similarity index 97% rename from otp/otp.py rename to psa-car-controller/psa/otp/otp.py index 9db251d..196b88a 100644 --- a/otp/otp.py +++ b/psa-car-controller/psa/otp/otp.py @@ -1,4 +1,5 @@ import hashlib +import logging import pickle from secrets import token_hex, token_bytes from math import ceil @@ -10,14 +11,12 @@ from Cryptodome.Cipher import AES from Cryptodome.PublicKey import RSA from Cryptodome import Hash -from mylogger import logger - from . import oaep from .load import IWData - # pylint: disable=invalid-name CONFIG_NAME = "otp.bin" +logger = logging.getLogger(__name__) def etree_to_dict(t): @@ -306,12 +305,7 @@ def save_otp(obj, filename="otp.bin"): class RenameUnpickler(pickle.Unpickler): def find_class(self, module, name): - renamed_module = module - if module == 'otp.Otp': - renamed_module = "otp.otp" - elif module == 'otp.Tokenizer': - renamed_module = "otp.tokenizer" - + renamed_module = "psa."+module.lower() return super().find_class(renamed_module, name) @@ -320,7 +314,8 @@ def load_otp(filename=CONFIG_NAME): with open(filename, 'rb') as input_file: try: return pickle.load(input_file) - except ModuleNotFoundError: + except ModuleNotFoundError as ex: + logger.debug(ex, exc_info=True) return RenameUnpickler(input_file).load() except FileNotFoundError: logger.debug("", exc_info=True) diff --git a/otp/tokenizer.py b/psa-car-controller/psa/otp/tokenizer.py similarity index 100% rename from otp/tokenizer.py rename to psa-car-controller/psa/otp/tokenizer.py diff --git a/libs/psa/setup/apk_parser.py b/psa-car-controller/psa/setup/apk_parser.py similarity index 98% rename from libs/psa/setup/apk_parser.py rename to psa-car-controller/psa/setup/apk_parser.py index 9613209..9b5f594 100644 --- a/libs/psa/setup/apk_parser.py +++ b/psa-car-controller/psa/setup/apk_parser.py @@ -6,7 +6,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.serialization import pkcs12 -from libs.psa.constants import BRAND +from psa.constants import BRAND class ApkParser: diff --git a/libs/psa/setup/app_decoder.py b/psa-car-controller/psa/setup/app_decoder.py similarity index 88% rename from libs/psa/setup/app_decoder.py rename to psa-car-controller/psa/setup/app_decoder.py index e2ff7bf..8408bd4 100755 --- a/libs/psa/setup/app_decoder.py +++ b/psa-car-controller/psa/setup/app_decoder.py @@ -1,15 +1,17 @@ #!/usr/bin/env python3 import json +import logging import traceback import requests -from charge_control import ChargeControl, ChargeControls -from libs.psa.constants import BRAND -from libs.psa.setup.apk_parser import ApkParser -from libs.psa.setup.github import urlretrieve_from_github -from my_psacc import MyPSACC -from mylogger import logger +from psa.constants import BRAND +from psa.setup.apk_parser import ApkParser +from psa.setup.github import urlretrieve_from_github +from psacc.application.psa_client import PSAClient +from psacc.application.charge_control import ChargeControl, ChargeControls + +logger = logging.getLogger(__name__) APP_VERSION = "1.33.0" GITHUB_USER = "flobz" @@ -84,9 +86,9 @@ def firstLaunchConfig(package_name, client_email, client_password, country_code, logger.error(msg) raise Exception(msg) from ex # Psacc - psacc = MyPSACC(None, apk_parser.client_id, apk_parser.client_secret, - None, customer_id, BRAND[package_name]["realm"], - country_code) + psacc = PSAClient(None, apk_parser.client_id, apk_parser.client_secret, + None, customer_id, BRAND[package_name]["realm"], + country_code) psacc.connect(client_email, client_password) psacc.save_config(name=config_prefix + "config.json") res = psacc.get_vehicles() diff --git a/libs/psa/setup/github.py b/psa-car-controller/psa/setup/github.py similarity index 97% rename from libs/psa/setup/github.py rename to psa-car-controller/psa/setup/github.py index 9f60c61..0215853 100644 --- a/libs/psa/setup/github.py +++ b/psa-car-controller/psa/setup/github.py @@ -1,8 +1,9 @@ +import logging from hashlib import sha1 import requests -from mylogger import logger +logger = logging.getLogger(__name__) def get_github_sha_from_file(user, repo, directory, filename): diff --git a/psa-car-controller/psacc/__init__.py b/psa-car-controller/psacc/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/psa-car-controller/psacc/application/__init__.py b/psa-car-controller/psacc/application/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/web/abrp.py b/psa-car-controller/psacc/application/abrp.py similarity index 96% rename from web/abrp.py rename to psa-car-controller/psacc/application/abrp.py index ed721d4..e08ed9d 100644 --- a/web/abrp.py +++ b/psa-car-controller/psacc/application/abrp.py @@ -1,12 +1,13 @@ import json +import logging from datetime import datetime from json.decoder import JSONDecodeError import requests -from libs.car import Car -from mylogger import logger +from psacc.model.car import Car +logger = logging.getLogger(__name__) class Abrp: api_key = "1e28ad14-df16-49f0-97da-364c9154b44a" diff --git a/psa-car-controller/psacc/application/battery_charge_curve.py b/psa-car-controller/psacc/application/battery_charge_curve.py new file mode 100644 index 0000000..78c8f92 --- /dev/null +++ b/psa-car-controller/psacc/application/battery_charge_curve.py @@ -0,0 +1,58 @@ +from statistics import mean + +from typing import List + +from psacc.model.battery_curve import BatteryCurveDto +from psacc.model.car import Car +from psacc.model.charge import Charge +from psacc.repository.db import Database + + +class BatteryChargeCurve: + def __init__(self, level, speed): + self.level = level + self.speed = speed + + @staticmethod + def dto_to_battery_curve(car: Car, charge: Charge, battery_curves_dto: List[BatteryCurveDto]) \ + -> 'List[BatteryChargeCurve]': # pylint: disable=too-many-locals + start_date = charge.start_at + stop_at = charge.stop_at + conn = Database.get_db() + conn.close() + battery_curves = [] + if len(battery_curves_dto) > 0: + battery_capacity = battery_curves_dto[-1].level * car.battery_power / 100 + km_by_kw = 0.8 * battery_curves_dto[-1].autonomy / battery_capacity + start = 0 + speeds = [] + + def speed_in_kw_from_km(battery_curve_dto): + try: + speed = battery_curve_dto.rate / km_by_kw + if speed > 0: + speeds.append(speed) + except (KeyError, TypeError): + pass + + for end in range(1, len(battery_curves_dto)): + start_level = battery_curves_dto[start].level + end_level = battery_curves_dto[end].level + diff_level = end_level - start_level + diff_sec = (battery_curves_dto[end].date - battery_curves_dto[start].date).total_seconds() + speed_in_kw_from_km(battery_curves_dto[end - 1]) + if diff_sec > 0 and diff_level > 3: + speed_in_kw_from_km(battery_curves_dto[end]) + speed = car.get_charge_speed(diff_level, diff_sec) + if len(speeds) > 0: + speed = mean([*speeds, speed]) + speed = round(speed * 2) / 2 + battery_curves.append(BatteryChargeCurve(start_level, speed)) + start = end + speeds = [] + battery_curves.append(BatteryChargeCurve(charge.end_level, 0)) + else: + speed = car.get_charge_speed(charge.end_level - charge.start_level, (stop_at - start_date).total_seconds()) + battery_curves.append(BatteryChargeCurve(charge.start_level, speed)) + battery_curves.append(BatteryChargeCurve(charge.end_level, speed)) + return battery_curves diff --git a/charge_control.py b/psa-car-controller/psacc/application/charge_control.py similarity index 92% rename from charge_control.py rename to psa-car-controller/psacc/application/charge_control.py index 7c0f3dd..7df16de 100644 --- a/charge_control.py +++ b/psa-car-controller/psacc/application/charge_control.py @@ -1,4 +1,5 @@ import json +import logging import threading from copy import copy from datetime import datetime, timedelta @@ -7,16 +8,17 @@ from time import sleep import pytz -from libs.psa.constants import DISCONNECTED, INPROGRESS, FINISHED -from libs.utils import RateLimitException -from my_psacc import MyPSACC -from mylogger import logger +from psa.constants import DISCONNECTED, INPROGRESS, FINISHED +from common.utils import RateLimitException +from .psa_client import PSAClient + +logger = logging.getLogger(__name__) class ChargeControl: MQTT_TIMEOUT = 60 - def __init__(self, psacc: MyPSACC, vin, percentage_threshold, stop_hour): + def __init__(self, psacc: PSAClient, vin, percentage_threshold, stop_hour): self.vin = vin self.percentage_threshold = percentage_threshold self.set_stop_hour(stop_hour) @@ -57,7 +59,7 @@ class ChargeControl: # force update if the car doesn't send info during 10 minutes last_update = self.psacc.vehicles_list.get_car_by_vin(self.vin).get_status().get_energy('Electric').updated_at if quick_refresh: - wakeup_timeout = self.wakeup_timeout/2 + wakeup_timeout = self.wakeup_timeout / 2 else: wakeup_timeout = self.wakeup_timeout if (datetime.utcnow().replace(tzinfo=pytz.UTC) - last_update).total_seconds() > 60 * wakeup_timeout: @@ -90,7 +92,7 @@ class ChargeControl: if next_in_second < self.psacc.info_refresh_rate: periodicity = next_in_second thread = threading.Timer(periodicity, self.process) - thread.setDaemon(True) + thread.setDaemon(True) # pylint: disable=deprecated-method thread.start() else: if self._next_stop_hour is not None and self._next_stop_hour < now: @@ -129,7 +131,7 @@ class ChargeControls(dict): logger.info("save config change") @staticmethod - def load_config(psacc: MyPSACC, name="charge_config.json"): + def load_config(psacc: PSAClient, name="charge_config.json"): with open(name, "r", encoding="utf-8") as file: config_str = file.read() chd = json.loads(config_str) diff --git a/psa-car-controller/psacc/application/charging.py b/psa-car-controller/psacc/application/charging.py new file mode 100644 index 0000000..f3c7a16 --- /dev/null +++ b/psa-car-controller/psacc/application/charging.py @@ -0,0 +1,100 @@ +import logging +from datetime import datetime +from sqlite3 import IntegrityError + +from typing import List + +from .battery_charge_curve import BatteryChargeCurve +from .ecomix import Ecomix + +from psacc.repository.config_repository import ElectricityPriceConfig +from psacc.repository.db import Database +from ..model.car import Car +from ..model.charge import Charge + +logger = logging.getLogger(__name__) + + +class Charging: + elec_price: ElectricityPriceConfig = ElectricityPriceConfig() + + @staticmethod + def get_chargings() -> List[dict]: + conn = Database.get_db() + res = conn.execute("select * from battery ORDER BY start_at").fetchall() + conn.close() + return list(map(dict, res)) + + @staticmethod + def get_battery_curve(conn, charge, car) -> List[BatteryChargeCurve]: + battery_curves_dto = Database.get_battery_curve(conn, charge.start_at, charge.stop_at, charge.vin) + battery_curves = BatteryChargeCurve.dto_to_battery_curve(car, charge, battery_curves_dto) + return battery_curves + + @staticmethod + def set_charge_price(charge, conn, car): + battery_curves = Charging.get_battery_curve(conn, charge, car) + charge.price = Charging.elec_price.get_price(charge, battery_curves) + + @staticmethod + def set_default_price(cars): + if Charging.elec_price.is_enable(): + conn = Database.get_db() + charge_list = Database.get_all_charge_without_price(conn) + for charge in charge_list: + Charging.set_charge_price(charge, conn, cars.get_car_by_vin(charge.vin)) + Database.set_chargings_price(conn, charge) + conn.close() + + # pylint: disable=too-many-arguments + @staticmethod + def update_chargings(conn, charge: Charge, car): + Charging.set_charge_price(charge, conn, car) + Database.update_charge(charge) + Database.clean_battery(conn) + + + + @staticmethod + def is_charge_ended(charge:'Charge'): + return not charge or charge.stop_at + + @staticmethod + def record_charging(car: Car, charging_status, charge_date: datetime, level, latitude, + # pylint: disable=too-many-locals + longitude, country_code, charging_mode, charging_rate, autonomy): + conn = Database.get_db() + charge_date = charge_date.replace(microsecond=0) + if charging_status == "InProgress": + last_charge = Database.get_last_charge(car.vin) + if Charging.is_charge_ended(last_charge): + conn.execute("INSERT INTO battery(start_at,start_level,charging_mode,VIN) VALUES(?,?,?,?)", + (charge_date, level, charging_mode, car.vin)) + start_at = charge_date + else: + start_at = last_charge.start_at + try: + conn.execute( + "INSERT INTO battery_curve(start_at,VIN,date,level,rate,autonomy) VALUES(?,?,?,?,?,?)", + (start_at, car.vin, charge_date, level, charging_rate, autonomy)) + except IntegrityError: + # todo add charging rate to unique constraint + logger.debug("level already stored") + Ecomix.get_data_from_co2_signal(latitude, longitude, country_code) + else: + try: + last_charge = Database.get_last_charge(car.vin) + charge_just_finished = last_charge.stop_at is None + except TypeError: + logger.debug("battery table is probably empty :", exc_info=True) + charge_just_finished = False + if charge_just_finished: + co2_per_kw = Ecomix.get_co2_per_kw(last_charge.start_at, charge_date, latitude, longitude, country_code) + consumption_kw = (level - last_charge.start_level) / 100 * car.battery_power + last_charge.end_level = level + last_charge.co2 = co2_per_kw + last_charge.kw = consumption_kw + last_charge.stop_at = charge_date + Charging.update_chargings(conn, last_charge, car) + conn.commit() + conn.close() diff --git a/ecomix.py b/psa-car-controller/psacc/application/ecomix.py similarity index 96% rename from ecomix.py rename to psa-car-controller/psacc/application/ecomix.py index 128574e..a442e69 100644 --- a/ecomix.py +++ b/psa-car-controller/psacc/application/ecomix.py @@ -1,3 +1,4 @@ +import logging from datetime import datetime, timedelta from statistics import mean, StatisticsError import xml.etree.cElementTree as ElT @@ -8,11 +9,11 @@ import reverse_geocode from pytz import UTC from requests import RequestException -from mylogger import logger CO2_SIGNAL_REQ_INTERVAL = 600 CO2_SIGNAL_URL = "https://api.co2signal.com" +logger = logging.getLogger(__name__) class Ecomix: _cache = {} @@ -81,8 +82,8 @@ class Ecomix: @staticmethod def clean_cache(): max_date = datetime.utcnow().replace(tzinfo=UTC) - timedelta(days=1) - for country in Ecomix._cache: - Ecomix._cache[country][:] = [x for x in Ecomix._cache[country] if max_date < x[0]] + for values in Ecomix._cache.values(): + values[:] = [x for x in values if max_date < x[0]] @staticmethod def get_co2_from_signal_cache(start: datetime, end: datetime, country_code): diff --git a/libs/config.py b/psa-car-controller/psacc/application/psa_car_controller.py similarity index 84% rename from libs/config.py rename to psa-car-controller/psacc/application/psa_car_controller.py index b56adba..b209895 100644 --- a/libs/config.py +++ b/psa-car-controller/psacc/application/psa_car_controller.py @@ -5,12 +5,13 @@ from os import environ, path from oauth2_client.credentials_manager import OAuthError -from charge_control import ChargeControls -from libs.charging import Charging -from libs.elec_price import ElecPrice -from my_psacc import MyPSACC -from mylogger import logger, my_logger -from otp.otp import CONFIG_NAME as OTP_CONFIG_NAME, ConfigException +from .charge_control import ChargeControls +from .charging import Charging +from psacc.repository.config_repository import ConfigRepository +from psacc.utils.utils import Singleton +from .psa_client import PSAClient +from common.mylogger import logger, my_logger +from psa.otp.otp import CONFIG_NAME as OTP_CONFIG_NAME, ConfigException DEFAULT_NAME = "config.json" @@ -35,24 +36,16 @@ def parse_args(): return parser.parse_args() -class Singleton(type): - _instances = {} - - def __call__(cls, *args, **kwargs): - if cls not in cls._instances: - cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) - return cls._instances[cls] - - -class Config(metaclass=Singleton): +class PSACarController(metaclass=Singleton): def __init__(self): self.args = parse_args() - self.myp: MyPSACC + self.myp: PSAClient self.chc: ChargeControls self.config_name = DEFAULT_NAME self.is_good: bool = True self.offline = self.args.offline self.remote_control = not (self.args.remote_disable or self.offline) + self.config = ConfigRepository.read_config() def start_remote_control(self): if self.args.remote_disable: @@ -63,8 +56,8 @@ class Config(metaclass=Singleton): try: self.myp.remote_client.start() if self.args.charge_control: - Config.chc = ChargeControls.load_config(self.myp, name=self.args.charge_control) - Config.chc.init() + self.chc = ChargeControls.load_config(self.myp, name=self.args.charge_control) + self.chc.init() self.myp.start_refresh_thread() except ConfigException: logger.error("start_remote_control failed redo otp config") @@ -74,7 +67,7 @@ class Config(metaclass=Singleton): if self.args.config: self.config_name = self.args.config if path.isfile(self.config_name): - self.myp = MyPSACC.load_config(name=self.config_name) + self.myp = PSAClient.load_config(name=self.config_name) elif self.args.web_conf: self.is_good = False return False @@ -82,7 +75,7 @@ class Config(metaclass=Singleton): raise FileNotFoundError(self.config_name) atexit.register(self.save_config) self.myp.set_record(self.args.record) - Charging.elec_price = ElecPrice.read_config() + Charging.elec_price = self.config.Electricity_config if self.args.offline: logger.info("offline mode") self.is_good = True diff --git a/my_psacc.py b/psa-car-controller/psacc/application/psa_client.py similarity index 89% rename from my_psacc.py rename to psa-car-controller/psacc/application/psa_client.py index ab8477f..315cb43 100644 --- a/my_psacc.py +++ b/psa-car-controller/psacc/application/psa_client.py @@ -1,4 +1,5 @@ import json +import logging import threading from json import JSONEncoder from hashlib import md5 @@ -7,27 +8,28 @@ from time import sleep from oauth2_client.credentials_manager import ServiceInformation from urllib3.exceptions import InvalidHeader -import psa_connectedcar as psac -from libs.car import Cars, Car -from libs.charging import Charging -from libs.psa.AccountInformation import AccountInformation -from libs.psa.RemoteClient import RemoteClient -from libs.psa.RemoteCredentials import RemoteCredentials -from libs.psa.oauth import OpenIdCredentialManager, Oauth2PSACCApiConfig, OauthAPIClient -from ecomix import Ecomix -from libs.psa.constants import realm_info, AUTHORIZE_SERVICE -from psa_connectedcar.rest import ApiException -from mylogger import logger +from psa.connected_car_api.api.vehicles_api import VehiclesApi +from psa.connected_car_api.rest import ApiException +from psacc.model.car import Cars, Car +from .charging import Charging +from psa.AccountInformation import AccountInformation +from psa.RemoteClient import RemoteClient +from psa.RemoteCredentials import RemoteCredentials +from psa.oauth import OpenIdCredentialManager, Oauth2PSACCApiConfig, OauthAPIClient +from .ecomix import Ecomix +from psa.constants import realm_info, AUTHORIZE_SERVICE -from web.abrp import Abrp -from web.db import Database +from .abrp import Abrp +from psacc.repository.db import Database SCOPE = ['openid profile'] CARS_FILE = "cars.json" DEFAULT_CONFIG_FILENAME = "config.json" +logger = logging.getLogger(__name__) -class MyPSACC: + +class PSAClient: def connect(self, user, password): self.manager.init_with_user_credentials_realm(user, password, self.realm) @@ -77,9 +79,9 @@ class MyPSACC: def get_app_name(self): return realm_info[self.realm]['app_name'] - def api(self) -> psac.VehiclesApi: + def api(self) -> VehiclesApi: self.api_config.access_token = self.manager.access_token - api_instance = psac.VehiclesApi(OauthAPIClient(self.api_config)) + api_instance = VehiclesApi(OauthAPIClient(self.api_config)) return api_instance def set_proxies(self, proxies): @@ -125,8 +127,7 @@ class MyPSACC: def start_refresh_thread(self): if self.refresh_thread is None: - self.refresh_thread = threading.Thread(target=self.__refresh_vehicle_info) - self.refresh_thread.setDaemon(True) + self.refresh_thread = threading.Thread(target=self.__refresh_vehicle_info,daemon=True) self.refresh_thread.start() def get_vehicles(self): @@ -147,7 +148,7 @@ class MyPSACC: def save_config(self, name=None, force=False): if name is None: name = self.config_file - config_str = json.dumps(self, cls=MyPeugeotEncoder, sort_keys=True, indent=4).encode("utf8") + config_str = json.dumps(self, cls=PSAClientEncoder, sort_keys=True, indent=4).encode("utf8") new_hash = md5(config_str).hexdigest() if force or self._config_hash != new_hash: with open(name, "wb") as f: @@ -165,7 +166,7 @@ class MyPSACC: for new_el in ["abrp", "co2_signal_api"]: if new_el not in config: config[new_el] = None - psacc = MyPSACC(**config) + psacc = PSAClient(**config) psacc.config_file = name return psacc @@ -183,6 +184,7 @@ class MyPSACC: latitude = car.status.last_position.geometry.coordinates[1] altitude = car.status.last_position.geometry.coordinates[2] date = car.status.last_position.properties.updated_at + date = car.status.service.updated_at if date is None: date = charge_date logger.debug("vin:%s longitude:%s latitude:%s date:%s mileage:%s level:%s charge_date:%s level_fuel:" @@ -207,9 +209,9 @@ class MyPSACC: yield key, value -class MyPeugeotEncoder(JSONEncoder): +class PSAClientEncoder(JSONEncoder): - def default(self, mp: MyPSACC): # pylint: disable=arguments-renamed + def default(self, mp: PSAClient): # pylint: disable=arguments-renamed mpd = {"proxies": mp.manager.proxies, "refresh_token": mp.manager.refresh_token, "client_secret": mp.service_information.client_secret, diff --git a/trip_parser.py b/psa-car-controller/psacc/application/trip_parser.py similarity index 96% rename from trip_parser.py rename to psa-car-controller/psacc/application/trip_parser.py index 3426a29..5a48972 100644 --- a/trip_parser.py +++ b/psa-car-controller/psacc/application/trip_parser.py @@ -1,11 +1,12 @@ +import logging from collections.abc import Callable -from libs.car import Car -from mylogger import logger +from psacc.model.car import Car LEVEL = 5 LEVEL_FUEL = 8 +logger = logging.getLogger(__name__) class TripParser: def __init__(self, car: Car): diff --git a/psa-car-controller/psacc/model/__init__.py b/psa-car-controller/psacc/model/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/psa-car-controller/psacc/model/battery_curve.py b/psa-car-controller/psacc/model/battery_curve.py new file mode 100644 index 0000000..aecdb19 --- /dev/null +++ b/psa-car-controller/psacc/model/battery_curve.py @@ -0,0 +1,6 @@ +class BatteryCurveDto: + def __init__(self, date, level, rate, autonomy): + self.autonomy = autonomy + self.rate = rate + self.level = level + self.date = date diff --git a/libs/car.py b/psa-car-controller/psacc/model/car.py similarity index 92% rename from libs/car.py rename to psa-car-controller/psacc/model/car.py index a2c7e4f..6c5cca4 100644 --- a/libs/car.py +++ b/psa-car-controller/psacc/model/car.py @@ -1,9 +1,10 @@ import json +import logging from copy import copy +from .car_status import CarStatus +from ..repository.car_model import CarModelRepository -from mylogger import logger -from libs.car_model import CarModel -from libs.car_status import CarStatus +logger = logging.getLogger(__name__) # pylint: disable=too-many-arguments @@ -13,9 +14,9 @@ class Car: self.vin = vin model = None if label is not None: - model = CarModel.find_model_by_name(label) + model = CarModelRepository().find_model_by_name(label) if model is None: - model = CarModel.find_model_by_vin(self.vin) + model = CarModelRepository().find_model_by_vin(self.vin) label = model.name self.vehicle_id = vehicle_id self.label = label @@ -127,7 +128,7 @@ class Cars(list): if name is None: name = Cars().config_filename try: - with open(name, "r",encoding="utf-8") as file: + with open(name, "r", encoding="utf-8") as file: json_str = file.read() cars = Cars.from_json(json.loads(json_str)) cars.config_filename = name diff --git a/psa-car-controller/psacc/model/car_model.py b/psa-car-controller/psacc/model/car_model.py new file mode 100644 index 0000000..e7348ad --- /dev/null +++ b/psa-car-controller/psacc/model/car_model.py @@ -0,0 +1,78 @@ +import re + +DEFAULT_BATTERY_POWER = 46 +DEFAULT_FUEL_CAPACITY = 0 +DEFAULT_MAX_ELEC_CONSUMPTION = 70 +DEFAULT_MAX_FUEL_CONSUMPTION = 30 + + +class CarModel: + # pylint: disable=too-many-arguments + def __init__(self, name, battery_power, fuel_capacity, abrp_name=None, reg=None, + max_elec_consumption=DEFAULT_MAX_ELEC_CONSUMPTION, max_fuel_consumption=DEFAULT_MAX_FUEL_CONSUMPTION): + self.name = name + self.battery_power = battery_power + self.fuel_capacity = fuel_capacity + self.abrp_name = abrp_name + self.reg = reg + self.max_elec_consumption = max_elec_consumption + self.max_fuel_consumption = max_fuel_consumption + + def match(self, vin): + if self.reg is None: + return False + return re.match(self.reg, vin) is not None + + +class ElecModel(CarModel): + # pylint: disable=too-many-arguments + def __init__(self, name, battery_power, abrp_name=None, reg=None, + max_elec_consumption=DEFAULT_MAX_ELEC_CONSUMPTION): + super().__init__(name, battery_power, 0, abrp_name, reg, max_elec_consumption, 0) + + @property + def max_fuel_consumption(self): + return 0 + +# car_models = [ +# ElecModel("e-208", 46, "peugeot:e208:20:50", r"VR3UHZKX.*"), +# ElecModel("e-2008", 46, "peugeot:e2008:20:48", r"VR3UKZKX.*"), +# ElecModel("e-Spacetourer", 46, "peugeot:etraveler:21:50:citroen", r"VF7VZZKX.*"), +# ElecModel("e-Traveller", 46, "peugeot:etraveler:21:50", r"VF3VZZKX.*"), +# ElecModel("corsa-e", 46, "opel:corsae:20:50", r"VXKUHZKX.*"), +# ElecModel("DS3 Crossback e-tense", 46, "ds:3crossback:20:48", r"VR1UJZKX.*"), # VR1UJZKXZL +# ElecModel("Mokka-e", 46, "opel:mokkae:20:48", r"VXKUKZKX.*"), # VXKUKZKXZM +# ElecModel("Zaphira-e", 68, "peugeot:etraveler:21:75:opel", r"VXEVZZKX.*"), # VXEVZZKXZMZ +# ElecModel("E-C4", 46, "citroen:ec4:21:50", r"VR7BCZKX.*"), # VR7BCZKXCM +# CarModel("SUV 3008 Hybrid 225", 13.2, 43, reg=r"VF3M4DGZ.*"), # VF3M4DGZUMS +# CarModel("SUV 3008", 0, 53, reg=r"VF3MJEHZ.*"), # VF3MJEHZRJ +# CarModel("308", 0, 56, reg=r"VF3L35GG.*"), +# CarModel("208", 0, 44, reg=r"VR3UPHN[SE].*"), # VR3UPHNSSM VR3UPHNEKM +# CarModel("2008", 0, 44, reg=r"VR3USHNS.*"), # VR3USHNSKM +# CarModel("2008 II", 0, 45, reg=r"VR3USHNK.*"), # VR3USHNKKL +# CarModel("SUV 5008 II", 0, 56, reg=r"VF3MRHNS.*"), # vf3mrhnsum +# CarModel("SUV 5008 II 2018", 0, 56, reg=r"VF3MRHNY.*"), # VF3MRHNYHH +# CarModel("N5008 GT-LINE 1.6L", 0, 60, reg=r"VF3MCBHZ.*"), # VF3MCBHZWJ +# CarModel("C5 Aircross Hybrid", 13.2, 43, reg=r"VR7A4DGZ.*"), # VR7A4DGZSM +# CarModel("DS7 Crossback E-Tense 300 4x4", 11.5, 43, reg="VR1J45GB.*"), # VR1J45GBUM VR1J45GBUL VR1J45GBUK +# CarModel("508 SW Hybrid", 11.5, 45, reg=r"VR3F4DGZ.*"), # VR3F4DGZTL +# CarModel("508 Hybrid", 11.5, 43, reg=r"VR3F3DGZ.*"), # VR3F3DGZTM +# CarModel("508 SW 2.0 HDI 163CV", 0, 72, reg=r"VF38ERHH.*"), # VF38ERHH +# CarModel("Grandland X Hybrid", 13.2, 43, reg=r"W0VZ4DGZ.*"), # W0VZ4DGZ2L +# CarModel("Grandland X Hybrid 4x4", 13.2, 43, reg=r"W0VZ45GB.*") # W0VZ45GB3L +# ] + +# fuel_model = [] +# +# import sys +# +# +# print(yaml.dump(car_models, sys.stdout)) +# with open("car_models.yml", "w") as f: +# yaml.dump(car_models, f) +# +# models_file = "/home/florian/Documents/psa/psa-car-controller/psacc/resources/car_models.yml" +# +# models +# res = yaml.load(models)[0] +# res diff --git a/libs/car_status.py b/psa-car-controller/psacc/model/car_status.py similarity index 76% rename from libs/car_status.py rename to psa-car-controller/psacc/model/car_status.py index cd91316..c62a754 100644 --- a/libs/car_status.py +++ b/psa-car-controller/psacc/model/car_status.py @@ -1,6 +1,15 @@ -from mylogger import logger -from psa_connectedcar import Position, Geometry, PositionProperties, Kinetic, Energy, EnergyCharging, Status, \ - VehicleOdometer +import logging + +from psa.connected_car_api.models.energy import Energy +from psa.connected_car_api.models.energy_charging import EnergyCharging +from psa.connected_car_api.models.geometry import Geometry +from psa.connected_car_api.models.kinetic import Kinetic +from psa.connected_car_api.models.position import Position +from psa.connected_car_api.models.position_properties import PositionProperties +from psa.connected_car_api.models.status import Status +from psa.connected_car_api.models.vehicle_odometer import VehicleOdometer + +logger = logging.getLogger(__name__) # pylint: disable=too-many-arguments diff --git a/psa-car-controller/psacc/model/charge.py b/psa-car-controller/psacc/model/charge.py new file mode 100644 index 0000000..2a6e55f --- /dev/null +++ b/psa-car-controller/psacc/model/charge.py @@ -0,0 +1,28 @@ +from datetime import datetime +from enum import Enum + + +class ChargingMode(Enum): + AC = "slow" + DC = "fast" + UNKNOWN = "unknown" + + @classmethod + def _missing_(cls, value): + return ChargingMode.UNKNOWN + + +class Charge: + # pylint: disable=too-many-arguments + def __init__(self, start_at: datetime, stop_at: datetime = None, vin=None, start_level=None, end_level=None, + co2=None, kw=None, price=None, charging_mode=None): + assert isinstance(start_at, datetime) + self.charging_mode: ChargingMode = ChargingMode(charging_mode) + self.start_at = start_at + self.stop_at = stop_at + self.vin = vin + self.start_level = start_level + self.end_level = end_level + self.co2 = co2 + self.kw = kw + self.price = price diff --git a/psa-car-controller/psacc/model/trip.py b/psa-car-controller/psacc/model/trip.py new file mode 100644 index 0000000..5198d4b --- /dev/null +++ b/psa-car-controller/psacc/model/trip.py @@ -0,0 +1,104 @@ +import logging +from statistics import mean +from typing import List + +from geojson import MultiLineString, Feature + +from .car import Car + +logger = logging.getLogger(__name__) + +class Points: + def __init__(self, latitude, longitude): + self.latitude = latitude + self.longitude = longitude + + def list(self): + return self.latitude, self.longitude + + +class Trip: + def __init__(self): + self.start_at = None + self.end_at = None + self.positions: List[Points] = [] + self.speed_average = None + self.consumption = 0 + self.consumption_km = 0 + self.consumption_fuel = 0 + self.consumption_fuel_km = 0 + self.distance = None + self.duration = None + self.mileage = None + self.car: Car = None + self.altitude_diff = None + self.temperatures = [] + self.id = None + + def add_points(self, latitude, longitude): + self.positions.append(Points(latitude, longitude)) + + def add_temperature(self, temp): + self.temperatures.append(temp) + + def get_temperature(self): + if len(self.temperatures) > 0: + return float(mean(self.temperatures)) + return None + + def set_consumption(self, diff_level: float) -> float: + if diff_level < 0: + logger.debugv("trip has negative consumption") + diff_level = 0 + self.consumption = diff_level * self.car.battery_power / 100 + try: + self.consumption_km = 100 * self.consumption / self.distance # kw/100 km + except TypeError: + raise ValueError("Distance not set") from TypeError + return self.consumption_km + + def set_fuel_consumption(self, consumption) -> float: + if self.distance is None: + raise ValueError("Distance not set") + if consumption < 0: + logger.debugv("trip has negative fuel consumption") + self.consumption_fuel = round(consumption * self.car.fuel_capacity / 100, 2) # L + self.consumption_fuel_km = round(100 * self.consumption_fuel / self.distance, 2) # L/100 km + return self.consumption_fuel_km + + def to_geojson(self): + multi_line_string = MultiLineString(tuple(map(list, self.positions))) + return Feature(geometry=multi_line_string, properties={"start_at": self.start_at, "end_at": self.end_at, + "average speed": self.speed_average, + "average consumption": self.consumption_km, + "average consumption fuel": self.consumption_fuel_km}) + + def get_info(self): + + res = {"consumption_km": self.consumption_km, "start_at": self.start_at, + "consumption_by_temp": self.get_temperature(), "positions": self.get_positions(), + "duration": self.duration * 60, "speed_average": self.speed_average, "distance": self.distance, + "mileage": self.mileage, "altitude_diff": self.altitude_diff, "id": self.id, + "consumption": self.consumption + } + if self.car.has_battery(): + res["consumption_km"] = self.consumption_km + + if self.car.has_fuel(): + res["consumption_fuel_km"] = self.consumption_fuel_km + + return res + + def set_altitude_diff(self, start, end): + try: + self.altitude_diff = end - start + except (NameError, TypeError): + pass + + def get_positions(self): + lat = [] + long = [] + for position in self.positions: + lat.append(position.latitude) + long.append(position.longitude) + return {"lat": lat, "long": long} diff --git a/psa-car-controller/psacc/repository/car_model.py b/psa-car-controller/psacc/repository/car_model.py new file mode 100644 index 0000000..b4e3114 --- /dev/null +++ b/psa-car-controller/psacc/repository/car_model.py @@ -0,0 +1,36 @@ +import logging +import os + +import ruamel.yaml +from typing import List + +from psacc.model.car_model import ElecModel, CarModel, DEFAULT_BATTERY_POWER, DEFAULT_FUEL_CAPACITY +from psacc.utils.utils import Singleton + +MODELS_FILE = os.path.dirname(os.path.realpath(__file__)) + "/../resources/car_models.yml" +logger = logging.getLogger(__name__) + + +class CarModelRepository(metaclass=Singleton): + def __init__(self): + with open(MODELS_FILE, "r") as f: + models = f.read() + yaml = ruamel.yaml.YAML() + yaml.register_class(ElecModel) + yaml.register_class(CarModel) + self.models: List = yaml.load(models) + + def find_model_by_vin(self, vin) -> CarModel: + if vin != "vin": + for car_model in self.models: + if car_model.match(vin): + return car_model + logger.warning("Can't get car model, please report an issue on github with your car model" + " and first ten letter of your VIN : %s", vin[:10]) + return CarModel("unknown", DEFAULT_BATTERY_POWER, DEFAULT_FUEL_CAPACITY) + + def find_model_by_name(self, name) -> CarModel: + for car_model in self.models: + if car_model.name == name: + return car_model + return None diff --git a/psa-car-controller/psacc/repository/config_repository.py b/psa-car-controller/psacc/repository/config_repository.py new file mode 100644 index 0000000..01da5f3 --- /dev/null +++ b/psa-car-controller/psacc/repository/config_repository.py @@ -0,0 +1,205 @@ +import logging +import re +from datetime import datetime, timezone, timedelta +from statistics import mean, StatisticsError + +from configupdater import ConfigUpdater +from pydantic import BaseModel +from typing import List + +from psacc.application.battery_charge_curve import BatteryChargeCurve +from psacc.model.charge import Charge + +logger = logging.getLogger(__name__) + +DEFAULT_CONFIG = """[General] +currency = € +# minimum trip length in km so it's added to stats and map in website +minimum trip length = + +[Electricity config] +# price by kw/h +day price = +night price = +# ex: 22h30 +night hour start = +# ex: 6h00 +night hour end = +dc charge price = +high speed dc charge price = +# minimum power in kW that should be delivered during a charge so it can be considered as a high speed charger +high speed dc charge threshold = +""" + + +def utc_to_local(utc_dt): + return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=None) + + +def replace_key_underscore_by_space(obj, key): + new_obj = {} + for k, v in obj.items(): + if isinstance(v, dict): + new_obj[k.replace("_", " ")] = replace_key_underscore_by_space(v, key) + else: + new_obj[k.replace("_", " ")] = v + return new_obj + + +class Hour: + reg = re.compile(r"([0-9]{1,2})h([0-9]{1,2})") + + def __init__(self, hours: int, minutes: int): + self.hours = hours + self.minutes = minutes + + @classmethod + def __get_validators__(cls): + yield cls.validate + + @classmethod + def validate(cls, v): + if not isinstance(v, str): + raise TypeError('string required') + if len(v) == 0: + return None + + m = Hour.reg.fullmatch(v.lower()) + if not m: + raise ValueError('invalid hour format') + return cls(int(m.group(1)), int(m.group(2))) + + def __repr__(self): + return '{}h{}'.format(self.hours, self.minutes) + + +currency = "" +CONFIG_FILENAME = "config.ini" + + +class GeneralConfig(BaseModel): + currency: str = "€" + length_unit: str = "km" + minimum_trip_length: float = 10 + + +class ElectricityPriceConfig(BaseModel): + day_price: float = 0.15 + night_price: float = None + night_hour_start: Hour = None + night_hour_end: Hour = None + dc_charge_price: float = None + high_speed_dc_charge_price: float = None + high_speed_dc_charge_threshold: float = None + + @staticmethod + def compare_hour(date: datetime, hour, minute): + if date.hour < hour: + return False + if date.hour == hour and date.minute < minute: + return False + return True + + def is_nigh_hour_enabled(self): + return self.night_hour_start and self.night_hour_end and self.night_price + + def get_instant_price(self, date): + local_date = utc_to_local(date) + if self.night_price is None: + return self.day_price + if self.compare_hour(local_date, self.night_hour_start.hours, self.night_hour_start.minutes) or \ + not self.compare_hour(local_date, self.night_hour_end.hours, self.night_hour_end.minutes): + return self.night_price + return self.day_price + + def _get_dc_charge_price(self, charge: Charge, battery_charge_curves: List[BatteryChargeCurve]): + max_consumption = sum(battery_charge_curve.speed for battery_charge_curve in battery_charge_curves) + total_consumption = charge.kw + if self.high_speed_dc_charge_threshold and max_consumption > self.high_speed_dc_charge_threshold: + return self.high_speed_dc_charge_price * total_consumption + return self.dc_charge_price * total_consumption + + def _get_ac_charge_price(self, start, end, consumption): + prices = [] + date = start + res = None + if not (start is None or end is None): + while date < end: + prices.append(self.get_instant_price(date)) + date = date + timedelta(minutes=30) + try: + res = round(consumption * mean(prices), 2) + except (TypeError, StatisticsError): + logger.error("Can't get_price of charge, check config") + return res + + def get_price(self, charge: Charge, battery_charge_curves: List[BatteryChargeCurve]): + if charge.charging_mode.DC and self.dc_charge_price: + return self._get_dc_charge_price(charge, battery_charge_curves) + return self._get_ac_charge_price(charge.start_at, charge.stop_at, charge.kw) + + def is_enable(self): + return self.day_price is not None + + +class ConfigRepository(BaseModel): + General: GeneralConfig + Electricity_config: ElectricityPriceConfig + + @staticmethod + def _read_file(name): + if name is None: + name = CONFIG_FILENAME + with open(name, "r") as f: + return f.read() + + @staticmethod + def read_config(name=None) -> 'ConfigRepository': + try: + config_str = ConfigRepository._read_file(name) + config = ConfigUpdater() + config.read_string(config_str) + except FileNotFoundError: + config = ConfigRepository.get_default_config() + return ConfigRepository.config_file_to_dto(config) + + @staticmethod + def get_default_config(): + config = ConfigUpdater() + config.read_string(DEFAULT_CONFIG) + return config + + def config_dto_to_config_file(self, config): + res = replace_key_underscore_by_space(self.dict(), None) + for section, option in res.items(): + for key, value in option.items(): + config[section][key] = value + + return config + + def write_config(self, name=None): + if name is None: + name = CONFIG_FILENAME + config_to_write = ConfigRepository.get_default_config() + self.config_dto_to_config_file(config_to_write) + ConfigRepository._write(name, config_to_write) + + @staticmethod + def _write(name, config): + with open(name, "w") as f: + config.write(f) + + @staticmethod + def config_file_to_dto(config) -> 'ConfigRepository': + new_dict = {} + for section in config: + new_section = section.replace(" ", "_") + new_dict[new_section] = {} + for option in config[section]: + new_option = option.replace(" ", "_") + value = config[section][option].value + if len(value) > 0: + new_dict[new_section][new_option] = value + + config_obj = ConfigRepository(**new_dict) + return config_obj diff --git a/web/db.py b/psa-car-controller/psacc/repository/db.py similarity index 81% rename from web/db.py rename to psa-car-controller/psacc/repository/db.py index 116ff6a..2346395 100644 --- a/web/db.py +++ b/psa-car-controller/psacc/repository/db.py @@ -1,18 +1,22 @@ +import logging import sys import sqlite3 from datetime import datetime from threading import Lock from time import sleep -from typing import Callable +from typing import Callable, List import pytz import requests from geojson import Feature, Point, FeatureCollection from geojson import dumps as geo_dumps -from mylogger import logger -from libs.utils import get_temp +from psacc.model.battery_curve import BatteryCurveDto +from psacc.model.charge import Charge +from psacc.utils.utils import get_temp + +logger = logging.getLogger(__name__) NEW_BATTERY_COLUMNS = [["price", "INTEGER"], ["charging_mode", "TEXT"]] NEW_POSITION_COLUMNS = [["level_fuel", "INTEGER"], ["altitude", "INTEGER"]] @@ -30,6 +34,10 @@ def new_convert_datetime_from_string(string): return datetime.fromisoformat(string) +def dict_key_to_lower_case(**kwargs) -> dict: + return dict((k.lower(), v) for k, v in kwargs.items()) + + class CustomSqliteConnection(sqlite3.Connection): def __init__(self, *args, **kwargs): # real signature unknown @@ -79,7 +87,7 @@ class Database: if sys.version_info < (3, 7): logger.warning("Can't do database backup, please upgrade to python 3.7") else: - filename=f"info_backup_{datetime.now()}.db".replace(":", "_") + filename = f"info_backup_{datetime.now()}.db".replace(":", "_") back_conn = sqlite3.connect(filename) conn.backup(back_conn) back_conn.close() @@ -112,6 +120,7 @@ class Database: pass if make_backup: Database.backup(conn) + conn.execute("DROP TRIGGER IF EXISTS update_trigger") Database.clean_battery(conn) Database.add_altitude_to_db(conn) conn.commit() @@ -167,21 +176,24 @@ class Database: return res[0] @staticmethod - def set_chargings_price(conn, start_at, price): - if isinstance(start_at, str): - start_at = Database.convert_datetime_from_string(start_at) - update = conn.execute("UPDATE battery SET price=? WHERE start_at=?", (price, start_at)).rowcount == 1 + def set_chargings_price(conn, charge: Charge): + update = conn.execute("UPDATE battery SET price=? WHERE start_at=? AND VIN=?", + (charge.price, charge.start_at, charge.vin)).rowcount conn.commit() - if not update: + if update == 0: logger.error("Can't find line to update in the database") return update @staticmethod def get_battery_curve(conn, start_at, stop_at, vin): - return convert_sql_res(conn.execute("""SELECT date, level, rate, autonomy + battery_curves = [] + res = conn.execute("""SELECT date, level, rate, autonomy FROM battery_curve WHERE start_at=? and date<=? and VIN=?;""", - (start_at, stop_at, vin)).fetchall()) + (start_at, stop_at, vin)).fetchall() + for row in res: + battery_curves.append(BatteryCurveDto(**dict_key_to_lower_case(**row))) + return battery_curves @staticmethod def add_altitude_to_db(conn): @@ -266,3 +278,41 @@ class Database: conn.close() logger.debug("position already saved") return False + + @staticmethod + def get_last_charge(vin) -> Charge: + conn = Database.get_db() + res = conn.execute("SELECT start_at, stop_at, vin, start_level, end_level, co2, kw, price, charging_mode " + "FROM battery WHERE VIN=? ORDER BY start_at DESC limit 1", (vin,)).fetchone() + if res: + return Charge(**dict_key_to_lower_case(**res)) + return None + + @staticmethod + def get_charge(vin, start_at) -> Charge: + conn = Database.get_db() + res = conn.execute("SELECT * FROM battery WHERE VIN=? AND START_AT=? ORDER BY start_at DESC limit 1", + (vin, start_at,)).fetchone() + if res: + return Charge(**dict_key_to_lower_case(**res)) + return None + + @staticmethod + def get_all_charge_without_price(conn) -> List[Charge]: + res = conn.execute("SELECT * FROM battery WHERE price IS NULL").fetchall() + charges = [] + for row in res: + charges.append(Charge(**dict_key_to_lower_case(**row))) + return charges + + @staticmethod + def update_charge(charge: Charge): + conn = Database.get_db() + res = conn.execute( + "UPDATE battery set stop_at=?, end_level=?, co2=?, kw=?, price=? WHERE start_at=? and VIN=?", + (charge.stop_at, charge.end_level, charge.co2, charge.kw, charge.price, charge.start_at, + charge.vin)).rowcount + if res == 0: + logger.error("Can't find battery row to update") + conn.commit() + conn.close() diff --git a/trip.py b/psa-car-controller/psacc/repository/trips.py similarity index 56% rename from trip.py rename to psa-car-controller/psacc/repository/trips.py index 361904f..928e877 100644 --- a/trip.py +++ b/psa-car-controller/psacc/repository/trips.py @@ -1,111 +1,15 @@ import logging -from statistics import mean -from typing import List, Dict +from typing import Dict -from geojson import Feature, FeatureCollection, MultiLineString +from geojson import FeatureCollection -from libs.car import Cars, Car -from mylogger import logger -from trip_parser import TripParser -from web.db import Database +from psacc.application.trip_parser import TripParser +from psacc.model.trip import Trip +from psacc.model.car import Cars +from psacc.repository.db import Database -class Points: - def __init__(self, latitude, longitude): - self.latitude = latitude - self.longitude = longitude - - def list(self): - return self.latitude, self.longitude - - -class Trip: - def __init__(self): - self.start_at = None - self.end_at = None - self.positions: List[Points] = [] - self.speed_average = None - self.consumption = 0 - self.consumption_km = 0 - self.consumption_fuel = 0 - self.consumption_fuel_km = 0 - self.distance = None - self.duration = None - self.mileage = None - self.car: Car = None - self.altitude_diff = None - self.temperatures = [] - self.id = None - - def add_points(self, latitude, longitude): - self.positions.append(Points(latitude, longitude)) - - def add_temperature(self, temp): - self.temperatures.append(temp) - - def get_temperature(self): - if len(self.temperatures) > 0: - return float(mean(self.temperatures)) - return None - - def set_consumption(self, diff_level: float) -> float: - if diff_level < 0: - logger.debugv("trip has negative consumption") - diff_level = 0 - self.consumption = diff_level * self.car.battery_power / 100 - try: - self.consumption_km = 100 * self.consumption / self.distance # kw/100 km - except TypeError: - raise ValueError("Distance not set") from TypeError - return self.consumption_km - - def set_fuel_consumption(self, consumption) -> float: - if self.distance is None: - raise ValueError("Distance not set") - if consumption < 0: - logger.debugv("trip has negative fuel consumption") - self.consumption_fuel = round(consumption, 2) # L - self.consumption_fuel_km = round(100 * self.consumption_fuel / self.distance, 2) # L/100 km - return self.consumption_fuel_km - - - def to_geojson(self): - multi_line_string = MultiLineString(tuple(map(list, self.positions))) - return Feature(geometry=multi_line_string, properties={"start_at": self.start_at, "end_at": self.end_at, - "average speed": self.speed_average, - "average consumption": self.consumption_km, - "average consumption fuel": self.consumption_fuel_km}) - - - def get_info(self): - - res = {"consumption_km": self.consumption_km, "start_at": self.start_at, - "consumption_by_temp": self.get_temperature(), "positions": self.get_positions(), - "duration": self.duration * 60, "speed_average": self.speed_average, "distance": self.distance, - "mileage": self.mileage, "altitude_diff": self.altitude_diff, "id": self.id, - "consumption": self.consumption - } - if self.car.has_battery(): - res["consumption_km"] = self.consumption_km - - if self.car.has_fuel(): - res["consumption_fuel_km"] = self.consumption_fuel_km - - return res - - def set_altitude_diff(self, start, end): - try: - self.altitude_diff = end - start - except (NameError, TypeError): - pass - - def get_positions(self): - lat = [] - long = [] - for position in self.positions: - lat.append(position.latitude) - long.append(position.longitude) - return {"lat": lat, "long": long} +logger = logging.getLogger(__name__) class Trips(list): @@ -134,7 +38,7 @@ class Trips(list): return False @staticmethod - def get_trips(vehicles_list: Cars) -> Dict[str, "Trips"]: # noqa: MC0001 + def get_trips(vehicles_list: Cars) -> Dict[str, "Trips"]: # noqa: MC0001 # pylint: disable=too-many-locals,too-many-statements,too-many-nested-blocks,too-many-branches conn = Database.get_db() vehicles = conn.execute("SELECT DISTINCT vin FROM position;").fetchall() @@ -142,8 +46,9 @@ class Trips(list): for vin in vehicles: trips = Trips() vin = vin[0] - res = conn.execute('SELECT Timestamp, VIN, longitude, latitude, mileage, level, moving, temperature,' - ' level_fuel, altitude FROM position WHERE VIN=? ORDER BY Timestamp', (vin,)).fetchall() + res = conn.execute('SELECT Timestamp, VIN, longitude, latitude, mileage, level, moving, temperature, ' + 'level_fuel, altitude FROM position WHERE VIN=? AND mileage NOT NULL ORDER BY Timestamp', + (vin,)).fetchall() if len(res) > 1: car = vehicles_list.get_car_by_vin(vin) assert car is not None @@ -156,7 +61,7 @@ class Trips(list): if logger.isEnabledFor(logging.DEBUG): # reduce execution time if debug disabled logger.debugv("%s mileage:%.1f level:%s level_fuel:%s", res[x]['Timestamp'], res[x]['mileage'], res[x]['level'], res[x]['level_fuel']) - next_el = res[x + 2] + next_point = res[x + 2] distance = 0 try: distance = end["mileage"] - start["mileage"] @@ -174,14 +79,14 @@ class Trips(list): logger.debugv("restart trip at {0[Timestamp]} mileage:{0[mileage]:.1f} level:{0[level]}" " level_fuel:{0[level_fuel]}", start, style='{') else: - distance = next_el["mileage"] - end["mileage"] # km - duration = (next_el["Timestamp"] - end["Timestamp"]).total_seconds() / 3600 + distance = next_point["mileage"] - end["mileage"] # km + duration = (next_point["Timestamp"] - end["Timestamp"]).total_seconds() / 3600 try: speed_average = distance / duration except ZeroDivisionError: speed_average = 0 end_trip = False - if trip_parser.is_refuel(end, next_el, distance) or \ + if trip_parser.is_refuel(end, next_point, distance) or \ TripParser.is_low_speed(speed_average, duration): end_trip = True elif duration > 2: @@ -189,7 +94,7 @@ class Trips(list): logger.debugv("too much time detected") elif x == len(res) - 3: # last record detected # think if add point is needed - end = next_el + end = next_point end_trip = True logger.debugv("last position found") if end_trip: @@ -218,11 +123,11 @@ class Trips(list): "{0.consumption_fuel_km:.2f}L/100km {0.mileage:.1f}km", trip, style="{") # filter bad value trips.check_and_append(trip) - start = next_el + start = next_point trip = Trip() else: trip.add_points(end["latitude"], end["longitude"]) - end = next_el + end = next_point trips_by_vin[vin] = trips conn.close() return trips_by_vin diff --git a/psa-car-controller/psacc/resources/car_models.yml b/psa-car-controller/psacc/resources/car_models.yml new file mode 100644 index 0000000..76f23fa --- /dev/null +++ b/psa-car-controller/psacc/resources/car_models.yml @@ -0,0 +1,198 @@ +- !ElecModel + name: e-208 + battery_power: 46 + fuel_capacity: 0 + abrp_name: peugeot:e208:20:50 + reg: VR3UHZKX.* + max_elec_consumption: 70 +- !ElecModel + name: e-2008 + battery_power: 46 + fuel_capacity: 0 + abrp_name: peugeot:e2008:20:48 + reg: VR3UKZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: e-Spacetourer + battery_power: 46 + fuel_capacity: 0 + abrp_name: peugeot:etraveler:21:50:citroen + reg: VF7VZZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: e-Traveller + battery_power: 46 + fuel_capacity: 0 + abrp_name: peugeot:etraveler:21:50 + reg: VF3VZZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: corsa-e + battery_power: 46 + fuel_capacity: 0 + abrp_name: opel:corsae:20:50 + reg: VXKUHZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: DS3 Crossback e-tense + battery_power: 46 + fuel_capacity: 0 + abrp_name: ds:3crossback:20:48 + reg: VR1UJZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: Mokka-e + battery_power: 46 + fuel_capacity: 0 + abrp_name: opel:mokkae:20:48 + reg: VXKUKZKX.* + max_elec_consumption: 70 +- !ElecModel + name: Zaphira-e + battery_power: 68 + fuel_capacity: 0 + abrp_name: peugeot:etraveler:21:75:opel + reg: VXEVZZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !ElecModel + name: E-C4 + battery_power: 46 + fuel_capacity: 0 + abrp_name: citroen:ec4:21:50 + reg: VR7BCZKX.* + max_elec_consumption: 70 + max_fuel_consumption: 0 +- !CarModel + name: SUV 3008 Hybrid 225 + battery_power: 13.2 + fuel_capacity: 43 + abrp_name: + reg: VF3M4DGZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: SUV 3008 + battery_power: 0 + fuel_capacity: 53 + abrp_name: + reg: VF3MJEHZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: '308' + battery_power: 0 + fuel_capacity: 56 + abrp_name: + reg: VF3L35GG.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: '208' + battery_power: 0 + fuel_capacity: 44 + abrp_name: + reg: VR3UPHN[SE].* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: '2008' + battery_power: 0 + fuel_capacity: 44 + abrp_name: + reg: VR3USHNS.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: 2008 II + battery_power: 0 + fuel_capacity: 45 + abrp_name: + reg: VR3USHNK.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: SUV 5008 II + battery_power: 0 + fuel_capacity: 56 + abrp_name: + reg: VF3MRHNS.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: SUV 5008 II 2018 + battery_power: 0 + fuel_capacity: 56 + abrp_name: + reg: VF3MRHNY.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: N5008 GT-LINE 1.6L + battery_power: 0 + fuel_capacity: 60 + abrp_name: + reg: VF3MCBHZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: C5 Aircross Hybrid + battery_power: 13.2 + fuel_capacity: 43 + abrp_name: + reg: VR7A4DGZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: DS7 Crossback E-Tense 300 4x4 + battery_power: 11.5 + fuel_capacity: 43 + abrp_name: + reg: VR1J45GB.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: 508 SW Hybrid + battery_power: 11.5 + fuel_capacity: 45 + abrp_name: + reg: VR3F4DGZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: 508 Hybrid + battery_power: 11.5 + fuel_capacity: 43 + abrp_name: + reg: VR3F3DGZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: 508 SW 2.0 HDI 163CV + battery_power: 0 + fuel_capacity: 72 + abrp_name: + reg: VF38ERHH.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: Grandland X Hybrid + battery_power: 13.2 + fuel_capacity: 43 + abrp_name: + reg: W0VZ4DGZ.* + max_elec_consumption: 70 + max_fuel_consumption: 30 +- !CarModel + name: Grandland X Hybrid 4x4 + battery_power: 13.2 + fuel_capacity: 43 + abrp_name: + reg: W0VZ45GB.* + max_elec_consumption: 70 + max_fuel_consumption: 30 diff --git a/libs/requirements.py b/psa-car-controller/psacc/utils/requirements.py similarity index 94% rename from libs/requirements.py rename to psa-car-controller/psacc/utils/requirements.py index b7e64cf..f05321e 100644 --- a/libs/requirements.py +++ b/psa-car-controller/psacc/utils/requirements.py @@ -1,9 +1,10 @@ +import logging import sys import pkg_resources from pathlib import Path -from mylogger import logger +logger = logging.getLogger(__name__) class TestRequirements: diff --git a/psa-car-controller/psacc/utils/utils.py b/psa-car-controller/psacc/utils/utils.py new file mode 100644 index 0000000..3fdce38 --- /dev/null +++ b/psa-car-controller/psacc/utils/utils.py @@ -0,0 +1,38 @@ +import logging +import socket + +import requests + +logger = logging.getLogger(__name__) + + +def get_temp(latitude: str, longitude: str, api_key: str) -> float: + try: + if not (latitude is None or longitude is None or api_key is None): + weather_rep = requests.get("https://api.openweathermap.org/data/2.5/onecall", + params={"lat": latitude, "lon": longitude, + "exclude": "minutely,hourly,daily,alerts", + "appid": api_key, + "units": "metric"}) + temp = weather_rep.json()["current"]["temp"] + logger.debug("Temperature :%fc", temp) + return temp + except ConnectionError: + logger.error("Can't connect to openweathermap :", exc_info=True) + except KeyError: + logger.error("Unable to get temperature from openweathermap :", exc_info=True) + return None + + +def is_port_in_use(ip, port): + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: + return s.connect_ex((ip, port)) == 0 + + +class Singleton(type): + _instances = {} + + def __call__(cls, *args, **kwargs): + if cls not in cls._instances: + cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) + return cls._instances[cls] diff --git a/psa-car-controller/web/__init__.py b/psa-car-controller/web/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/web/app.py b/psa-car-controller/web/app.py similarity index 98% rename from web/app.py rename to psa-car-controller/web/app.py index d2a3a00..167fcda 100644 --- a/web/app.py +++ b/psa-car-controller/web/app.py @@ -12,7 +12,7 @@ try: except ImportError: from werkzeug import DispatcherMiddleware -from mylogger import logger, file_handler +from common.mylogger import logger, file_handler import importlib # pylint: disable=invalid-name diff --git a/web/assets/clientside.js b/psa-car-controller/web/assets/clientside.js similarity index 94% rename from web/assets/clientside.js rename to psa-car-controller/web/assets/clientside.js index 74ee447..8a1d155 100644 --- a/web/assets/clientside.js +++ b/psa-car-controller/web/assets/clientside.js @@ -44,7 +44,7 @@ function addLocaleDate (data, dateKey) { const dateOption = [undefined, { hour: 'numeric', minute: 'numeric' }] function dateToLocale (row, key) { const date = new Date(row[key]) - row[key] = date + row[key] = date.getTime() row[key + '_str'] = date.toLocaleDateString(...dateOption) } let datasetName, dataset @@ -87,12 +87,6 @@ function updateFigures (data, oldFigure, x, y) { const xLabel = x[i] const figure = Object.assign({}, oldFigure[i]) i++ - // console.log(oldFigure[i]); - // var unique_y_label = y[i].filter((v, i, a) => a.indexOf(v) === i); - // var data_nonnull = trips - // unique_y_label.forEach(function(label) { - // data_nonnull = data_nonnull.filter(line => line[label]); - // }); if ('mapbox' in figure.layout) { figure.data[0].lat = [] figure.data[0].lon = [] @@ -125,11 +119,26 @@ function updateFigures (data, oldFigure, x, y) { return figures } +function removeObjectFromTableRow (data) { + const rows = [] + data.forEach(object => { + const row = {} + for (const key in object) { + if (typeof object[key] !== 'object') { + row[key] = object[key] + } + } + rows.push(row) + }) + return rows +} + function updateTables (data, tables) { console.log('tables', tables) const figures = [] tables.forEach(function (table) { - figures.push(data[table.src]) + const tableData = removeObjectFromTableRow(data[table.src]) + figures.push(tableData) }) return figures } diff --git a/web/assets/images/battery-charge-line.svg b/psa-car-controller/web/assets/images/battery-charge-line.svg similarity index 100% rename from web/assets/images/battery-charge-line.svg rename to psa-car-controller/web/assets/images/battery-charge-line.svg diff --git a/web/assets/images/battery-charge.svg b/psa-car-controller/web/assets/images/battery-charge.svg similarity index 100% rename from web/assets/images/battery-charge.svg rename to psa-car-controller/web/assets/images/battery-charge.svg diff --git a/web/assets/images/consumption.svg b/psa-car-controller/web/assets/images/consumption.svg similarity index 100% rename from web/assets/images/consumption.svg rename to psa-car-controller/web/assets/images/consumption.svg diff --git a/web/assets/images/electricity bill.svg b/psa-car-controller/web/assets/images/electricity bill.svg similarity index 100% rename from web/assets/images/electricity bill.svg rename to psa-car-controller/web/assets/images/electricity bill.svg diff --git a/web/assets/images/mileage.svg b/psa-car-controller/web/assets/images/mileage.svg similarity index 100% rename from web/assets/images/mileage.svg rename to psa-car-controller/web/assets/images/mileage.svg diff --git a/web/assets/images/pollution.svg b/psa-car-controller/web/assets/images/pollution.svg similarity index 100% rename from web/assets/images/pollution.svg rename to psa-car-controller/web/assets/images/pollution.svg diff --git a/web/assets/images/settings.svg b/psa-car-controller/web/assets/images/settings.svg similarity index 100% rename from web/assets/images/settings.svg rename to psa-car-controller/web/assets/images/settings.svg diff --git a/web/assets/images/sync.svg b/psa-car-controller/web/assets/images/sync.svg similarity index 100% rename from web/assets/images/sync.svg rename to psa-car-controller/web/assets/images/sync.svg diff --git a/web/assets/sprites/osm-liberty.json b/psa-car-controller/web/assets/sprites/osm-liberty.json similarity index 100% rename from web/assets/sprites/osm-liberty.json rename to psa-car-controller/web/assets/sprites/osm-liberty.json diff --git a/web/assets/sprites/osm-liberty.png b/psa-car-controller/web/assets/sprites/osm-liberty.png similarity index 100% rename from web/assets/sprites/osm-liberty.png rename to psa-car-controller/web/assets/sprites/osm-liberty.png diff --git a/web/assets/sprites/osm-liberty@2x.json b/psa-car-controller/web/assets/sprites/osm-liberty@2x.json similarity index 100% rename from web/assets/sprites/osm-liberty@2x.json rename to psa-car-controller/web/assets/sprites/osm-liberty@2x.json diff --git a/web/assets/sprites/osm-liberty@2x.png b/psa-car-controller/web/assets/sprites/osm-liberty@2x.png similarity index 100% rename from web/assets/sprites/osm-liberty@2x.png rename to psa-car-controller/web/assets/sprites/osm-liberty@2x.png diff --git a/web/assets/style.json b/psa-car-controller/web/assets/style.json similarity index 100% rename from web/assets/style.json rename to psa-car-controller/web/assets/style.json diff --git a/web/dash_custom.py b/psa-car-controller/web/dash_custom.py similarity index 99% rename from web/dash_custom.py rename to psa-car-controller/web/dash_custom.py index 5f9d143..dd72cb8 100644 --- a/web/dash_custom.py +++ b/psa-car-controller/web/dash_custom.py @@ -1,5 +1,6 @@ from dash import Dash + class DashCustom(Dash): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/web/figures.py b/psa-car-controller/web/figures.py similarity index 79% rename from web/figures.py rename to psa-car-controller/web/figures.py index 331e382..5cbdb1a 100644 --- a/web/figures.py +++ b/psa-car-controller/web/figures.py @@ -1,5 +1,4 @@ from copy import deepcopy -from statistics import mean import dash_bootstrap_components as dbc from dash import html @@ -9,13 +8,14 @@ import plotly.graph_objects as go from dash.dash_table.Format import Scheme, Symbol, Format from dash.dcc import Graph -from libs.car import Car -from libs.elec_price import ElecPrice -from trip import Trip -from web.db import Database -from web.utils import card_value_div, dash_date_to_datetime +from psacc.application.charging import Charging +from psacc.model.car import Car +from psacc.repository.trips import Trip +from psacc.repository.db import Database # pylint: disable=invalid-name +from web.tools.utils import card_value_div, dash_date_to_datetime + ERROR_DIV = dbc.Alert("No data to show, there is probably no trips recorded yet", color="danger") PADDING_TOP = {"padding-top": "1em"} consumption_fig = ERROR_DIV @@ -34,9 +34,10 @@ ELEC_CONSUM_KW = "elec_consum_kw" ELEC_CONSUM_PRICE = "elec_consum_price" AVG_CONSUM_KW = "avg_consum_kw" AVG_CONSUM_PRICE = "avg_consum_price" +CURRENCY = "€" SUMMARY_CARDS = {"Average consumption": {"text": [card_value_div(AVG_CONSUM_KW, "kWh/100km"), - card_value_div(AVG_CONSUM_PRICE, f"{ElecPrice.currency}/100km")], + card_value_div(AVG_CONSUM_PRICE, f"{CURRENCY}/100km")], "src": "assets/images/consumption.svg"}, "Average emission": {"text": [card_value_div(AVG_EMISSION_KM, " g/km"), card_value_div(AVG_EMISSION_KW, "g/kWh")], @@ -44,12 +45,11 @@ SUMMARY_CARDS = {"Average consumption": {"text": [card_value_div(AVG_CONSUM_KW, "Average charge speed": {"text": [card_value_div(AVG_CHARGE_SPEED, " kW")], "src": "assets/images/battery-charge-line.svg"}, "Electricity consumption": {"text": [card_value_div(ELEC_CONSUM_KW, "kWh"), - card_value_div(ELEC_CONSUM_PRICE, ElecPrice.currency)], + card_value_div(ELEC_CONSUM_PRICE, CURRENCY)], "src": "assets/images/electricity bill.svg"} } -# pylint: disable=too-many-locals def get_figures(car: Car): global consumption_fig, trips_map, consumption_fig_by_speed, table_fig, battery_table, consumption_fig_by_temp lats = [42, 41] @@ -128,7 +128,7 @@ def get_figures(car: Car): {'id': 'kw', 'name': 'consumption', 'type': 'numeric', 'format': deepcopy(nb_format).symbol_suffix(" kWh").precision(2)}, {'id': 'price', 'name': 'price', 'type': 'numeric', - 'format': deepcopy(nb_format).symbol_suffix(" " + ElecPrice.currency).precision(2), 'editable': True} + 'format': deepcopy(nb_format).symbol_suffix(" " + CURRENCY).precision(2), 'editable': True} ], data=[], style_data_conditional=[ @@ -157,46 +157,11 @@ def get_figures(car: Car): def get_battery_curve_fig(row: dict, car: Car): start_date = dash_date_to_datetime(row["start_at"]) - stop_at = dash_date_to_datetime(row["stop_at"]) conn = Database.get_db() - res = Database.get_battery_curve(conn, start_date, stop_at, car.vin) - conn.close() - battery_curves = [] - if len(res) > 0: - battery_capacity = res[-1]["level"] * car.battery_power / 100 - km_by_kw = 0.8 * res[-1]["autonomy"] / battery_capacity - start = 0 - speeds = [] - - def speed_in_kw_from_km(row): - try: - speed = row["rate"] / km_by_kw - if speed > 0: - speeds.append(speed) - except (KeyError, TypeError): - pass - - for end in range(1, len(res)): - start_level = res[start]["level"] - end_level = res[end]["level"] - diff_level = end_level - start_level - diff_sec = (res[end]["date"] - res[start]["date"]).total_seconds() - speed_in_kw_from_km(res[end - 1]) - if diff_sec > 0 and diff_level > 3: - speed_in_kw_from_km(res[end]) - speed = car.get_charge_speed(diff_level, diff_sec) - if len(speeds) > 0: - speed = mean([*speeds, speed]) - speed = round(speed * 2) / 2 - battery_curves.append({"level": start_level, "speed": speed}) - start = end - speeds = [] - battery_curves.append({"level": row["end_level"], "speed": 0}) - else: - speed = car.get_charge_speed(row["end_level"]-row["start_level"], (stop_at-start_date).total_seconds()) - battery_curves.append({"level": row["start_level"], "speed": speed}) - battery_curves.append({"level": row["end_level"], "speed": speed}) - fig = px.line(battery_curves, x="level", y="speed") + charge = Database.get_charge(car.vin, start_date) + battery_curves = Charging.get_battery_curve(conn, charge, car) + battery_curves_dict = list(map(lambda bc: bc.__dict__, battery_curves)) + fig = px.line(battery_curves_dict, x="level", y="speed") fig.update_layout(xaxis_title="Battery %", yaxis_title="Charging speed in kW") return html.Div(Graph(figure=fig)) diff --git a/web/tools/Button.py b/psa-car-controller/web/tools/Button.py similarity index 100% rename from web/tools/Button.py rename to psa-car-controller/web/tools/Button.py diff --git a/web/tools/Switch.py b/psa-car-controller/web/tools/Switch.py similarity index 100% rename from web/tools/Switch.py rename to psa-car-controller/web/tools/Switch.py diff --git a/web/tools/figurefilter.py b/psa-car-controller/web/tools/figurefilter.py similarity index 98% rename from web/tools/figurefilter.py rename to psa-car-controller/web/tools/figurefilter.py index a8a699d..a186d43 100644 --- a/web/tools/figurefilter.py +++ b/psa-car-controller/web/tools/figurefilter.py @@ -1,11 +1,13 @@ import json +import logging from logging import DEBUG from dash import dcc from dash._utils import create_callback_id from dash.dependencies import Output, Input -from mylogger import logger +logger = logging.getLogger(__name__) + class Graph: diff --git a/web/utils.py b/psa-car-controller/web/tools/utils.py similarity index 100% rename from web/utils.py rename to psa-car-controller/web/tools/utils.py diff --git a/psa-car-controller/web/view/__init__.py b/psa-car-controller/web/view/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/web/view/config_views.py b/psa-car-controller/web/view/config_views.py similarity index 90% rename from web/view/config_views.py rename to psa-car-controller/web/view/config_views.py index 2fc3d5f..51ecac2 100644 --- a/web/view/config_views.py +++ b/psa-car-controller/web/view/config_views.py @@ -1,16 +1,20 @@ +import logging + from dash import callback_context, html, dcc from dash.exceptions import PreventUpdate from flask import request -from libs.psa.setup.app_decoder import firstLaunchConfig -from libs.config import Config -from mylogger import LOG_FILE, logger -from otp.otp import new_otp_session +from psa.otp.otp import new_otp_session +from psacc.application.psa_car_controller import PSACarController +from psa.setup.app_decoder import firstLaunchConfig +from common.mylogger import LOG_FILE from web.app import dash_app import dash_bootstrap_components as dbc from dash.dependencies import Output, Input, State -config = Config() +logger = logging.getLogger(__name__) + +app = PSACarController() login_config_layout = dbc.Row(dbc.Col(md=12, lg=2, className="m-3", children=[ dbc.Row(html.H2('Config')), dbc.Row(className="ms-2", children=[ @@ -127,11 +131,12 @@ def connectPSA(n_clicks, app_name, email, password, countrycode): # pylint: dis if ctx.triggered: try: res = firstLaunchConfig(app_name, email, password, countrycode) - config.load_app() - config.start_remote_control() + app.load_app() + app.start_remote_control() return dbc.Alert([res, html.A(" Go to otp config", href=request.url_root + "config_otp")], color="success") except Exception as e: res = str(e) + logger.exception(e) return dbc.Alert(res, color="danger") else: return "" @@ -144,7 +149,7 @@ def askCode(n_clicks): # pylint: disable=unused-argument ctx = callback_context if ctx.triggered: try: - config.myp.remote_client.get_sms_otp_code() + app.myp.remote_client.get_sms_otp_code() return dbc.Alert("Sms sent", color="success") except Exception as e: res = str(e) @@ -161,10 +166,10 @@ def finishOtp(n_clicks, code_pin, sms_code): # pylint: disable=unused-argument ctx = callback_context if ctx.triggered: try: - otp_session = new_otp_session(sms_code, code_pin, config.myp.remote_client.otp) - config.myp.remote_client.otp = otp_session - config.myp.save_config() - config.start_remote_control() + otp_session = new_otp_session(sms_code, code_pin, app.myp.remote_client.otp) + app.myp.remote_client.otp = otp_session + app.myp.save_config() + app.start_remote_control() return dbc.Alert(["OTP config finish !!! ", html.A("Go to home", href=request.url_root)], color="success") except Exception as e: diff --git a/web/view/control.py b/psa-car-controller/web/view/control.py similarity index 93% rename from web/view/control.py rename to psa-car-controller/web/view/control.py index aa643c9..84bb761 100644 --- a/web/view/control.py +++ b/psa-car-controller/web/view/control.py @@ -1,11 +1,14 @@ +import logging + import dash_bootstrap_components as dbc from dash import html -from my_psacc import MyPSACC -from mylogger import logger +from psacc.application.psa_client import PSAClient from web.tools.Button import Button from web.tools.Switch import Switch -from web.utils import card_value_div, create_card +from web.tools.utils import card_value_div, create_card + +logger = logging.getLogger(__name__) REFRESH_SWITCH = "refresh-switch" ABRP_SWITCH = 'abrp-switch' @@ -27,7 +30,7 @@ def get_control_tabs(config): label = car.vin else: label = car.label - myp: MyPSACC = config.myp + myp: PSAClient = config.myp el = [] buttons_row = [] if config.remote_control: diff --git a/web/view/views.py b/psa-car-controller/web/view/views.py similarity index 86% rename from web/view/views.py rename to psa-car-controller/web/view/views.py index e49aa7b..5381380 100644 --- a/web/view/views.py +++ b/psa-car-controller/web/view/views.py @@ -1,4 +1,5 @@ import json +import logging from typing import List from urllib.parse import parse_qs, urlparse @@ -8,41 +9,45 @@ from dash.dependencies import Output, Input, State from dash.exceptions import PreventUpdate from flask import jsonify, request, Response as FlaskResponse -import web.utils -from libs.car import Cars, Car -from libs.utils import RateLimitException -from mylogger import logger +from psacc.application.psa_car_controller import PSACarController +from psacc.model.car import Cars, Car +from common.utils import RateLimitException +from psacc.model.charge import Charge -from trip import Trips +from psacc.repository.trips import Trips -from libs.charging import Charging +from psacc.application.charging import Charging from web import figures from web.app import app, dash_app -from web.db import Database +from psacc.repository.db import Database +from web.tools.utils import diff_dashtable, unix_time_millis, get_marks_from_start_end, create_card from web.view.config_views import log_layout, config_layout -from web.utils import diff_dashtable, dash_date_to_datetime # pylint: disable=invalid-name from web.tools.figurefilter import FigureFilter -from web.utils import create_card -from libs.config import Config from web.view.control import get_control_tabs +logger = logging.getLogger(__name__) + EMPTY_DIV = "empty-div" CALLBACK_CREATED = False trips: Trips = Trips() chargings: List[dict] min_date = max_date = min_millis = max_millis = step = marks = cached_layout = None -CONFIG = Config() +APP = PSACarController() + + +def get_default_car(): + return APP.myp.vehicles_list[0] def add_header(el): return dbc.Row([dbc.Col(dcc.Link(html.H1('My car info'), href=dash_app.requests_pathname_external_prefix, - style={"text-decoration": "none"})), + style={"TextDecoration": "none"})), dbc.Col(dcc.Link(html.Img(src="assets/images/settings.svg", width="30veh"), - href=dash_app.requests_pathname_external_prefix+"config", + href=dash_app.requests_pathname_external_prefix + "config", className="float-end"))]), el @@ -59,12 +64,12 @@ def display_page(pathname, search): page = config_layout("login") elif pathname == "/log": page = log_layout() - elif not CONFIG.is_good: + elif not APP.is_good: page = dcc.Location(pathname=dash_app.requests_pathname_external_prefix + "config_login", id="config_redirect") elif pathname == "/config_otp": page = config_layout("otp") elif pathname == "/control": - page = get_control_tabs(CONFIG) + page = get_control_tabs(APP) else: page = serve_layout() if no_header: @@ -86,8 +91,10 @@ def create_callback(): # noqa: MC0001 for changed_line in diff_data: if changed_line['column_name'] == 'price': conn = Database.get_db() - if not Database.set_chargings_price(conn, dash_date_to_datetime(changed_line['start_at']), - changed_line['current_value']): + charge = Charge(changed_line['start_at']) + charge.price = changed_line['current_value'] + charge.vin = get_default_car().vin + if not Database.set_chargings_price(conn, charge): logger.error("Can't find line to update in the database") else: logger.debug("update price %s of %s", changed_line['current_value'], changed_line['start_at']) @@ -104,7 +111,7 @@ def create_callback(): # noqa: MC0001 is_open = False if active_cell is not None and active_cell["column_id"] in ["start_level", "end_level"] and not is_open: row = data[active_cell["row"]] - return figures.get_battery_curve_fig(row, CONFIG.myp.vehicles_list[0]), True + return figures.get_battery_curve_fig(row, APP.myp.vehicles_list[0]), True return "", False @dash_app.callback([Output("tab_trips_popup_graph", "children"), Output("tab_trips_popup", "is_open"), ], @@ -118,13 +125,14 @@ def create_callback(): # noqa: MC0001 return figures.get_altitude_fig(trips[active_cell["row_id"] - 1]), True return "", False + figures.CURRENCY = APP.config.General.currency CALLBACK_CREATED = True @app.route('/get_vehicles') def get_vehicules(): response = app.response_class( - response=json.dumps(CONFIG.myp.get_vehicles(), default=lambda car: car.to_dict()), + response=json.dumps(APP.myp.get_vehicles(), default=lambda car: car.to_dict()), status=200, mimetype='application/json' ) @@ -135,7 +143,7 @@ def get_vehicules(): def get_vehicle_info(vin): from_cache = int(request.args.get('from_cache', 0)) == 1 response = app.response_class( - response=json.dumps(CONFIG.myp.get_vehicle_info(vin, from_cache).to_dict(), default=str), + response=json.dumps(APP.myp.get_vehicle_info(vin, from_cache).to_dict(), default=str), status=200, mimetype='application/json' ) @@ -159,32 +167,32 @@ def get_style(): @app.route('/charge_now//') def charge_now(vin, charge): - return jsonify(CONFIG.myp.remote_client.charge_now(vin, charge != 0)) + return jsonify(APP.myp.remote_client.charge_now(vin, charge != 0)) @app.route('/charge_hour') def change_charge_hour(): - return jsonify(CONFIG.myp.remote_client.change_charge_hour(request.args['vin'], - request.args['hour'], - request.args['minute'])) + return jsonify(APP.myp.remote_client.change_charge_hour(request.args['vin'], + request.args['hour'], + request.args['minute'])) @app.route('/wakeup/') def wakeup(vin): try: - return jsonify(CONFIG.myp.remote_client.wakeup(vin)) + return jsonify(APP.myp.remote_client.wakeup(vin)) except RateLimitException: return jsonify({"error": "Wakeup rate limit exceeded"}) @app.route('/preconditioning//') def preconditioning(vin, activate): - return jsonify(CONFIG.myp.remote_client.preconditioning(vin, activate)) + return jsonify(APP.myp.remote_client.preconditioning(vin, activate)) @app.route('/position/') def get_position(vin): - res = CONFIG.myp.get_vehicle_info(vin) + res = APP.myp.get_vehicle_info(vin) try: coordinates = res.last_position.geometry.coordinates except AttributeError: @@ -204,14 +212,14 @@ def get_position(vin): def get_charge_control(): logger.info(request) vin = request.args['vin'] - charge_control = CONFIG.chc.get(vin) + charge_control = APP.chc.get(vin) if charge_control is None: return jsonify("error: VIN not in list") if 'hour' in request.args and 'minute' in request.args: charge_control.set_stop_hour([int(request.args["hour"]), int(request.args["minute"])]) if 'percentage' in request.args: charge_control.percentage_threshold = int(request.args['percentage']) - CONFIG.chc.save_config() + APP.chc.save_config() return jsonify(charge_control.get_dict()) @@ -227,12 +235,12 @@ def abrp(): token = request.args.get('token', None) if vin is not None and enable is not None: if enable == '1': - CONFIG.myp.abrp.abrp_enable_vin.add(vin) + APP.myp.abrp.abrp_enable_vin.add(vin) else: - CONFIG.myp.abrp.abrp_enable_vin.discard(vin) + APP.myp.abrp.abrp_enable_vin.discard(vin) if token is not None: - CONFIG.myp.abrp.token = token - return jsonify(dict(CONFIG.myp.abrp)) + APP.myp.abrp.token = token + return jsonify(dict(APP.myp.abrp)) @app.after_request @@ -250,8 +258,8 @@ def update_trips(): conn.close() min_date = None max_date = None - if CONFIG.is_good: - car = CONFIG.myp.vehicles_list[0] # todo handle multiple car + if APP.is_good: + car = get_default_car() # todo handle multiple car try: trips_by_vin = Trips.get_trips(Cars([car])) trips = trips_by_vin[car.vin] @@ -278,10 +286,10 @@ def update_trips(): # update for slider try: logger.debug("min_date:%s - max_date:%s", min_date, max_date) - min_millis = web.utils.unix_time_millis(min_date) - max_millis = web.utils.unix_time_millis(max_date) + min_millis = unix_time_millis(min_date) + max_millis = unix_time_millis(max_date) step = (max_millis - min_millis) / 100 - marks = web.utils.get_marks_from_start_end(min_date, max_date) + marks = get_marks_from_start_end(min_date, max_date) cached_layout = None # force regenerate layout figures.get_figures(car) except (ValueError, IndexError): @@ -387,7 +395,7 @@ def serve_layout(): try: - Charging.set_default_price() + Charging.set_default_price(get_default_car()) Database.set_db_callback(update_trips) update_trips() except (IndexError, TypeError): diff --git a/psa_connectedcar/__init__.py b/psa_connectedcar/__init__.py deleted file mode 100644 index 50495b2..0000000 --- a/psa_connectedcar/__init__.py +++ /dev/null @@ -1,155 +0,0 @@ -# coding: utf-8 - -# flake8: noqa - -""" - Groupe PSA Connected Car - WEB API B2C - - *PSA B2C Connected Car API* # Introduction This is the description of the *Groupe PSA Connected Car V2 API*. The speccification is is based on **OpenAPI Specification version 3** and can be displayed via [ReDoc](https://github.com/Rebilly/ReDoc)a or [Swagger](http://swagger.io). This API allows applications to fetch data from the connected Vehicles data platform. # Authentication PSA Connected Car APIs uses the [OAuth 2.0](https://tools.ietf.org/html/rfc6749) protocol for authentication and Authorization. any application require a valid [Access Token](https://tools.ietf.org/html/rfc6749#section-1.4) to access to user data. # Errors Error codes returned by all REST APIs comply with the standard. Nevertheless, PSA Services (callers) need to have more complete data structures (even when the answer is not Http-OK) to better detail the type of error by providing application code, message and a debugging code(for investigation purposes). The http code of the response is managed by the protocol itself (in the header). **Errors are returned as a generic error response:** * ```xError``` object model. # noqa: E501 - - OpenAPI spec version: 4.0 - - Generated by: https://github.com/swagger-api/swagger-codegen.git -""" - - -from __future__ import absolute_import - -# import apis into sdk package -from psa_connectedcar.api.trips_api import TripsApi -from psa_connectedcar.api.user_api import UserApi -from psa_connectedcar.api.vehicles_api import VehiclesApi - -# import ApiClient -from psa_connectedcar.api_client import ApiClient -from psa_connectedcar.configuration import Configuration -# import models into sdk package -from psa_connectedcar.models.adas import Adas -from psa_connectedcar.models.adas_park_assist import AdasParkAssist -from psa_connectedcar.models.alert import Alert -from psa_connectedcar.models.alert_end_position import AlertEndPosition -from psa_connectedcar.models.alert_links import AlertLinks -from psa_connectedcar.models.alert_msg_enum import AlertMsgEnum -from psa_connectedcar.models.alerts import Alerts -from psa_connectedcar.models.alerts_embedded import AlertsEmbedded -from psa_connectedcar.models.battery import Battery -from psa_connectedcar.models.bounded_program import BoundedProgram -from psa_connectedcar.models.charging_status_enum import ChargingStatusEnum -from psa_connectedcar.models.circle_zone import CircleZone -from psa_connectedcar.models.circle_zone_coordinates import CircleZoneCoordinates -from psa_connectedcar.models.collection_result import CollectionResult -from psa_connectedcar.models.collision import Collision -from psa_connectedcar.models.collision_links import CollisionLinks -from psa_connectedcar.models.collision_obj import CollisionObj -from psa_connectedcar.models.collision_obj_front import CollisionObjFront -from psa_connectedcar.models.collisions import Collisions -from psa_connectedcar.models.collisions_embedded import CollisionsEmbedded -from psa_connectedcar.models.created_at_field import CreatedAtField -from psa_connectedcar.models.data_monitor_trigger import DataMonitorTrigger -from psa_connectedcar.models.data_trigger import DataTrigger -from psa_connectedcar.models.default_alert_push import DefaultAlertPush -from psa_connectedcar.models.default_alert_push_attributes import DefaultAlertPushAttributes -from psa_connectedcar.models.doors_state import DoorsState -from psa_connectedcar.models.doors_state_opening import DoorsStateOpening -from psa_connectedcar.models.e_coaching import ECoaching -from psa_connectedcar.models.e_coaching_links import ECoachingLinks -from psa_connectedcar.models.e_coaching_scores import ECoachingScores -from psa_connectedcar.models.energy import Energy -from psa_connectedcar.models.energy_battery import EnergyBattery -from psa_connectedcar.models.energy_battery_health import EnergyBatteryHealth -from psa_connectedcar.models.energy_charging import EnergyCharging -from psa_connectedcar.models.engine import Engine -from psa_connectedcar.models.engine_oil import EngineOil -from psa_connectedcar.models.environment import Environment -from psa_connectedcar.models.environment_luminosity import EnvironmentLuminosity -from psa_connectedcar.models.event import Event -from psa_connectedcar.models.event_links import EventLinks -from psa_connectedcar.models.extension import Extension -from psa_connectedcar.models.extension_type import ExtensionType -from psa_connectedcar.models.geometry import Geometry -from psa_connectedcar.models.ignition import Ignition -from psa_connectedcar.models.index_range import IndexRange -from psa_connectedcar.models.kinetic import Kinetic -from psa_connectedcar.models.lighting import Lighting -from psa_connectedcar.models.link import Link -from psa_connectedcar.models.maintenance import Maintenance -from psa_connectedcar.models.maintenance_links import MaintenanceLinks -from psa_connectedcar.models.maintenance_obj import MaintenanceObj -from psa_connectedcar.models.monitor import Monitor -from psa_connectedcar.models.monitor_id import MonitorId -from psa_connectedcar.models.monitor_links import MonitorLinks -from psa_connectedcar.models.monitor_parameter import MonitorParameter -from psa_connectedcar.models.monitor_parameter_trigger_param import MonitorParameterTriggerParam -from psa_connectedcar.models.monitor_ref import MonitorRef -from psa_connectedcar.models.monitor_ref_links import MonitorRefLinks -from psa_connectedcar.models.monitor_status import MonitorStatus -from psa_connectedcar.models.monitor_status_setter import MonitorStatusSetter -from psa_connectedcar.models.monitor_subscribe import MonitorSubscribe -from psa_connectedcar.models.monitor_subscribe_batch_notify import MonitorSubscribeBatchNotify -from psa_connectedcar.models.monitor_subscribe_retry_policy import MonitorSubscribeRetryPolicy -from psa_connectedcar.models.monitor_trigger import MonitorTrigger -from psa_connectedcar.models.monitor_webhook import MonitorWebhook -from psa_connectedcar.models.monitor_webhook_attributes import MonitorWebhookAttributes -from psa_connectedcar.models.monitors import Monitors -from psa_connectedcar.models.monitors_embedded import MonitorsEmbedded -from psa_connectedcar.models.overall_autonomy import OverallAutonomy -from psa_connectedcar.models.point import Point -from psa_connectedcar.models.polygon_zone import PolygonZone -from psa_connectedcar.models.position import Position -from psa_connectedcar.models.position_properties import PositionProperties -from psa_connectedcar.models.preconditioning import Preconditioning -from psa_connectedcar.models.preconditioning_air_conditioning import PreconditioningAirConditioning -from psa_connectedcar.models.preconditioning_program import PreconditioningProgram -from psa_connectedcar.models.privacy import Privacy -from psa_connectedcar.models.program import Program -from psa_connectedcar.models.program_occurence import ProgramOccurence -from psa_connectedcar.models.safety import Safety -from psa_connectedcar.models.service_type import ServiceType -from psa_connectedcar.models.status import Status -from psa_connectedcar.models.status_embedded import StatusEmbedded -from psa_connectedcar.models.status_extension_type import StatusExtensionType -from psa_connectedcar.models.status_links import StatusLinks -from psa_connectedcar.models.tab_links import TabLinks -from psa_connectedcar.models.telemetry import Telemetry -from psa_connectedcar.models.telemetry_embedded import TelemetryEmbedded -from psa_connectedcar.models.telemetry_enum import TelemetryEnum -from psa_connectedcar.models.telemetry_extension import TelemetryExtension -from psa_connectedcar.models.telemetry_extension_type import TelemetryExtensionType -from psa_connectedcar.models.telemetry_message import TelemetryMessage -from psa_connectedcar.models.telemetry_message_embedded import TelemetryMessageEmbedded -from psa_connectedcar.models.telemetry_message_vehicle import TelemetryMessageVehicle -from psa_connectedcar.models.telemetry_message_vehicle_braking_system import TelemetryMessageVehicleBrakingSystem -from psa_connectedcar.models.telemetry_message_vehicle_transmission import TelemetryMessageVehicleTransmission -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox import TelemetryMessageVehicleTransmissionGearbox -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox_gear import TelemetryMessageVehicleTransmissionGearboxGear -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox_mode import TelemetryMessageVehicleTransmissionGearboxMode -from psa_connectedcar.models.time_monitor_trigger import TimeMonitorTrigger -from psa_connectedcar.models.time_range import TimeRange -from psa_connectedcar.models.time_stamped import TimeStamped -from psa_connectedcar.models.time_trigger import TimeTrigger -from psa_connectedcar.models.time_zone_monitor_trigger import TimeZoneMonitorTrigger -from psa_connectedcar.models.time_zone_trigger import TimeZoneTrigger -from psa_connectedcar.models.trip import Trip -from psa_connectedcar.models.trip_avg_consumption import TripAvgConsumption -from psa_connectedcar.models.trip_links import TripLinks -from psa_connectedcar.models.trips import Trips -from psa_connectedcar.models.trips_embedded import TripsEmbedded -from psa_connectedcar.models.updated_field import UpdatedField -from psa_connectedcar.models.url import Url -from psa_connectedcar.models.user import User -from psa_connectedcar.models.user_embedded import UserEmbedded -from psa_connectedcar.models.user_links import UserLinks -from psa_connectedcar.models.vect2_d import Vect2D -from psa_connectedcar.models.vehicle import Vehicle -from psa_connectedcar.models.vehicle_engine import VehicleEngine -from psa_connectedcar.models.vehicle_links import VehicleLinks -from psa_connectedcar.models.vehicle_odometer import VehicleOdometer -from psa_connectedcar.models.vehicles import Vehicles -from psa_connectedcar.models.vehicles_embedded import VehiclesEmbedded -from psa_connectedcar.models.way_points import WayPoints -from psa_connectedcar.models.way_points_embedded import WayPointsEmbedded -from psa_connectedcar.models.x_error import XError -from psa_connectedcar.models.zone_monitor_trigger import ZoneMonitorTrigger -from psa_connectedcar.models.zone_trigger import ZoneTrigger -from psa_connectedcar.models.zone_trigger_place import ZoneTriggerPlace -from psa_connectedcar.models.zone_trigger_place_center import ZoneTriggerPlaceCenter diff --git a/psa_connectedcar/api/__init__.py b/psa_connectedcar/api/__init__.py deleted file mode 100644 index a73e183..0000000 --- a/psa_connectedcar/api/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from __future__ import absolute_import - -# flake8: noqa - -# import apis into api package -from psa_connectedcar.api.trips_api import TripsApi -from psa_connectedcar.api.user_api import UserApi -from psa_connectedcar.api.vehicles_api import VehiclesApi diff --git a/psa_connectedcar/models/__init__.py b/psa_connectedcar/models/__init__.py deleted file mode 100644 index 757a026..0000000 --- a/psa_connectedcar/models/__init__.py +++ /dev/null @@ -1,146 +0,0 @@ -# coding: utf-8 - -# flake8: noqa -""" - Groupe PSA Connected Car - WEB API B2C - - *PSA B2C Connected Car API* # Introduction This is the description of the *Groupe PSA Connected Car V2 API*. The speccification is is based on **OpenAPI Specification version 3** and can be displayed via [ReDoc](https://github.com/Rebilly/ReDoc)a or [Swagger](http://swagger.io). This API allows applications to fetch data from the connected Vehicles data platform. # Authentication PSA Connected Car APIs uses the [OAuth 2.0](https://tools.ietf.org/html/rfc6749) protocol for authentication and Authorization. any application require a valid [Access Token](https://tools.ietf.org/html/rfc6749#section-1.4) to access to user data. # Errors Error codes returned by all REST APIs comply with the standard. Nevertheless, PSA Services (callers) need to have more complete data structures (even when the answer is not Http-OK) to better detail the type of error by providing application code, message and a debugging code(for investigation purposes). The http code of the response is managed by the protocol itself (in the header). **Errors are returned as a generic error response:** * ```xError``` object model. # noqa: E501 - - OpenAPI spec version: 4.0 - - Generated by: https://github.com/swagger-api/swagger-codegen.git -""" - - -from __future__ import absolute_import - -# import models into model package -from psa_connectedcar.models.adas import Adas -from psa_connectedcar.models.adas_park_assist import AdasParkAssist -from psa_connectedcar.models.alert import Alert -from psa_connectedcar.models.alert_end_position import AlertEndPosition -from psa_connectedcar.models.alert_links import AlertLinks -from psa_connectedcar.models.alert_msg_enum import AlertMsgEnum -from psa_connectedcar.models.alerts import Alerts -from psa_connectedcar.models.alerts_embedded import AlertsEmbedded -from psa_connectedcar.models.battery import Battery -from psa_connectedcar.models.bounded_program import BoundedProgram -from psa_connectedcar.models.charging_status_enum import ChargingStatusEnum -from psa_connectedcar.models.circle_zone import CircleZone -from psa_connectedcar.models.circle_zone_coordinates import CircleZoneCoordinates -from psa_connectedcar.models.collection_result import CollectionResult -from psa_connectedcar.models.collision import Collision -from psa_connectedcar.models.collision_links import CollisionLinks -from psa_connectedcar.models.collision_obj import CollisionObj -from psa_connectedcar.models.collision_obj_front import CollisionObjFront -from psa_connectedcar.models.collisions import Collisions -from psa_connectedcar.models.collisions_embedded import CollisionsEmbedded -from psa_connectedcar.models.created_at_field import CreatedAtField -from psa_connectedcar.models.data_monitor_trigger import DataMonitorTrigger -from psa_connectedcar.models.data_trigger import DataTrigger -from psa_connectedcar.models.default_alert_push import DefaultAlertPush -from psa_connectedcar.models.default_alert_push_attributes import DefaultAlertPushAttributes -from psa_connectedcar.models.doors_state import DoorsState -from psa_connectedcar.models.doors_state_opening import DoorsStateOpening -from psa_connectedcar.models.e_coaching import ECoaching -from psa_connectedcar.models.e_coaching_links import ECoachingLinks -from psa_connectedcar.models.e_coaching_scores import ECoachingScores -from psa_connectedcar.models.energy import Energy -from psa_connectedcar.models.energy_battery import EnergyBattery -from psa_connectedcar.models.energy_battery_health import EnergyBatteryHealth -from psa_connectedcar.models.energy_charging import EnergyCharging -from psa_connectedcar.models.engine import Engine -from psa_connectedcar.models.engine_oil import EngineOil -from psa_connectedcar.models.environment import Environment -from psa_connectedcar.models.environment_luminosity import EnvironmentLuminosity -from psa_connectedcar.models.event import Event -from psa_connectedcar.models.event_links import EventLinks -from psa_connectedcar.models.extension import Extension -from psa_connectedcar.models.extension_type import ExtensionType -from psa_connectedcar.models.geometry import Geometry -from psa_connectedcar.models.ignition import Ignition -from psa_connectedcar.models.index_range import IndexRange -from psa_connectedcar.models.kinetic import Kinetic -from psa_connectedcar.models.lighting import Lighting -from psa_connectedcar.models.link import Link -from psa_connectedcar.models.maintenance import Maintenance -from psa_connectedcar.models.maintenance_links import MaintenanceLinks -from psa_connectedcar.models.maintenance_obj import MaintenanceObj -from psa_connectedcar.models.monitor import Monitor -from psa_connectedcar.models.monitor_id import MonitorId -from psa_connectedcar.models.monitor_links import MonitorLinks -from psa_connectedcar.models.monitor_parameter import MonitorParameter -from psa_connectedcar.models.monitor_parameter_trigger_param import MonitorParameterTriggerParam -from psa_connectedcar.models.monitor_ref import MonitorRef -from psa_connectedcar.models.monitor_ref_links import MonitorRefLinks -from psa_connectedcar.models.monitor_status import MonitorStatus -from psa_connectedcar.models.monitor_status_setter import MonitorStatusSetter -from psa_connectedcar.models.monitor_subscribe import MonitorSubscribe -from psa_connectedcar.models.monitor_subscribe_batch_notify import MonitorSubscribeBatchNotify -from psa_connectedcar.models.monitor_subscribe_retry_policy import MonitorSubscribeRetryPolicy -from psa_connectedcar.models.monitor_trigger import MonitorTrigger -from psa_connectedcar.models.monitor_webhook import MonitorWebhook -from psa_connectedcar.models.monitor_webhook_attributes import MonitorWebhookAttributes -from psa_connectedcar.models.monitors import Monitors -from psa_connectedcar.models.monitors_embedded import MonitorsEmbedded -from psa_connectedcar.models.overall_autonomy import OverallAutonomy -from psa_connectedcar.models.point import Point -from psa_connectedcar.models.polygon_zone import PolygonZone -from psa_connectedcar.models.position import Position -from psa_connectedcar.models.position_properties import PositionProperties -from psa_connectedcar.models.preconditioning import Preconditioning -from psa_connectedcar.models.preconditioning_air_conditioning import PreconditioningAirConditioning -from psa_connectedcar.models.preconditioning_program import PreconditioningProgram -from psa_connectedcar.models.privacy import Privacy -from psa_connectedcar.models.program import Program -from psa_connectedcar.models.program_occurence import ProgramOccurence -from psa_connectedcar.models.safety import Safety -from psa_connectedcar.models.service_type import ServiceType -from psa_connectedcar.models.status import Status -from psa_connectedcar.models.status_embedded import StatusEmbedded -from psa_connectedcar.models.status_extension_type import StatusExtensionType -from psa_connectedcar.models.status_links import StatusLinks -from psa_connectedcar.models.tab_links import TabLinks -from psa_connectedcar.models.telemetry import Telemetry -from psa_connectedcar.models.telemetry_embedded import TelemetryEmbedded -from psa_connectedcar.models.telemetry_enum import TelemetryEnum -from psa_connectedcar.models.telemetry_extension import TelemetryExtension -from psa_connectedcar.models.telemetry_extension_type import TelemetryExtensionType -from psa_connectedcar.models.telemetry_message import TelemetryMessage -from psa_connectedcar.models.telemetry_message_embedded import TelemetryMessageEmbedded -from psa_connectedcar.models.telemetry_message_vehicle import TelemetryMessageVehicle -from psa_connectedcar.models.telemetry_message_vehicle_braking_system import TelemetryMessageVehicleBrakingSystem -from psa_connectedcar.models.telemetry_message_vehicle_transmission import TelemetryMessageVehicleTransmission -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox import TelemetryMessageVehicleTransmissionGearbox -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox_gear import TelemetryMessageVehicleTransmissionGearboxGear -from psa_connectedcar.models.telemetry_message_vehicle_transmission_gearbox_mode import TelemetryMessageVehicleTransmissionGearboxMode -from psa_connectedcar.models.time_monitor_trigger import TimeMonitorTrigger -from psa_connectedcar.models.time_range import TimeRange -from psa_connectedcar.models.time_stamped import TimeStamped -from psa_connectedcar.models.time_trigger import TimeTrigger -from psa_connectedcar.models.time_zone_monitor_trigger import TimeZoneMonitorTrigger -from psa_connectedcar.models.time_zone_trigger import TimeZoneTrigger -from psa_connectedcar.models.trip import Trip -from psa_connectedcar.models.trip_avg_consumption import TripAvgConsumption -from psa_connectedcar.models.trip_links import TripLinks -from psa_connectedcar.models.trips import Trips -from psa_connectedcar.models.trips_embedded import TripsEmbedded -from psa_connectedcar.models.updated_field import UpdatedField -from psa_connectedcar.models.url import Url -from psa_connectedcar.models.user import User -from psa_connectedcar.models.user_embedded import UserEmbedded -from psa_connectedcar.models.user_links import UserLinks -from psa_connectedcar.models.vect2_d import Vect2D -from psa_connectedcar.models.vehicle import Vehicle -from psa_connectedcar.models.vehicle_engine import VehicleEngine -from psa_connectedcar.models.vehicle_links import VehicleLinks -from psa_connectedcar.models.vehicle_odometer import VehicleOdometer -from psa_connectedcar.models.vehicles import Vehicles -from psa_connectedcar.models.vehicles_embedded import VehiclesEmbedded -from psa_connectedcar.models.way_points import WayPoints -from psa_connectedcar.models.way_points_embedded import WayPointsEmbedded -from psa_connectedcar.models.x_error import XError -from psa_connectedcar.models.zone_monitor_trigger import ZoneMonitorTrigger -from psa_connectedcar.models.zone_trigger import ZoneTrigger -from psa_connectedcar.models.zone_trigger_place import ZoneTriggerPlace -from psa_connectedcar.models.zone_trigger_place_center import ZoneTriggerPlaceCenter diff --git a/requirements.txt b/requirements.txt index 17b3de9..ae46ddb 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ cryptography>=2.6 Werkzeug>=1.0.0 flask>=1.0.4 dash_bootstrap_components>=1 +configupdater>=3.0 pandas oauth2_client requests @@ -16,10 +17,11 @@ geojson reverse_geocode androguard pycryptodomex +pydantic +ruamel.yaml>=0.15.0 #swagger req certifi >= 14.05.14 six >= 1.10 python_dateutil >= 2.5.3 urllib3 >= 1.15.1 - diff --git a/test/test_config.py b/test/test_config.py new file mode 100644 index 0000000..3dfdf6b --- /dev/null +++ b/test/test_config.py @@ -0,0 +1,47 @@ +import os +import unittest +from configparser import ConfigParser +from unittest.mock import MagicMock + +from configupdater import ConfigUpdater + +from common.mylogger import my_logger +from psacc.repository.config_repository import ConfigRepository + + +class TestUnit(unittest.TestCase): + def test_read_config(self): + config = ConfigRepository.read_config() + + def test_read_old_config(self): + old_config = ConfigUpdater() + old_config_str = """[General] +currency = € + +[Electricity config] +day price = 42 +night price = 0.1 +night hour start = 1h00 +night hour end = 4h42 + +""" + ConfigRepository._read_file = MagicMock(return_value=old_config_str) + ConfigRepository._write = MagicMock() + conf = ConfigRepository.read_config() + conf.write_config(conf) + config_written: ConfigParser = ConfigRepository._write.call_args_list[0][0][1] + self.assertEqual(config_written["General"]["currency"].value, "€") + self.assertEqual(config_written["Electricity config"]["day price"].value, 42) + print(config_written) + + def test_read_non_existent_config(self): + self.assertRaises(FileNotFoundError, lambda :ConfigRepository._read_file("nonexistent.ini")) + + def test_read_config_non_existent_config(self): + result = ConfigRepository.read_config("nonexistent.ini") + expected_result = ConfigRepository.config_file_to_dto(ConfigRepository.get_default_config()) + self.assertEqual(result,expected_result) + +if __name__ == '__main__': + my_logger(handler_level=os.environ.get("DEBUG_LEVEL", 20)) + unittest.main() diff --git a/test/test_unit.py b/test/test_unit.py index 738ea5f..b0cf03c 100644 --- a/test/test_unit.py +++ b/test/test_unit.py @@ -4,28 +4,30 @@ import os import unittest from datetime import datetime, timedelta +import reverse_geocode from pytz import UTC -import libs.config -from libs.psa.setup.app_decoder import GITHUB_USER, GITHUB_REPO -from libs.psa.setup.github import github_file_need_to_be_downloaded -from psa_connectedcar import ApiClient -import psa_connectedcar as psacc -import reverse_geocode -from libs.car import Car, Cars -from libs.charging import Charging -from libs.elec_price import ElecPrice -from my_psacc import MyPSACC -from ecomix import Ecomix -from libs.car_model import CarModel -from mylogger import my_logger -from otp.otp import load_otp, save_otp -from charge_control import ChargeControls -from test.utils import DATA_DIR, record_position, latitude, longitude, date0, date1, date2, date3, record_charging, \ +import psa.connected_car_api + +from common.mylogger import my_logger +from common.utils import parse_hour, RateLimitException, rate_limit +from psa.otp.otp import load_otp, save_otp +from psa.setup.app_decoder import get_content_from_apk, GITHUB_USER, GITHUB_REPO +from psa.setup.github import github_file_need_to_be_downloaded +from psa.connected_car_api import ApiClient +from psacc.application.charge_control import ChargeControls +from psacc.application.charging import Charging +from psacc.application.ecomix import Ecomix +from psacc.application.psa_client import PSAClient +from psacc.model.car import Car, Cars +from psacc.repository import config_repository +from psacc.repository.car_model import CarModelRepository +from psacc.repository.config_repository import ConfigRepository +from psacc.repository.db import Database +from psacc.repository.trips import Trips +from psacc.utils.utils import get_temp +from utils import DATA_DIR, record_position, latitude, longitude, date0, date1, date2, date3, record_charging, \ vehicule_list, get_new_test_db, get_date, date4 -from trip import Trips -from libs.utils import get_temp, parse_hour, rate_limit, RateLimitException -from web.db import Database from web.figures import get_figures, get_battery_curve_fig, get_altitude_fig from deepdiff import DeepDiff @@ -65,21 +67,19 @@ class TestUnit(unittest.TestCase): def test_mypsacc(self): if self.test_online: - myp = MyPSACC.load_config("config.json") + myp = PSAClient.load_config("config.json") myp.refresh_token() myp.get_vehicles() car = myp.vehicles_list[0] myp.abrp.abrp_enable_vin.add(car.vin) - res = myp.get_vehicle_info(myp.vehicles_list[0].vin) + myp.get_vehicle_info(myp.vehicles_list[0].vin) myp.abrp.call(car, 22.1) - libs.config.Config().myp = myp - libs.config.Config().save_config() assert isinstance(get_temp(str(latitude), str(longitude), myp.weather_api), float) def test_car_model(self): - assert CarModel.find_model_by_vin("VR3UHZKXZL").name == "e-208" - assert CarModel.find_model_by_vin("VR3UKZKXZM").name == "e-2008" - assert CarModel.find_model_by_vin("VXKUHZKXZL").name == "corsa-e" + assert CarModelRepository().find_model_by_vin("VR3UHZKXZL").name == "e-208" + assert CarModelRepository().find_model_by_vin("VR3UKZKXZM").name == "e-2008" + assert CarModelRepository().find_model_by_vin("VXKUHZKXZL").name == "corsa-e" def test_c02_signal_cache(self): start = datetime.utcnow().replace(tzinfo=UTC) - timedelta(minutes=30) @@ -89,6 +89,8 @@ class TestUnit(unittest.TestCase): [start + timedelta(minutes=2), 20], [start + timedelta(minutes=3), 30]]} assert Ecomix.get_co2_from_signal_cache(start, end, "FR") == 20 + Ecomix.clean_cache() + self.assertEqual(3, len(Ecomix._cache["FR"])) def test_c02_signal(self): if self.test_online: @@ -106,10 +108,25 @@ class TestUnit(unittest.TestCase): charge_control.save_config(force=True) def test_battery_curve(self): + vin = self.vehicule_list[0].vin get_new_test_db() record_charging() - res = Database.get_battery_curve(Database.get_db(), date0, date4, self.vehicule_list[0].vin) - assert len(res) == 3 + charge = Database.get_last_charge(vin) + self.assertEqual(charge.stop_at, date4) + res = Database.get_battery_curve(Database.get_db(), date0, date4, vin) + self.assertEqual(4, len(res)) + + def test_set_charge_price(self): + vin = self.vehicule_list[0].vin + get_new_test_db() + record_charging() + charge = Database.get_last_charge(vin) + charge.price = 42 + conn = Database.get_db() + Database.set_chargings_price(conn, charge) + conn.close() + res = Database.get_charge(vin, charge.start_at) + self.assertEqual(charge.price, res.price) def test_sdk(self): res = { @@ -133,13 +150,13 @@ class TestUnit(unittest.TestCase): 'href': 'https://api.groupe-psa.com/connectedcar/v4/user/vehicles/myid'}}, 'timed.odometer': {'createdAt': None, 'mileage': 1107.1}, 'updatedAt': '2021-04-01T16:17:01Z'} api = ApiClient() - status: psacc.models.status.Status = api._ApiClient__deserialize(res, "Status") + status: psa.connected_car_api.models.status.Status = api._ApiClient__deserialize(res, "Status") geocode_res = reverse_geocode.search([(status.last_position.geometry.coordinates[:2])[::-1]])[0] assert geocode_res["country_code"] == "DE" get_new_test_db() car = Car("XX", "vid", "Peugeot") car.status = status - myp = MyPSACC.load_config(DATA_DIR + "config.json") + myp = PSAClient.load_config(DATA_DIR + "config.json") myp.record_info(car) assert "features" in json.loads(Database.get_recorded_position()) # electric should be first @@ -147,7 +164,7 @@ class TestUnit(unittest.TestCase): def test_record_position_charging(self): get_new_test_db() - ElecPrice.CONFIG_FILENAME = DATA_DIR + "config.ini" + config_repository.CONFIG_FILENAME = DATA_DIR + "config.ini" car = self.vehicule_list[0] record_position() Database.add_altitude_to_db(Database.get_db()) @@ -164,7 +181,7 @@ class TestUnit(unittest.TestCase): 'duration': 40.0, 'speed_average': 28.5, 'distance': 19.0, 'mileage': 30.0, 'altitude_diff': 2, 'id': 1, 'consumption': 4.6}) - Charging.elec_price = ElecPrice.read_config() + Charging.elec_price = ConfigRepository.read_config(DATA_DIR + "config.ini").Electricity_config start_level = 40 end_level = 85 Charging.record_charging(car, "InProgress", date0, start_level, latitude, longitude, None, "slow", 20, 60) @@ -188,12 +205,13 @@ class TestUnit(unittest.TestCase): assert get_figures(car) row = {"start_at": date0.strftime('%Y-%m-%dT%H:%M:%S.000Z'), "stop_at": date3.strftime('%Y-%m-%dT%H:%M:%S.000Z'), "start_level": start_level, "end_level": end_level} - assert get_battery_curve_fig(row, car) is not None + battery_curve_fix = get_battery_curve_fig(row, car) + assert battery_curve_fix is not None assert get_altitude_fig(trip) is not None def test_fuel_car(self): get_new_test_db() - ElecPrice.CONFIG_FILENAME = DATA_DIR + "config.ini" + config_repository.CONFIG_FILENAME = DATA_DIR + "config.ini" car = self.vehicule_list[1] Database.record_position(None, car.vin, 11, latitude, longitude, 22, date0, 40, 30, False) Database.record_position(None, car.vin, 20, latitude, longitude, 22, date1, 35, 29, False) @@ -212,11 +230,11 @@ class TestUnit(unittest.TestCase): 'altitude_diff': 0, 'id': 1, 'consumption': 1.32, - 'consumption_fuel_km': 10.53}]) + 'consumption_fuel_km': 4.53}]) def test_none_mileage(self): get_new_test_db() - ElecPrice.CONFIG_FILENAME = DATA_DIR + "config.ini" + config_repository.CONFIG_FILENAME = DATA_DIR + "config.ini" car = self.vehicule_list[1] Database.record_position(None, car.vin, None, latitude, longitude, 22, get_date(1), 40, 30, False) Database.record_position(None, car.vin, None, latitude, longitude, 22, get_date(2), 35, 29, False) @@ -241,7 +259,7 @@ class TestUnit(unittest.TestCase): 'altitude_diff': 0, 'id': 1, 'consumption': 1.32, - 'consumption_fuel_km': 10.53}]) + 'consumption_fuel_km': 4.53}]) def test_db_callback(self): old_dummy_value = dummy_value @@ -269,7 +287,6 @@ class TestUnit(unittest.TestCase): pass def test_parse_apk(self): - from libs.psa.setup.app_decoder import get_content_from_apk filename = "mypeugeot.apk" try: os.remove(filename) diff --git a/test/utils.py b/test/utils.py index 5d1423f..c20df01 100644 --- a/test/utils.py +++ b/test/utils.py @@ -5,9 +5,9 @@ from datetime import timedelta, datetime import pytz -from libs.car import Car, Cars -from libs.charging import Charging -from web.db import Database +from psacc.application.charging import Charging +from psacc.model.car import Cars, Car +from psacc.repository.db import Database DATA_DIR = os.path.dirname(os.path.realpath(__file__)) + "/data/" latitude = 47.2183 @@ -40,6 +40,7 @@ def record_position(): Database.record_position(None, car.vin, 11, latitude, longitude - 0.05, None, date0, 40, None, False) Database.record_position(None, car.vin, 20, latitude, longitude, 32, date1, 35, None, False) Database.record_position(None, car.vin, 30, latitude, longitude, 42, date2, 30, None, False) + Database.record_position(None, car.vin, None, latitude, longitude, 42, date2, 30, None, False) def record_charging():