Slide 1

Slide 1 text

Using Grails to power your Electric Car

Slide 2

Slide 2 text

Small Intro ● Marco Pas (1973) › Education in Chemistry and then moved to Transportation & Logistics to finally IT.. what is next? ● Software Engineer ● Burgundian lifestyle Wikipedia tells us : 'enjoyment of life, good food, and extravagant spectacle'

Slide 3

Slide 3 text

Agenda ● What the heck am I trying to solve!! ● How on earth did we solve it? ● What are our plans for the future?

Slide 4

Slide 4 text

Disclaimer....

Slide 5

Slide 5 text

Electric Cars vs Electric Vehicles

Slide 6

Slide 6 text

Convention Fueling != Electric Vehicle Charging ● EV Charging Challenges: › Impossible to store & forward electricity › Charge often (Limited Range) › Time to charge (from minutes to hours) › Compatibility (plugs, charging cables)

Slide 7

Slide 7 text

Not kidding... !! Range Anxiety Reducer :)

Slide 8

Slide 8 text

Public EV Chargers in numbers ● 2011: EU 12.000 ● 2020: EU 660.000 2011 2020 Denmark 280 5.000 Germany 1.900 150.000 Italy 1.300 125.000 Netherlands 1.700 32.000 United Kingdom 703 122.000

Slide 9

Slide 9 text

EV Chargers in the wild

Slide 10

Slide 10 text

Charging Process Back Office Validation / Verification ● Is the card valid? ● Electricity pricing? ● How much can I charge? ● Who is the customer? ● Did you make a reservation? ● ….

Slide 11

Slide 11 text

Stakeholders involved in EV Charging

Slide 12

Slide 12 text

How to manage all those (different kind of) Chargers? Stakeholders? Processes?

Slide 13

Slide 13 text

Requirements ● Implement a platform that enables EV Infra management: › To monitor a Charge Point (CP) network › Supports remote management › Track charging sessions ● Including charge authorization & transaction storage › Multi-tenancy › 3rd party integration using Web Services (SOAP / REST)

Slide 14

Slide 14 text

No content

Slide 15

Slide 15 text

Schematic overview of a Charge Point

Slide 16

Slide 16 text

Open Charge Point Protocol (OCPP) ● Open protocol between charging stations and a managing central system aka back office › Asynchronous › Based on SOAP (v1.2) › Working group with support from all manufacturers!

Slide 17

Slide 17 text

Agenda ● What the heck am I trying to solve!! ● How on earth did we solve it? ● What are our plans for the future?

Slide 18

Slide 18 text

Release 1.0 ! ! SOAP ~ Contract First with Grails was not that easy, so we moved to a pure JAVA/Spring OCPP application

Slide 19

Slide 19 text

Jackson JSON Mapper public class JsonMapper extends ObjectMapper { public JsonMapper() { super(); /** * De-Serialization options JSON -> OBJECT */ // - ignore unknown fields - otherwise the construction of the object will fail! this.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // - make it possible to also construct empty objects this.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); /** * Serialization options OBJECT -> JSON */ // properties with non-null values are to be included in the resulting JSON this.setSerializationInclusion(JsonInclude.Include.NON_NULL); } }

Slide 20

Slide 20 text

Jackson JSON Mapper ● JSON → Object ● Object → JSON resources.groovy beans = { // a preconfigured Jackson JSON mapper with defaults jsonMapper(JsonMapper){} } def jsonContent = “{'name': 'John Doe'}” Person person = jsonMapper.readValue(jsonContent, Person.class) Person person = new Person(name: 'John Doe') def jsonContent = jsonMapper.valueToTree(person)

Slide 21

Slide 21 text

Theming support ● Login-Logout & user configurable themes ● Using Spring Security Core Plugin Config.groovy // make sure we can act on security events grails.plugins.springsecurity.useSecurityEventListener = true // executed when a user succesfully authenticates into the application grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx → // .. code intentionally emitted .. // session.theme = “MyNameOfTheTheme” } page.gsp <% session.theme="${grailsApplication.config.default.theme}"%>

Slide 22

Slide 22 text

Chargepoint Overview

Slide 23

Slide 23 text

Pool Overview

Slide 24

Slide 24 text

Nokia Maps – Heat Map

Slide 25

Slide 25 text

Technical Debt ● Client was very happy but.... shame on us: › Tightly coupled › Poor test coverage › Spring project & Grails project › Adding functional value is just to much fun! ● But... ready for round 2.. › Thanks to Grails we could refactor with great ease and speed!

Slide 26

Slide 26 text

Release 2.0 ● Guidelines: › Focus on creating a modular platform › Test Driven Development › Use Grails for everything!! › Minimize the use of plugins!!!

Slide 27

Slide 27 text

Grails CXF Plugin ● WSDL › Contract First & Code First ● Wire Interceptors › Logging, Security ● Support for versioning @GrailsCxfEndpoint(address='/myCustomSoapService/v2/')

Slide 28

Slide 28 text

Annotated example @GrailsCxfEndpoint( address='/centralsystem/ocpp/v1/5', wsdl = 'wsdl/ocpp_15_centralsystem.wsdl', expose = EndpointType.JAX_WS_WSDL, soap12 = true, inInterceptors = ["logSoapInboundInterceptor", "setReplyToSOAPHeaderInInterceptor"], outInterceptors = ["logSoapOutboundInterceptor"]) @WebService( name = "CentralSystemService", targetNamespace = "urn://Ocpp/Cs/2012/06/", serviceName = "CentralSystemService", portName = "CentralSystemServiceSoap12" ) @GZIP class CentralSystemOcpp15Service implements CentralSystemService { // ... code intentionally omitted // ... contains the methods that needs to be implemented due to the 'implements' }

Slide 29

Slide 29 text

Demo ● Create a contract first webservice using Grails CXF plugin › Source WSDL: CustomerService.wsdl › Steps: ● Create grails project ● Install CXF plugin ● Use WSDL2JAVA to generate web service implementation ● Create Grails service that implements the web service interface ● Test using SOAPUI

Slide 30

Slide 30 text

AMQP - Advanced Message Queuing Protocol ● Asynchronous and synchronous message exchange › Enables modular platform architecture

Slide 31

Slide 31 text

RabbitMQ – an AMQP implementation ● Grails RabbitMQ Plugin › High-level abstraction for sending and receiving messages › Fallback to Spring Template class MessageReceiveService { static rabbitQueue = 'helloQ' void handleMessage(message) { // handle message… } } class MessageSendController { def sendMessage = { rabbitSend 'helloQ', 'Hello!' } }

Slide 32

Slide 32 text

RabbitMQ Synchronous class MessageSendController { def rabbitTemplate // use the Spring rabbitTemplate directly def sendMessage = { def response = rabbitTemplate.convertSendAndReceive 'helloQ', 'Hello World' println response } } class MessageReceiveService { static rabbitQueue = [queues: 'helloQ', messageConverterBean: ''] void handleMessage(Message message) { // determine the reply queue def returnQueue = message.messageProperties.replyTo // return the response to temporary return queue.. rabbitSend returnQueue, 'Hello there' } }

Slide 33

Slide 33 text

Demo ● Send and Consume a message via RabbitMQ › Steps: ● Install RabbitMQ plugin ● Configure Grails app to use RabbitMQ ● Create code to publish and consume a message

Slide 34

Slide 34 text

No content

Slide 35

Slide 35 text

Testing ● Functional & Unit Testing › Build-Test-Data › Spock ● Load & Performane Testing › BadBoy / Apache JMeter

Slide 36

Slide 36 text

Some stuff we have used ● Grails Plugins › Spring Security › Export › RabbitMQ › CXF › Fixture › Spock › Build-Test-Data ● Non-Plugins › Twitter BootStrap › Jackson JSON

Slide 37

Slide 37 text

Agenda ● What the heck am I trying to solve!! ● How on earth did we solve it? ● What are our plans for the future?

Slide 38

Slide 38 text

Release 3.0 ● Additional protocol implementation in JSON › Eliminating the verbosity of SOAP! › To ([, “”, “”, {}]) 940 http://127.0.0.1:1234 http://127.0.0.1:1234 http://www.starwarsrules.com/services/centralsystem/ocpp/v1/5 /Heartbeat CHARGER_001_1234 [2, “19223201”, “HeartBeat”, {“”}] 940 http://127.0.0.1:1234 http://127.0.0.1:1234 http://www.starwarsrules.com/services/centralsystem/ocpp/v1/5 /Heartbeat CHARGER_001_1234

Slide 39

Slide 39 text

Release 3.0 ● Using WebSockets for full-duplex communication

Slide 40

Slide 40 text

WebSockets ● Defines an API establishing a "socket" connections between a client and a server › Providing full-duplex communication channel over a single TCP connection › HTTP upgrade by Protocol Negotiation › Firewall friendly! (port 80) › No reconnect handling or guaranteed message delivery

Slide 41

Slide 41 text

WebSocket handshake ● Client Request ● Server Response GET /mychat HTTP/1.1 Host: server.example.com Upgrade: websocket Connection: Upgrade Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat Sec-WebSocket-Version: 13 Origin: http://example.com HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat

Slide 42

Slide 42 text

WebSocket API Hooks

Slide 43

Slide 43 text

Vertx.io ● Asynchronous Application Development › Polyglot, Simplicity, Scalability, Concurrency › Distributed Event Bus › WebSocket support ● Verticles Server.groovy vertx.createHttpServer().requestHandler { req -> req.response.headers().put("Content-Type", "text/html; charset-UTF-8"); req.response.end("

Hello from vert.x!

"); }.listen(8080) vertx run Server.groovy vertx run Server.groovy -instances 4

Slide 44

Slide 44 text

Thank you!! http://twitter.com/marcopas [email protected] http://www.linkedin.com/in/marcopas