Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ChargePoint interface upgrade #3156

Merged
merged 3 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ activated environment:

::

pip install suds-jurko
pip install zeep

Alternatively requirements can be installed from requirements.txt using:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,11 @@
import logging
import abc
import sys

from . import service as cps
from . import async_service as async

from . import async_service as async_service
from .. import BaseInterface, BaseRegister, BasicRevert, DriverInterfaceError
from suds.sudsobject import asdict
#from suds.sudsobject import asdict
from zeep.helpers import serialize_object

_log = logging.getLogger(__name__)

Expand All @@ -68,7 +67,7 @@
point_name_mapping = {"Status.TimeStamp": "TimeStamp"}

service = {}
gevent.spawn(async.web_service)
gevent.spawn(async_service.web_service)


def recursive_asdict(d):
Expand All @@ -78,7 +77,7 @@ def recursive_asdict(d):
http://stackoverflow.com/questions/2412486/serializing-a-suds-object-in-python
"""
out = {}
for k, v in asdict(d).items():
for k, v in serialize_object(d, dict).items():
if hasattr(v, '__keylist__'):
out[k] = recursive_asdict(v)
elif isinstance(v, list):
Expand Down Expand Up @@ -153,6 +152,16 @@ def read_only_check(self):
raise IOError("Trying to write to a point configured read only: {0}".format(self.attribute_name))
return True

def get_last_non_none_value(self,lst):
"""
Depends on port number, the result could be a list with None value
get last non-None value as result
"""
for item in reversed(lst):
if item is not None:
return item
return None

def get_register(self, result, method, port_flag=True):
"""Gets correct register from API response.

Expand All @@ -165,9 +174,10 @@ def get_register(self, result, method, port_flag=True):
:return: Correct register value cast to appropriate python type. Returns None if there is an error.
"""
try:
value = getattr(result, self.attribute_name)(self.port)[0] \
_log.debug(f'In get_register, to get {self.attribute_name}, the port_flag is {port_flag}')
value = self.get_last_non_none_value(getattr(result, self.attribute_name)(self.port)) \
if port_flag \
else getattr(result, self.attribute_name)(None)[0]
else self.get_last_non_none_value(getattr(result, self.attribute_name)(None))
return self.sanitize_output(self.data_type, value)
except cps.CPAPIException as exception:
if exception._responseCode not in ['153']:
Expand Down Expand Up @@ -210,7 +220,7 @@ def __init__(self, read_only, point_name, attribute_name, units, data_type, stat
def value(self):
global service
method = service[self.username].getStations
result = async.CPRequest.request(method, self.timeout, stationID=self.station_id)
result = async_service.CPRequest.request(method, self.timeout, stationID=self.station_id)
result.wait()
return self.get_register(result.value, method)

Expand Down Expand Up @@ -251,7 +261,7 @@ def __init__(self, read_only, point_name, attribute_name, units, data_type, stat
def value(self):
global service
method = service[self.username].getLoad
result = async.CPRequest.request(method, self.timeout, stationID=self.station_id)
result = async_service.CPRequest.request(method, self.timeout, stationID=self.station_id)
result.wait()
return self.get_register(result.value, method)

Expand All @@ -277,7 +287,7 @@ def value(self, x):
kwargs = {'stationID': self.station_id}
if self.attribute_name == 'shedState' and not value:
method = service[self.username].clearShedState
result = async.CPRequest.request(method, 0, stationID=self.station_id)
result = async_service.CPRequest.request(method, 0, stationID=self.station_id)
elif self.attribute_name == 'shedState':
_log.error('shedState may only be written with value 0. If you want to shedLoad, write to '
'allowedLoad or percentShed')
Expand All @@ -287,7 +297,7 @@ def value(self, x):
kwargs[self.attribute_name] = value
if self.port:
kwargs['portNumber'] = self.port
result = async.CPRequest.request(method, 0, **kwargs)
result = async_service.CPRequest.request(method, 0, **kwargs)

result.wait()
if result.value.responseCode != "100":
Expand Down Expand Up @@ -336,7 +346,7 @@ def value(self):
if self.port:
kwargs['portNumber'] = self.port

result = async.CPRequest.request(method, self.timeout, **kwargs)
result = async_service.CPRequest.request(method, self.timeout, **kwargs)
result.wait()
return self.get_register(result.value, method, False)

Expand All @@ -362,7 +372,7 @@ def value(self, x):
if self.attribute_name == 'clearAlarms' and value:
kwargs = {'stationID': self.station_id}
method = service[self.username].clearAlarms
result = async.CPRequest.request(method, 0, **kwargs)
result = async_service.CPRequest.request(method, 0, **kwargs)

result.wait()
if result.value.responseCode not in ['100', '153']:
Expand Down Expand Up @@ -397,11 +407,12 @@ def __init__(self, read_only, point_name, attribute_name, units, data_type, stat
def value(self):
global service
method = service[self.username].getChargingSessionData
result = async.CPRequest.request(method, self.timeout, stationID=self.station_id)
result = async_service.CPRequest.request(method, self.timeout, stationID=self.station_id)
result.wait()

# Of Note, due to API limitations, port number is ignored for these calls
return self.get_register(result.value, method, False)
# NOTE: Change this port number for Chargingsession data.
return self.get_register(result.value, method)

@value.setter
def value(self, x):
Expand Down Expand Up @@ -432,7 +443,7 @@ def __init__(self, read_only, point_name, attribute_name, units, data_type, stat
def value(self):
global service
method = service[self.username].getStationStatus
result = async.CPRequest.request(method, self.timeout, self.station_id)
result = async_service.CPRequest.request(method, self.timeout, self.station_id)
result.wait()
return self.get_register(result.value, method)

Expand Down Expand Up @@ -469,7 +480,7 @@ def __init__(self, read_only, point_name, attribute_name, units, data_type, stat
def value(self):
global service
method = service[self.username].getStationRights
result = async.CPRequest.request(method, self.timeout, stationID=self.station_id)
result = async_service.CPRequest.request(method, self.timeout, stationID=self.station_id)
result.wait()

# Note: this does not go through get_register, as it is of a unique type, 'dictionary.'
Expand Down Expand Up @@ -572,7 +583,7 @@ def parse_config(self, config_dict, registry_config_str):
description=description,
port_number=port_num,
username=config_dict['username'],
timeout=config_dict['cacheExpiration']
timeout=config_dict.get('cacheExpiration',0)
)

self.insert_register(register)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,14 @@
import gevent.event
import gevent.queue
import logging
import suds
import zeep
from gevent import monkey
from .service import CPAPIException
from datetime import datetime, timedelta

monkey.patch_all()
_log = logging.getLogger(__name__)
SERVICE_WSDL_URL = "https://webservices.chargepoint.com/cp_api_5.0.wsdl"

SERVICE_WSDL_URL = "https://webservices.chargepoint.com/cp_api_5.1.wsdl"
# Queue for Web API requests and responses. It is managed by the long running
# web_service() greenlet.
web_service_queue = gevent.queue.Queue()
Expand Down Expand Up @@ -267,7 +266,7 @@ def web_service():
web_cache[item_key] = cache_item

if not client_set:
client_set.add(suds.client.Client(SERVICE_WSDL_URL))
client_set.add(zeep.Client(SERVICE_WSDL_URL))
client = client_set.pop()
gevent.spawn(web_call, item, client)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from . import service as cps
import suds
import zeep
import io

station_csv = {
Expand Down Expand Up @@ -176,5 +176,5 @@
else:
print("Some other error happened")

except suds.WebFault as a:
except zeep.exception.Fault as e:
print("Sorry, your API credentials are invalid. Please contact Chargepoint for assistance.")
Original file line number Diff line number Diff line change
@@ -1 +1 @@
suds-jurko==0.6
zeep==4.2.1
Loading
Loading