Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
ea41953
Create __init__.py
mekrapp Jun 15, 2024
6c05372
Add files via upload
mekrapp Jun 15, 2024
55f6939
Add files via upload
mekrapp Jun 15, 2024
38c4aca
Add files via upload
mekrapp Jun 15, 2024
c90a586
Add files via upload
mekrapp Jun 15, 2024
08d7c3e
Update soc.py
mekrapp Jun 16, 2024
d62c77b
Update soc.py
mekrapp Jun 16, 2024
fbfd4ec
Update soc.py
mekrapp Jun 16, 2024
320c0b3
Update soc.py
mekrapp Jun 21, 2024
3ba67d2
Update responses.py
mekrapp Jun 21, 2024
f6c9754
Update packages/modules/vehicles/leaf/soc.py
mekrapp Jun 22, 2024
a03caf6
Update soc.py
mekrapp Jun 22, 2024
b93dd5f
Update __init__.py
mekrapp Aug 21, 2024
1c142c7
Update __init__.py
mekrapp Aug 21, 2024
38f7973
Update __init__.py
mekrapp Aug 21, 2024
f4db4e4
Merge branch 'openWB:master' into master
mekrapp Aug 21, 2024
da78bd8
Update __init__.py
mekrapp Aug 21, 2024
30e305d
Merge pull request #1 from mekrapp/mekrapp-patch-1
mekrapp Aug 21, 2024
a867764
Merge branch 'openWB:master' into master
mekrapp Aug 24, 2024
9a02623
Update pycarwings2.py
mekrapp Aug 24, 2024
69d663f
Update pycarwings2.py
mekrapp Aug 24, 2024
f8ee104
Update __init__.py
mekrapp Aug 24, 2024
c629c1e
Update soc.py
mekrapp Aug 24, 2024
920abad
Update __init__.py
mekrapp Aug 24, 2024
6ce31f1
Delete packages/modules/vehicles/leaf/__init__.py
mekrapp Aug 24, 2024
9b6a833
Add files via upload
mekrapp Aug 24, 2024
2d9d5b9
Update requirements.txt
mekrapp Aug 29, 2024
c41725f
Update packages/modules/vehicles/leaf/soc.py
mekrapp Aug 30, 2024
4d8783f
Delete packages/modules/vehicles/leaf/pycarwings2.py
mekrapp Aug 30, 2024
8f87879
Delete packages/modules/vehicles/leaf/responses.py
mekrapp Aug 30, 2024
fbef254
Delete packages/modules/vehicles/leaf/soc.py
mekrapp Mar 7, 2025
10bc2b2
Add files via upload
mekrapp Mar 7, 2025
b59ce84
Add files via upload
mekrapp Mar 8, 2025
d380e3d
Add files via upload
mekrapp Mar 8, 2025
e3aba8f
Add files via upload
mekrapp Mar 8, 2025
44aaa36
Add files via upload
mekrapp Mar 8, 2025
b8fb70a
Update api.py
mekrapp Mar 11, 2025
625779d
Update api.py
mekrapp Mar 11, 2025
295c64a
Update api.py
mekrapp Mar 11, 2025
02f627e
Update config.py
mekrapp Mar 14, 2025
9d26c25
Update soc.py
mekrapp Mar 14, 2025
5582f2c
Update api.py
mekrapp Mar 14, 2025
4553365
Update config.py
mekrapp Mar 16, 2025
cd7afcb
Update api.py
mekrapp Mar 16, 2025
8d95c00
Update api.py
mekrapp Mar 16, 2025
c49fbad
Update api.py
mekrapp Mar 16, 2025
973b6bf
Update api.py
mekrapp Mar 17, 2025
03cb6df
Update soc.py
mekrapp Mar 18, 2025
5b2978d
Update api.py
mekrapp Mar 18, 2025
cdcd2c7
Delete packages/modules/vehicles/leaf/api_wo_CarState.py
mekrapp Mar 18, 2025
5a6a90b
Delete packages/modules/vehicles/leaf/test_fetch_soc.py
mekrapp Mar 18, 2025
557e2dc
Merge branch 'master' into master
mekrapp Mar 19, 2025
b9e30cf
Update soc.py
mekrapp Mar 19, 2025
5d280ea
Update api.py
mekrapp Mar 19, 2025
dc9c8d4
Update api.py
mekrapp Mar 19, 2025
d647c46
Merge branch 'openWB:master' into master
mekrapp Mar 26, 2025
6196514
Merge branch 'openWB:master' into master
mekrapp Mar 27, 2025
8e24b99
Merge branch 'openWB:master' into master
mekrapp Mar 31, 2025
a6bff5c
Merge branch 'openWB:master' into master
mekrapp Apr 1, 2025
eb48e5a
Merge branch 'openWB:master' into master
mekrapp Apr 3, 2025
adc0dfc
Merge branch 'openWB:master' into master
mekrapp Apr 3, 2025
796144f
Merge branch 'openWB:master' into master
mekrapp Apr 5, 2025
4f051da
Merge branch 'openWB:master' into master
mekrapp Apr 7, 2025
1b93125
Update soc.py
mekrapp Apr 10, 2025
d3161f2
Merge branch 'openWB:master' into master
mekrapp Apr 10, 2025
b1d8012
Update soc.py
mekrapp Apr 10, 2025
5639687
Update soc.py
mekrapp Apr 10, 2025
a1a03a9
Merge branch 'openWB:master' into master
mekrapp Apr 10, 2025
b31a094
Merge branch 'openWB:master' into master
mekrapp Apr 11, 2025
3ec4c07
Mock pycarwings3 for pytest
LKuemmel Apr 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/modules/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
sys.modules['skodaconnect.Connection'] = type(sys)('skodaconnect.Connection')
sys.modules['socketserver'] = type(sys)('socketserver')
sys.modules['grpc'] = type(sys)('grpc')
sys.modules['pycarwings3'] = type(sys)('pycarwings3')


# sys.modules['telnetlib3'] = type(sys)('telnetlib3')
Expand Down
Empty file.
77 changes: 77 additions & 0 deletions packages/modules/vehicles/leaf/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#!/usr/bin/env python3
import asyncio
import logging
from datetime import datetime, timezone

from modules.common.component_state import CarState

import pycarwings3

log = logging.getLogger(__name__)


async def _fetch_soc(username, password, region, vehicle) -> CarState:

async def getNissanSession():
# open HTTPS session with Nissan server
log.debug("vehicle%s: login = %s, region = %s" % (vehicle, username, region))
session = pycarwings3.Session(username, password, region)
leaf = await session.get_leaf()
await asyncio.sleep(1)
return leaf

async def readSoc(leaf) -> CarState:
# get SoC & range & time stamp from Nissan server
leaf_info = await leaf.get_latest_battery_status()
soc = float(leaf_info.battery_percent)
log.debug("vehicle%s: Battery State of Charge %s" % (vehicle, soc))
range = int(leaf_info.answer["BatteryStatusRecords"]["CruisingRangeAcOff"])/1000
log.debug("vehicle%s: Cruising range AC Off %s" % (vehicle, range))
time_stamp_str_utc = leaf_info.answer["BatteryStatusRecords"]["NotificationDateAndTime"]
soc_time = datetime.strptime(f"{time_stamp_str_utc}", "%Y/%m/%d %H:%M").replace(tzinfo=timezone.utc)
log.debug("vehicle%s: Date&Time of SoC (UTC) %s" % (vehicle, soc_time))
soc_timestamp = soc_time.timestamp()
log.debug("vehicle%s: soc_timestamp %s" % (vehicle, soc_timestamp))
log.debug("vehicle%s: local Date&Time of SoC %s" % (vehicle, datetime.fromtimestamp(soc_timestamp)))
return CarState(soc, range, soc_timestamp)

async def requestSoc(leaf: pycarwings3.Leaf):
# request Nissan server to request last SoC from car
log.debug("vehicle%s: Request SoC Update from vehicle" % (vehicle))
key = await leaf.request_update()
sleepsecs = 20
for _ in range(0, 3):
log.debug("Waiting {0} seconds".format(sleepsecs))
await asyncio.sleep(sleepsecs)
status = await leaf.get_status_from_update(key)
if status is not None:
log.debug("vehicle%s: Update successful" % (vehicle))
return status
log.debug("vehicle%s: Update not successful" % (vehicle))
return status

try:
leaf = await getNissanSession() # start HTTPS session with Nissan server
soc_range = await readSoc(leaf) # read old SoC & range values from server
await asyncio.sleep(1) # give Nissan server some time
status = await requestSoc(leaf) # Nissan server to request new values from vehicle
if status is not None: # was update of values successful?
await asyncio.sleep(1) # give Nissan server some time
soc_range = await readSoc(leaf) # final read of SoC & range from server
except pycarwings3.CarwingsError as e:
log.info("vehicle%s: SoC & range request not successful" % (vehicle))
log.info(e)
soc_range = CarState(0.0, 0.0)
return soc_range


# main entry - _fetch_soc needs to be run async
def fetch_soc(user_id: str, password: str, region: str, vehicle: int) -> CarState:

loop = asyncio.new_event_loop() # prepare and call async method
asyncio.set_event_loop(loop)

# get SoC and range from vehicle via server
soc_range = loop.run_until_complete(_fetch_soc(user_id, password, region, vehicle))

return soc_range
18 changes: 18 additions & 0 deletions packages/modules/vehicles/leaf/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from typing import Optional


class LeafConfiguration:
def __init__(self, user_id: Optional[str] = None, password: Optional[str] = None, region: Optional[str] = None):
self.user_id = user_id
self.password = password
self.region = region


class LeafSoc:
def __init__(self,
name: str = "Nissan Leaf/NV200 -05.2019 (experimental)",
type: str = "leaf",
configuration: LeafConfiguration = None) -> None:
self.name = name
self.type = type
self.configuration = configuration or LeafConfiguration()
47 changes: 47 additions & 0 deletions packages/modules/vehicles/leaf/soc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from typing import List

import logging

from helpermodules.cli import run_using_positional_cli_args
from modules.common import store
from modules.common.abstract_device import DeviceDescriptor
from modules.common.abstract_vehicle import VehicleUpdateData
from modules.common.component_state import CarState
from modules.common.configurable_vehicle import ConfigurableVehicle
from modules.vehicles.leaf import api
from modules.vehicles.leaf.config import LeafSoc, LeafConfiguration


log = logging.getLogger(__name__)


def create_vehicle(vehicle_config: LeafSoc, vehicle: int):
def updater(vehicle_update_data: VehicleUpdateData) -> CarState:
return api.fetch_soc(
vehicle_config.configuration.user_id,
vehicle_config.configuration.password,
vehicle_config.configuration.region,
vehicle)
return ConfigurableVehicle(vehicle_config=vehicle_config,
component_updater=updater,
vehicle=vehicle)


def leaf_update(user_id: str, password: str, region: str, charge_point: int):
log.debug("leaf: user_id="+user_id+" region="+region+" charge_point="+str(charge_point))
vehicle_config = LeafSoc(configuration=LeafConfiguration(charge_point,
user_id,
password,
region))
store.get_car_value_store(charge_point).store.set(api.fetch_soc(
vehicle_config.configuration.user_id,
vehicle_config.configuration.password,
vehicle_config.configuration.region,
charge_point))


def main(argv: List[str]):
run_using_positional_cli_args(leaf_update, argv)


device_descriptor = DeviceDescriptor(configuration_factory=LeafSoc)
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ protobuf==4.25.3
bimmer_connected==0.17.2
ocpp==1.0.0
websockets==12.0
pycarwings3==0.7.13