- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
117 lines
3.9 KiB
Python
117 lines
3.9 KiB
Python
from datetime import datetime, timezone
|
|
|
|
from xsdata.models.datatype import XmlDate
|
|
|
|
from shapeshifter_uftp import ShapeshifterAgrService
|
|
from shapeshifter_uftp.uftp import FlexOffer, FlexOfferOption, FlexOfferOptionISP
|
|
|
|
|
|
class DemoAggregator(ShapeshifterAgrService):
|
|
def process_agr_portfolio_query_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_agr_portfolio_update_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_d_prognosis_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_flex_offer_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_flex_offer_revocation_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_flex_order(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_flex_request(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
# Example of how to send a new message after
|
|
# processing an incoming message.
|
|
dso_client = self.dso_client(message.sender_domain)
|
|
dso_client.send_flex_offer(
|
|
FlexOffer(
|
|
isp_duration="PT15M",
|
|
period=XmlDate(2023, 1, 1),
|
|
congestion_point="ean.123456789012",
|
|
expiration_date_time=datetime.now(timezone.utc).isoformat(),
|
|
offer_options=[
|
|
FlexOfferOption(
|
|
isps=[FlexOfferOptionISP(power=1, start=1, duration=1)],
|
|
option_reference="MyOption",
|
|
price=2.30,
|
|
min_activation_factor=0.5,
|
|
)
|
|
],
|
|
)
|
|
)
|
|
|
|
def process_flex_reservation_update(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_flex_settlement(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
def process_metering_response(self, message):
|
|
print(f"Received a message: {message}")
|
|
|
|
|
|
def key_lookup(sender_domain, sender_role):
|
|
known_senders = {
|
|
("dso.demo", "DSO"): "NsTbq/iABU6tbsjriBg/Z5dSfQstulD0GpMI2fLDWec=",
|
|
("cro.demo", "CRO"): "ySUYU87usErRFKGJafwvVDLGhnBVJCCNYfQvmwv8ObM=",
|
|
}
|
|
return known_senders.get((sender_domain, sender_role))
|
|
|
|
|
|
def endpoint_lookup(sender_domain, sender_role):
|
|
known_senders = {
|
|
("dso.demo", "DSO"): "http://localhost:8081/shapeshifter/api/v3/message",
|
|
("cro.demo", "CRO"): "http://localhost:8082/shapeshifter/api/v3/message",
|
|
}
|
|
return known_senders.get((sender_domain, sender_role))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
aggregator = DemoAggregator(
|
|
sender_domain="aggregator.demo",
|
|
signing_key="mz5XYCNKxpx48K+9oipUhsjBZed3L7rTVKLsWmG1HOqRLIeuGpIa1KAt6AlbVGqJvewd8v1J0uVUTqpGt7F8tw==",
|
|
key_lookup_function=key_lookup,
|
|
endpoint_lookup_function=endpoint_lookup,
|
|
port=8080,
|
|
)
|
|
|
|
# Start the Aggregator Service
|
|
aggregator.run_in_thread()
|
|
|
|
# Create a client object to talk to a DSO
|
|
dso_client = aggregator.dso_client("dso.demo")
|
|
|
|
# Create a Flex Offer Message
|
|
flex_offer_message = FlexOffer(
|
|
isp_duration="PT15M",
|
|
period=XmlDate(2023, 1, 1),
|
|
congestion_point="ean.123456789012",
|
|
expiration_date_time=datetime.now(timezone.utc).isoformat(),
|
|
offer_options=[
|
|
FlexOfferOption(
|
|
isps=[FlexOfferOptionISP(power=1, start=1, duration=1)],
|
|
option_reference="MyOption",
|
|
price=2.30,
|
|
min_activation_factor=0.5,
|
|
)
|
|
],
|
|
)
|
|
|
|
# As a demo, press enter to send another FlexOffer message to the DSO.
|
|
while True:
|
|
try:
|
|
input("Press return to send a FlexOffer message to the DSO")
|
|
response = dso_client.send_flex_offer(flex_offer_message)
|
|
print(f"Response was: {response}")
|
|
except:
|
|
aggregator.stop()
|
|
break
|