/* ================================================================== * ChargeSessionManager_v15Tests.java - 11/06/2015 6:47:01 am * * Copyright 2007-2015 SolarNetwork.net Dev Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * ================================================================== */ package net.solarnetwork.node.ocpp.charge.test; import static org.easymock.EasyMock.anyObject; import static org.easymock.EasyMock.capture; import static org.easymock.EasyMock.eq; import static org.easymock.EasyMock.expect; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.UUID; import org.easymock.Capture; import org.easymock.EasyMock; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.osgi.service.event.Event; import net.solarnetwork.node.DatumDataSource; import net.solarnetwork.node.domain.ACEnergyDatum; import net.solarnetwork.node.domain.EnergyDatum; import net.solarnetwork.node.domain.GeneralNodeACEnergyDatum; import net.solarnetwork.node.ocpp.AuthorizationManager; import net.solarnetwork.node.ocpp.CentralSystemServiceFactory; import net.solarnetwork.node.ocpp.ChargeSession; import net.solarnetwork.node.ocpp.ChargeSessionDao; import net.solarnetwork.node.ocpp.ChargeSessionMeterReading; import net.solarnetwork.node.ocpp.OCPPException; import net.solarnetwork.node.ocpp.SocketDao; import net.solarnetwork.node.ocpp.charge.ChargeSessionManager_v15; import net.solarnetwork.node.test.AbstractNodeTest; import net.solarnetwork.node.util.ClassUtils; import net.solarnetwork.util.StaticOptionalServiceCollection; import ocpp.v15.cs.AuthorizationStatus; import ocpp.v15.cs.CentralSystemService; import ocpp.v15.cs.ChargePointStatus; import ocpp.v15.cs.IdTagInfo; import ocpp.v15.cs.Measurand; import ocpp.v15.cs.MeterValue; import ocpp.v15.cs.MeterValue.Value; import ocpp.v15.cs.MeterValuesRequest; import ocpp.v15.cs.MeterValuesResponse; import ocpp.v15.cs.ReadingContext; import ocpp.v15.cs.StartTransactionRequest; import ocpp.v15.cs.StartTransactionResponse; import ocpp.v15.cs.StatusNotificationRequest; import ocpp.v15.cs.StatusNotificationResponse; import ocpp.v15.cs.StopTransactionRequest; import ocpp.v15.cs.StopTransactionResponse; import ocpp.v15.cs.TransactionData; import ocpp.v15.cs.UnitOfMeasure; /** * Test cases for the {@link ChargeSessionManager_v15} class. * * @author matt * @version 1.0 */ public class ChargeSessionManager_v15Tests extends AbstractNodeTest { private static final String TEST_CHARGE_BOX_IDENTITY = "test.ident"; private static final String TEST_METER_SOURCE_ID = "test.meter"; private static final String TEST_SOCKET_ID = "/socket/test"; private static final String TEST_ID_TAG = "test.tag"; private static final Integer TEST_CONNECTOR_ID = 11; private static final Integer TEST_TRANSACTION_ID = 22; private static final String TEST_SESSION_ID = UUID.randomUUID().toString(); private AuthorizationManager authManager; private CentralSystemServiceFactory centralSystem; private CentralSystemService client; private ChargeSessionDao chargeSessionDao; private SocketDao socketDao; private DatumDataSource<ACEnergyDatum> meterDataSource; private ChargeSessionManager_v15 manager; @SuppressWarnings("unchecked") private DatumDataSource<ACEnergyDatum> newMeterDataSource() { return EasyMock.createMock(DatumDataSource.class); } @Before public void setup() { authManager = EasyMock.createMock(AuthorizationManager.class); client = EasyMock.createMock(CentralSystemService.class); centralSystem = new MockCentralSystemServiceFactory("OCPP Central System", null, client, TEST_CHARGE_BOX_IDENTITY); chargeSessionDao = EasyMock.createMock(ChargeSessionDao.class); socketDao = EasyMock.createMock(SocketDao.class); meterDataSource = newMeterDataSource(); manager = new ChargeSessionManager_v15(); manager.setAuthManager(authManager); manager.setCentralSystem(centralSystem); manager.setChargeSessionDao(chargeSessionDao); manager.setSocketDao(socketDao); manager.setMeterDataSource(new StaticOptionalServiceCollection<DatumDataSource<ACEnergyDatum>>( Collections.singletonList(meterDataSource))); manager.setSocketConnectorMapping(Collections.singletonMap(TEST_SOCKET_ID, TEST_CONNECTOR_ID)); manager.setSocketMeterSourceMapping( Collections.singletonMap(TEST_SOCKET_ID, TEST_METER_SOURCE_ID)); } @After public void finish() { EasyMock.verify(authManager, client, chargeSessionDao, socketDao, meterDataSource); } private void replayAll() { EasyMock.replay(authManager, client, chargeSessionDao, socketDao, meterDataSource); } @Test public void activeSessionNone() { expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(null); replayAll(); ChargeSession session = manager.activeChargeSession(TEST_SOCKET_ID); Assert.assertNull("No active session", session); } @Test public void activeSessionMatch() { final ChargeSession active = new ChargeSession(); expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(active); replayAll(); ChargeSession session = manager.activeChargeSession(TEST_SOCKET_ID); Assert.assertSame("Active session", active, session); } private Map<String, Object> datumCapturedEventProperties(EnergyDatum datum) { Map<String, Object> m = ClassUtils.getSimpleBeanProperties(datum, null); m.put(DatumDataSource.EVENT_DATUM_CAPTURED_DATUM_TYPE, datum.getClass().getSimpleName()); return m; } @Test public void handleDatumCapturedEventNoSession() { final GeneralNodeACEnergyDatum datum = new GeneralNodeACEnergyDatum(); datum.setCreated(new Date()); datum.setSourceId(TEST_METER_SOURCE_ID); datum.setWatts(100); datum.setWattHourReading(1000L); final Event captured = new Event(DatumDataSource.EVENT_TOPIC_DATUM_CAPTURED, datumCapturedEventProperties(datum)); // first look for active session associated with socket expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(null); replayAll(); manager.handleEvent(captured); } @Test public void handleDatumCapturedEventMatchingSession() { final GeneralNodeACEnergyDatum datum = new GeneralNodeACEnergyDatum(); datum.setCreated(new Date()); datum.setSourceId(TEST_METER_SOURCE_ID); datum.setWatts(100); datum.setWattHourReading(1000L); final Event captured = new Event(DatumDataSource.EVENT_TOPIC_DATUM_CAPTURED, datumCapturedEventProperties(datum)); final ChargeSession active = new ChargeSession(); active.setCreated(new Date()); active.setSessionId(TEST_SESSION_ID); active.setSocketId(TEST_SOCKET_ID); active.setStatus(AuthorizationStatus.ACCEPTED); active.setTransactionId(TEST_TRANSACTION_ID); // first look for active session associated with socket expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(active); // then store meter reading final Capture<Iterable<Value>> readingCapture = new Capture<Iterable<Value>>(); chargeSessionDao.addMeterReadings(eq(TEST_SESSION_ID), anyObject(Date.class), capture(readingCapture)); replayAll(); manager.handleEvent(captured); Iterable<Value> inserted = readingCapture.getValue(); Assert.assertNotNull("Inserted readings", inserted); Iterator<Value> itr = inserted.iterator(); Assert.assertTrue("More readings", itr.hasNext()); Value v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.SAMPLE_PERIODIC, v.getContext()); Assert.assertEquals("Measurand", Measurand.ENERGY_ACTIVE_IMPORT_REGISTER, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.WH, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWattHourReading()), v.getValue()); Assert.assertTrue("More readings", itr.hasNext()); v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.SAMPLE_PERIODIC, v.getContext()); Assert.assertEquals("Measurand", Measurand.POWER_ACTIVE_IMPORT, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.W, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWatts()), v.getValue()); Assert.assertFalse("No more readings", itr.hasNext()); } @Test public void initiateChargeSession() { // verify socket not disabled expect(socketDao.isEnabled(TEST_SOCKET_ID)).andReturn(true); // verify active session does not exist expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(null); // request authorization for IdTag expect(authManager.authorize(TEST_ID_TAG)).andReturn(AuthorizationStatus.ACCEPTED); // post OCCUPIED status notification Capture<StatusNotificationRequest> statusNotificationReqCapture = new Capture<StatusNotificationRequest>(); final StatusNotificationResponse statusNotificationResp = new StatusNotificationResponse(); expect(client.statusNotification(capture(statusNotificationReqCapture), eq(TEST_CHARGE_BOX_IDENTITY))).andReturn(statusNotificationResp); // get meter reading final GeneralNodeACEnergyDatum datum = new GeneralNodeACEnergyDatum(); datum.setCreated(new Date()); datum.setWatts(123); datum.setWattHourReading(111L); expect(meterDataSource.readCurrentDatum()).andReturn(datum); // start transaction Capture<StartTransactionRequest> startTransactionReqCapture = new Capture<StartTransactionRequest>(); final StartTransactionResponse startTransactionResp = new StartTransactionResponse(); startTransactionResp.setIdTagInfo(new IdTagInfo()); startTransactionResp.getIdTagInfo().setStatus(AuthorizationStatus.ACCEPTED); startTransactionResp.setTransactionId(123); expect(client.startTransaction(capture(startTransactionReqCapture), eq(TEST_CHARGE_BOX_IDENTITY))).andReturn(startTransactionResp); // store the session Capture<ChargeSession> sessionCapture = new Capture<ChargeSession>(); expect(chargeSessionDao.storeChargeSession(capture(sessionCapture))).andReturn(TEST_SESSION_ID); // store the initial meter readings final Capture<Iterable<Value>> readingCapture = new Capture<Iterable<Value>>(); chargeSessionDao.addMeterReadings(eq(TEST_SESSION_ID), eq(datum.getCreated()), capture(readingCapture)); replayAll(); String sessionId = manager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null); Assert.assertEquals("Session ID", TEST_SESSION_ID, sessionId); // verify StatusNotificationRequest StatusNotificationRequest statusNotificationReq = statusNotificationReqCapture.getValue(); Assert.assertNotNull("StatusNotificationRequest", statusNotificationReq); Assert.assertEquals("StartTransactionRequest connectorId", TEST_CONNECTOR_ID.intValue(), statusNotificationReq.getConnectorId()); Assert.assertEquals("StartTransactionRequest idTag", ChargePointStatus.OCCUPIED, statusNotificationReq.getStatus()); Assert.assertNotNull("StartTransactionRequest timestamp", statusNotificationReq.getTimestamp()); // verify StartTransactionRequest StartTransactionRequest startTransactionReq = startTransactionReqCapture.getValue(); Assert.assertNotNull("Request", startTransactionReq); Assert.assertEquals("StartTransactionRequest connectorId", TEST_CONNECTOR_ID.intValue(), startTransactionReq.getConnectorId()); Assert.assertEquals("StartTransactionRequest idTag", TEST_ID_TAG, startTransactionReq.getIdTag()); Assert.assertEquals("StartTransactionRequest meterStart", datum.getWattHourReading().intValue(), startTransactionReq.getMeterStart()); Assert.assertNull("StartTransactionRequest reservationId", startTransactionReq.getReservationId()); Assert.assertNotNull("StartTransactionRequest timestamp", startTransactionReq.getTimestamp()); // verify ChargeSession entity ChargeSession session = sessionCapture.getValue(); Assert.assertNotNull("ChargeSession", session); Assert.assertNotNull("ChargeSession created", session.getCreated()); Assert.assertNull("ChargeSession ended", session.getEnded()); Assert.assertNull("ChargeSession expiryDate", session.getExpiryDate()); Assert.assertEquals("ChargeSession idTag", TEST_ID_TAG, session.getIdTag()); Assert.assertNull("ChargeSession parentIdTag", session.getParentIdTag()); Assert.assertEquals("ChargeSession socketId", TEST_SOCKET_ID, session.getSocketId()); Assert.assertEquals("ChargeSession status", AuthorizationStatus.ACCEPTED, session.getStatus()); Assert.assertNotNull("ChargeSession transactionId", session.getTransactionId()); Assert.assertEquals("ChargeSession transactionId", startTransactionResp.getTransactionId(), session.getTransactionId().intValue()); // verify inserted readings Iterable<Value> inserted = readingCapture.getValue(); Assert.assertNotNull("Inserted readings", inserted); Iterator<Value> itr = inserted.iterator(); Assert.assertTrue("More readings", itr.hasNext()); Value v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.TRANSACTION_BEGIN, v.getContext()); Assert.assertEquals("Measurand", Measurand.ENERGY_ACTIVE_IMPORT_REGISTER, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.WH, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWattHourReading()), v.getValue()); Assert.assertTrue("More readings", itr.hasNext()); v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.TRANSACTION_BEGIN, v.getContext()); Assert.assertEquals("Measurand", Measurand.POWER_ACTIVE_IMPORT, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.W, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWatts()), v.getValue()); Assert.assertFalse("No more readings", itr.hasNext()); } @Test public void initiateChargeSessionAlreadyActive() { // verify socket not disabled expect(socketDao.isEnabled(TEST_SOCKET_ID)).andReturn(true); // verify active session does not exist (but it does) final ChargeSession existingSession = new ChargeSession(); expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)) .andReturn(existingSession); replayAll(); try { manager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null); Assert.fail("OCPPException should have been thrown"); } catch ( OCPPException e ) { Assert.assertEquals("Status", AuthorizationStatus.CONCURRENT_TX, e.getStatus()); } } @Test public void initiateChargeSessionSocketDisabled() { // verify socket not disabled expect(socketDao.isEnabled(TEST_SOCKET_ID)).andReturn(false); replayAll(); try { manager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null); Assert.fail("OCPPException should have been thrown"); } catch ( OCPPException e ) { Assert.assertEquals("Status", AuthorizationStatus.BLOCKED, e.getStatus()); } } @Test public void initiateChargeSessionNotAuthorized() { // verify socket not disabled expect(socketDao.isEnabled(TEST_SOCKET_ID)).andReturn(true); // verify active session does not exist expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)).andReturn(null); // request authorization for IdTag expect(authManager.authorize(TEST_ID_TAG)).andReturn(AuthorizationStatus.INVALID); replayAll(); try { manager.initiateChargeSession(TEST_ID_TAG, TEST_SOCKET_ID, null); Assert.fail("Should have thrown OCPPException on authorization failure"); } catch ( OCPPException e ) { Assert.assertEquals(AuthorizationStatus.INVALID, e.getStatus()); } } @Test public void finishChargeSession() { // get active session final ChargeSession existingSession = new ChargeSession(); existingSession.setIdTag(TEST_ID_TAG); existingSession.setSessionId(TEST_SESSION_ID); existingSession.setSocketId(TEST_SOCKET_ID); existingSession.setTransactionId(TEST_TRANSACTION_ID); expect(chargeSessionDao.getChargeSession(TEST_SESSION_ID)).andReturn(existingSession); // get final meter reading final GeneralNodeACEnergyDatum datum = new GeneralNodeACEnergyDatum(); datum.setCreated(new Date()); datum.setWatts(123); datum.setWattHourReading(1110L); expect(meterDataSource.readCurrentDatum()).andReturn(datum); // store the end meter readings final Capture<Iterable<Value>> readingCapture = new Capture<Iterable<Value>>(); chargeSessionDao.addMeterReadings(eq(TEST_SESSION_ID), eq(datum.getCreated()), capture(readingCapture)); // get all meter readings List<ChargeSessionMeterReading> readings = new ArrayList<ChargeSessionMeterReading>(8); int wh = datum.getWattHourReading().intValue() - (3 * 10); Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, -3); for ( int i = 0; i < 3; i++ ) { ChargeSessionMeterReading r = new ChargeSessionMeterReading(); r.setContext(i == 0 ? ReadingContext.TRANSACTION_BEGIN : i == 1 ? ReadingContext.SAMPLE_PERIODIC : ReadingContext.TRANSACTION_END); r.setMeasurand(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER); r.setSessionId(TEST_SESSION_ID); r.setTs(cal.getTime()); r.setUnit(UnitOfMeasure.WH); r.setValue(String.valueOf(wh)); readings.add(r); r = new ChargeSessionMeterReading(); r.setContext(i == 0 ? ReadingContext.TRANSACTION_BEGIN : i == 1 ? ReadingContext.SAMPLE_PERIODIC : ReadingContext.TRANSACTION_END); r.setMeasurand(Measurand.POWER_ACTIVE_IMPORT); r.setSessionId(TEST_SESSION_ID); r.setTs(cal.getTime()); r.setUnit(UnitOfMeasure.W); r.setValue(datum.getWatts().toString()); readings.add(r); wh += 10; cal.add(Calendar.MINUTE, 1); } expect(chargeSessionDao.findMeterReadingsForSession(TEST_SESSION_ID)).andReturn(readings); // post the StopTransaction message Capture<StopTransactionRequest> stopTransactionReqCapture = new Capture<StopTransactionRequest>(); final StopTransactionResponse stopTransactionResp = new StopTransactionResponse(); stopTransactionResp.setIdTagInfo(new IdTagInfo()); stopTransactionResp.getIdTagInfo().setStatus(AuthorizationStatus.ACCEPTED); expect(client.stopTransaction(capture(stopTransactionReqCapture), eq(TEST_CHARGE_BOX_IDENTITY))) .andReturn(stopTransactionResp); // save the ChargeSession end date expect(chargeSessionDao.storeChargeSession(existingSession)).andReturn(TEST_SESSION_ID); // post AVAILABLE status notification Capture<StatusNotificationRequest> statusNotificationReqCapture = new Capture<StatusNotificationRequest>(); final StatusNotificationResponse statusNotificationResp = new StatusNotificationResponse(); expect(client.statusNotification(capture(statusNotificationReqCapture), eq(TEST_CHARGE_BOX_IDENTITY))).andReturn(statusNotificationResp); replayAll(); manager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); // verify StopTransactionRequest StopTransactionRequest req = stopTransactionReqCapture.getValue(); Assert.assertNotNull("Request", req); Assert.assertEquals("StopTransactionRequest idTag", TEST_ID_TAG, req.getIdTag()); Assert.assertEquals("StopTransactionRequest meterStart", datum.getWattHourReading().intValue(), req.getMeterStop()); Assert.assertNotNull("StopTransactionRequest timestamp", req.getTimestamp()); // verify StopTransactionRequest TransactionData Assert.assertEquals("StopTransactionRequest transactionData count", 1, req.getTransactionData().size()); TransactionData data = req.getTransactionData().get(0); Assert.assertEquals("TransactionData transactionData values", 3, data.getValues().size()); cal.add(Calendar.MINUTE, -3); for ( int i = 0; i < 3; i++ ) { MeterValue meterValue = data.getValues().get(i); Assert.assertNotNull("MeterValue timestamp", meterValue.getTimestamp()); Assert.assertEquals("MeterValue timestamp", cal.getTime(), meterValue.getTimestamp().toGregorianCalendar().getTime()); cal.add(Calendar.MINUTE, 1); } // verify StatusNotificationRequest StatusNotificationRequest statusNotificationReq = statusNotificationReqCapture.getValue(); Assert.assertNotNull("StatusNotificationRequest", statusNotificationReq); Assert.assertEquals("StartTransactionRequest connectorId", TEST_CONNECTOR_ID.intValue(), statusNotificationReq.getConnectorId()); Assert.assertEquals("StartTransactionRequest idTag", ChargePointStatus.AVAILABLE, statusNotificationReq.getStatus()); Assert.assertNotNull("StartTransactionRequest timestamp", statusNotificationReq.getTimestamp()); // verify ChargeSession entity Assert.assertNotNull("ChargeSession ended", existingSession.getEnded()); Assert.assertNull("ChargeSession expiryDate", existingSession.getExpiryDate()); Assert.assertEquals("ChargeSession idTag", TEST_ID_TAG, existingSession.getIdTag()); Assert.assertNull("ChargeSession parentIdTag", existingSession.getParentIdTag()); Assert.assertEquals("ChargeSession socketId", TEST_SOCKET_ID, existingSession.getSocketId()); Assert.assertEquals("ChargeSession status", AuthorizationStatus.ACCEPTED, existingSession.getStatus()); // verify inserted readings Iterable<Value> inserted = readingCapture.getValue(); Assert.assertNotNull("Inserted readings", inserted); Iterator<Value> itr = inserted.iterator(); Assert.assertTrue("More readings", itr.hasNext()); Value v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.TRANSACTION_END, v.getContext()); Assert.assertEquals("Measurand", Measurand.ENERGY_ACTIVE_IMPORT_REGISTER, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.WH, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWattHourReading()), v.getValue()); Assert.assertTrue("More readings", itr.hasNext()); v = itr.next(); Assert.assertNotNull("Inserted reading", v); Assert.assertEquals("ReadingContext", ReadingContext.TRANSACTION_END, v.getContext()); Assert.assertEquals("Measurand", Measurand.POWER_ACTIVE_IMPORT, v.getMeasurand()); Assert.assertEquals("Unit", UnitOfMeasure.W, v.getUnit()); Assert.assertEquals("Value", String.valueOf(datum.getWatts()), v.getValue()); Assert.assertFalse("No more readings", itr.hasNext()); } @Test public void finishChargeSessionNoSession() { expect(chargeSessionDao.getChargeSession(TEST_SESSION_ID)).andReturn(null); replayAll(); try { manager.completeChargeSession(TEST_ID_TAG, TEST_SESSION_ID); Assert.fail("OCPPException should be thrown"); } catch ( OCPPException e ) { Assert.assertEquals("Status", AuthorizationStatus.INVALID, e.getStatus()); } } @Test public void postActiveSessionMeterValuesOneSession() { // get active session final ChargeSession existingSession = new ChargeSession(); existingSession.setIdTag(TEST_ID_TAG); existingSession.setSessionId(TEST_SESSION_ID); existingSession.setSocketId(TEST_SOCKET_ID); existingSession.setTransactionId(TEST_TRANSACTION_ID); expect(chargeSessionDao.getIncompleteChargeSessionForSocket(TEST_SOCKET_ID)) .andReturn(existingSession); // get all meter readings final GeneralNodeACEnergyDatum datum = new GeneralNodeACEnergyDatum(); datum.setCreated(new Date()); datum.setWatts(123); datum.setWattHourReading(1110L); List<ChargeSessionMeterReading> readings = new ArrayList<ChargeSessionMeterReading>(8); int wh = datum.getWattHourReading().intValue() - (3 * 10); Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, -3); for ( int i = 0; i < 3; i++ ) { ChargeSessionMeterReading r = new ChargeSessionMeterReading(); r.setContext(i == 0 ? ReadingContext.TRANSACTION_BEGIN : i == 1 ? ReadingContext.SAMPLE_PERIODIC : ReadingContext.TRANSACTION_END); r.setMeasurand(Measurand.ENERGY_ACTIVE_IMPORT_REGISTER); r.setSessionId(TEST_SESSION_ID); r.setTs(cal.getTime()); r.setUnit(UnitOfMeasure.WH); r.setValue(String.valueOf(wh)); readings.add(r); r = new ChargeSessionMeterReading(); r.setContext(i == 0 ? ReadingContext.TRANSACTION_BEGIN : i == 1 ? ReadingContext.SAMPLE_PERIODIC : ReadingContext.TRANSACTION_END); r.setMeasurand(Measurand.POWER_ACTIVE_IMPORT); r.setSessionId(TEST_SESSION_ID); r.setTs(cal.getTime()); r.setUnit(UnitOfMeasure.W); r.setValue(datum.getWatts().toString()); readings.add(r); wh += 10; cal.add(Calendar.MINUTE, 1); } expect(chargeSessionDao.findMeterReadingsForSession(TEST_SESSION_ID)).andReturn(readings); Capture<MeterValuesRequest> meterValuesRequestCapture = new Capture<MeterValuesRequest>(); final MeterValuesResponse meterValuesResp = new MeterValuesResponse(); expect(client.meterValues(capture(meterValuesRequestCapture), eq(TEST_CHARGE_BOX_IDENTITY))) .andReturn(meterValuesResp); replayAll(); manager.postActiveChargeSessionsMeterValues(); // verify MeterValuesRequest MeterValuesRequest meterValuesReq = meterValuesRequestCapture.getValue(); Assert.assertNotNull("MeterValuesRequest", meterValuesReq); Assert.assertEquals("MeterValuesRequest connectorId", TEST_CONNECTOR_ID.intValue(), meterValuesReq.getConnectorId()); Assert.assertEquals("MeterValuesRequest idTag", TEST_TRANSACTION_ID, meterValuesReq.getTransactionId()); // verify meter values posted Assert.assertNotNull("MeterValuesRequest values", meterValuesReq.getValues()); Assert.assertEquals("MeterValuesRequest values only most recent", 1, meterValuesReq.getValues().size()); cal.add(Calendar.MINUTE, -1); MeterValue meterValue = meterValuesReq.getValues().get(0); Assert.assertNotNull("MeterValue timestamp", meterValue.getTimestamp()); Assert.assertEquals("MeterValue timestamp", cal.getTime(), meterValue.getTimestamp().toGregorianCalendar().getTime()); Assert.assertEquals("MeterValue values", 2, meterValue.getValue().size()); Value v = meterValue.getValue().get(0); Assert.assertEquals("MeterValue measurand", Measurand.ENERGY_ACTIVE_IMPORT_REGISTER, v.getMeasurand()); Assert.assertEquals("MeterValue unit", UnitOfMeasure.WH, v.getUnit()); v = meterValue.getValue().get(1); Assert.assertEquals("MeterValue measurand", Measurand.POWER_ACTIVE_IMPORT, v.getMeasurand()); Assert.assertEquals("MeterValue unit", UnitOfMeasure.W, v.getUnit()); cal.add(Calendar.MINUTE, 1); } }