mirror of
https://github.com/openhab/openhab-addons.git
synced 2025-01-10 15:11:59 +01:00
[mercedesme] Websocket decoupling (#17753)
* decouple websocket thread from handler update Signed-off-by: Bernd Weymann <bernd.weymann@gmail.com> Signed-off-by: Ciprian Pascu <contact@ciprianpascu.ro>
This commit is contained in:
parent
18e80a7871
commit
e5da2860a2
@ -12,6 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.mercedesme.internal.handler;
|
package org.openhab.binding.mercedesme.internal.handler;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -57,8 +58,15 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
||||||
|
import com.daimler.mbcarkit.proto.Protos.AcknowledgeAssignedVehicles;
|
||||||
|
import com.daimler.mbcarkit.proto.VehicleEvents;
|
||||||
|
import com.daimler.mbcarkit.proto.VehicleEvents.AcknowledgeVEPUpdatesByVIN;
|
||||||
|
import com.daimler.mbcarkit.proto.VehicleEvents.PushMessage;
|
||||||
import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
|
import com.daimler.mbcarkit.proto.VehicleEvents.VEPUpdate;
|
||||||
|
import com.daimler.mbcarkit.proto.Vehicleapi.AcknowledgeAppTwinCommandStatusUpdatesByVIN;
|
||||||
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByPID;
|
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByPID;
|
||||||
|
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByVIN;
|
||||||
|
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinPendingCommandsRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The {@link AccountHandler} acts as Bridge between MercedesMe Account and the associated vehicles
|
* The {@link AccountHandler} acts as Bridge between MercedesMe Account and the associated vehicles
|
||||||
@ -82,7 +90,9 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
|
|
||||||
private Optional<AuthServer> server = Optional.empty();
|
private Optional<AuthServer> server = Optional.empty();
|
||||||
private Optional<AuthService> authService = Optional.empty();
|
private Optional<AuthService> authService = Optional.empty();
|
||||||
private Optional<ScheduledFuture<?>> scheduledFuture = Optional.empty();
|
private Optional<ScheduledFuture<?>> refreshScheduler = Optional.empty();
|
||||||
|
private List<byte[]> eventQueue = new ArrayList<>();
|
||||||
|
private boolean updateRunning = false;
|
||||||
|
|
||||||
private String capabilitiesEndpoint = "/v1/vehicle/%s/capabilities";
|
private String capabilitiesEndpoint = "/v1/vehicle/%s/capabilities";
|
||||||
private String commandCapabilitiesEndpoint = "/v1/vehicle/%s/capabilities/commands";
|
private String commandCapabilitiesEndpoint = "/v1/vehicle/%s/capabilities/commands";
|
||||||
@ -128,13 +138,13 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.NONE,
|
||||||
textKey + " [\"" + thing.getProperties().get("callbackUrl") + "\"]");
|
textKey + " [\"" + thing.getProperties().get("callbackUrl") + "\"]");
|
||||||
} else {
|
} else {
|
||||||
scheduledFuture = Optional.of(scheduler.scheduleWithFixedDelay(this::update, 0,
|
refreshScheduler = Optional.of(scheduler.scheduleWithFixedDelay(this::refresh, 0,
|
||||||
config.get().refreshInterval, TimeUnit.MINUTES));
|
config.get().refreshInterval, TimeUnit.MINUTES));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update() {
|
public void refresh() {
|
||||||
if (server.isPresent()) {
|
if (server.isPresent()) {
|
||||||
if (!Constants.NOT_SET.equals(authService.get().getToken())) {
|
if (!Constants.NOT_SET.equals(authService.get().getToken())) {
|
||||||
ws.run();
|
ws.run();
|
||||||
@ -203,12 +213,13 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
server = Optional.empty();
|
server = Optional.empty();
|
||||||
Utils.removePort(config.get().callbackPort);
|
Utils.removePort(config.get().callbackPort);
|
||||||
}
|
}
|
||||||
ws.interrupt();
|
refreshScheduler.ifPresent(schedule -> {
|
||||||
scheduledFuture.ifPresent(schedule -> {
|
|
||||||
if (!schedule.isCancelled()) {
|
if (!schedule.isCancelled()) {
|
||||||
schedule.cancel(true);
|
schedule.cancel(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
ws.interrupt();
|
||||||
|
eventQueue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -217,7 +228,7 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
@Override
|
@Override
|
||||||
public void onAccessTokenResponse(AccessTokenResponse tokenResponse) {
|
public void onAccessTokenResponse(AccessTokenResponse tokenResponse) {
|
||||||
if (!Constants.NOT_SET.equals(tokenResponse.getAccessToken())) {
|
if (!Constants.NOT_SET.equals(tokenResponse.getAccessToken())) {
|
||||||
scheduler.schedule(this::update, 2, TimeUnit.SECONDS);
|
scheduler.schedule(this::refresh, 2, TimeUnit.SECONDS);
|
||||||
} else if (server.isEmpty()) {
|
} else if (server.isEmpty()) {
|
||||||
// server not running - fix first
|
// server not running - fix first
|
||||||
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
String textKey = Constants.STATUS_TEXT_PREFIX + thing.getThingTypeUID().getId()
|
||||||
@ -262,7 +273,7 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
activeVehicleHandlerMap.put(vin, handler);
|
activeVehicleHandlerMap.put(vin, handler);
|
||||||
VEPUpdate updateForVin = vepUpdateMap.get(vin);
|
VEPUpdate updateForVin = vepUpdateMap.get(vin);
|
||||||
if (updateForVin != null) {
|
if (updateForVin != null) {
|
||||||
handler.distributeContent(updateForVin);
|
handler.enqueueUpdate(updateForVin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -284,12 +295,97 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* functions for websocket handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void enqueueMessage(byte[] data) {
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
eventQueue.add(data);
|
||||||
|
scheduler.execute(this::scheduleMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleMessage() {
|
||||||
|
byte[] data;
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
while (updateRunning) {
|
||||||
|
try {
|
||||||
|
eventQueue.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
eventQueue.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!eventQueue.isEmpty()) {
|
||||||
|
data = eventQueue.remove(0);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateRunning = true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
handleMessage(data);
|
||||||
|
} finally {
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
updateRunning = false;
|
||||||
|
eventQueue.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleMessage(byte[] array) {
|
||||||
|
try {
|
||||||
|
PushMessage pm = VehicleEvents.PushMessage.parseFrom(array);
|
||||||
|
if (pm.hasVepUpdates()) {
|
||||||
|
boolean distributed = distributeVepUpdates(pm.getVepUpdates().getUpdatesMap());
|
||||||
|
logger.trace("Distributed VEPUpdate {}", distributed);
|
||||||
|
if (distributed) {
|
||||||
|
AcknowledgeVEPUpdatesByVIN ack = AcknowledgeVEPUpdatesByVIN.newBuilder()
|
||||||
|
.setSequenceNumber(pm.getVepUpdates().getSequenceNumber()).build();
|
||||||
|
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeVepUpdatesByVin(ack).build();
|
||||||
|
ws.sendAcknowledgeMessage(cm);
|
||||||
|
}
|
||||||
|
} else if (pm.hasAssignedVehicles()) {
|
||||||
|
for (int i = 0; i < pm.getAssignedVehicles().getVinsCount(); i++) {
|
||||||
|
String vin = pm.getAssignedVehicles().getVins(0);
|
||||||
|
discovery(vin);
|
||||||
|
}
|
||||||
|
AcknowledgeAssignedVehicles ack = AcknowledgeAssignedVehicles.newBuilder().build();
|
||||||
|
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeAssignedVehicles(ack).build();
|
||||||
|
ws.sendAcknowledgeMessage(cm);
|
||||||
|
} else if (pm.hasApptwinCommandStatusUpdatesByVin()) {
|
||||||
|
AppTwinCommandStatusUpdatesByVIN csubv = pm.getApptwinCommandStatusUpdatesByVin();
|
||||||
|
commandStatusUpdate(csubv.getUpdatesByVinMap());
|
||||||
|
AcknowledgeAppTwinCommandStatusUpdatesByVIN ack = AcknowledgeAppTwinCommandStatusUpdatesByVIN
|
||||||
|
.newBuilder().setSequenceNumber(csubv.getSequenceNumber()).build();
|
||||||
|
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeApptwinCommandStatusUpdateByVin(ack)
|
||||||
|
.build();
|
||||||
|
ws.sendAcknowledgeMessage(cm);
|
||||||
|
} else if (pm.hasApptwinPendingCommandRequest()) {
|
||||||
|
AppTwinPendingCommandsRequest pending = pm.getApptwinPendingCommandRequest();
|
||||||
|
if (!pending.getAllFields().isEmpty()) {
|
||||||
|
logger.trace("Pending Command {}", pending.getAllFields());
|
||||||
|
}
|
||||||
|
} else if (pm.hasDebugMessage()) {
|
||||||
|
logger.trace("MB Debug Message: {}", pm.getDebugMessage().getMessage());
|
||||||
|
} else {
|
||||||
|
logger.trace("MB Message: {} not handled", pm.getAllFields());
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.trace("IOException decoding message {}", e.getMessage());
|
||||||
|
} catch (Error err) {
|
||||||
|
logger.debug("Error caught {}", err.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean distributeVepUpdates(Map<String, VEPUpdate> map) {
|
public boolean distributeVepUpdates(Map<String, VEPUpdate> map) {
|
||||||
List<String> notFoundList = new ArrayList<>();
|
List<String> notFoundList = new ArrayList<>();
|
||||||
map.forEach((key, value) -> {
|
map.forEach((key, value) -> {
|
||||||
VehicleHandler h = activeVehicleHandlerMap.get(key);
|
VehicleHandler h = activeVehicleHandlerMap.get(key);
|
||||||
if (h != null) {
|
if (h != null) {
|
||||||
h.distributeContent(value);
|
h.enqueueUpdate(value);
|
||||||
} else {
|
} else {
|
||||||
if (value.getFullUpdate()) {
|
if (value.getFullUpdate()) {
|
||||||
vepUpdateMap.put(key, value);
|
vepUpdateMap.put(key, value);
|
||||||
@ -430,7 +526,7 @@ public class AccountHandler extends BaseBridgeHandler implements AccessTokenRefr
|
|||||||
if (cm != null) {
|
if (cm != null) {
|
||||||
ws.setCommand(cm);
|
ws.setCommand(cm);
|
||||||
}
|
}
|
||||||
scheduler.schedule(this::update, 2, TimeUnit.SECONDS);
|
scheduler.schedule(this::refresh, 2, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void keepAlive(boolean b) {
|
public void keepAlive(boolean b) {
|
||||||
|
@ -134,6 +134,8 @@ public class VehicleHandler extends BaseThingHandler {
|
|||||||
private JSONObject chargeGroupValueStorage = new JSONObject();
|
private JSONObject chargeGroupValueStorage = new JSONObject();
|
||||||
private Map<String, State> hvacGroupValueStorage = new HashMap<>();
|
private Map<String, State> hvacGroupValueStorage = new HashMap<>();
|
||||||
private String vehicleType = NOT_SET;
|
private String vehicleType = NOT_SET;
|
||||||
|
private List<VEPUpdate> eventQueue = new ArrayList<>();
|
||||||
|
private boolean updateRunning = false;
|
||||||
|
|
||||||
Map<String, ChannelStateMap> eventStorage = new HashMap<>();
|
Map<String, ChannelStateMap> eventStorage = new HashMap<>();
|
||||||
Optional<AccountHandler> accountHandler = Optional.empty();
|
Optional<AccountHandler> accountHandler = Optional.empty();
|
||||||
@ -182,6 +184,7 @@ public class VehicleHandler extends BaseThingHandler {
|
|||||||
accountHandler.ifPresent(ah -> {
|
accountHandler.ifPresent(ah -> {
|
||||||
ah.unregisterVin(config.get().vin);
|
ah.unregisterVin(config.get().vin);
|
||||||
});
|
});
|
||||||
|
eventQueue.clear();
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,13 +590,49 @@ public class VehicleHandler extends BaseThingHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void distributeContent(VEPUpdate data) {
|
public void enqueueUpdate(VEPUpdate update) {
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
eventQueue.add(update);
|
||||||
|
scheduler.execute(this::scheduleUpdate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void scheduleUpdate() {
|
||||||
|
VEPUpdate data;
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
while (updateRunning) {
|
||||||
|
try {
|
||||||
|
eventQueue.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
eventQueue.clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!eventQueue.isEmpty()) {
|
||||||
|
data = eventQueue.remove(0);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateRunning = true;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
handleUpdate(data);
|
||||||
|
} finally {
|
||||||
|
synchronized (eventQueue) {
|
||||||
|
updateRunning = false;
|
||||||
|
eventQueue.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleUpdate(VEPUpdate update) {
|
||||||
updateStatus(ThingStatus.ONLINE);
|
updateStatus(ThingStatus.ONLINE);
|
||||||
boolean fullUpdate = data.getFullUpdate();
|
boolean fullUpdate = update.getFullUpdate();
|
||||||
/**
|
/**
|
||||||
* Deliver proto update
|
* Deliver proto update
|
||||||
*/
|
*/
|
||||||
String newProto = Utils.proto2Json(data, thing.getThingTypeUID());
|
String newProto = Utils.proto2Json(update, thing.getThingTypeUID());
|
||||||
String combinedProto = newProto;
|
String combinedProto = newProto;
|
||||||
ChannelUID protoUpdateChannelUID = new ChannelUID(thing.getUID(), GROUP_VEHICLE, OH_CHANNEL_PROTO_UPDATE);
|
ChannelUID protoUpdateChannelUID = new ChannelUID(thing.getUID(), GROUP_VEHICLE, OH_CHANNEL_PROTO_UPDATE);
|
||||||
ChannelStateMap oldProtoMap = eventStorage.get(protoUpdateChannelUID.getId());
|
ChannelStateMap oldProtoMap = eventStorage.get(protoUpdateChannelUID.getId());
|
||||||
@ -609,7 +648,7 @@ public class VehicleHandler extends BaseThingHandler {
|
|||||||
StringType.valueOf(combinedProto));
|
StringType.valueOf(combinedProto));
|
||||||
updateChannel(dataUpdateMap);
|
updateChannel(dataUpdateMap);
|
||||||
|
|
||||||
Map<String, VehicleAttributeStatus> atts = data.getAttributesMap();
|
Map<String, VehicleAttributeStatus> atts = update.getAttributesMap();
|
||||||
/**
|
/**
|
||||||
* handle "simple" values
|
* handle "simple" values
|
||||||
*/
|
*/
|
||||||
|
@ -39,13 +39,6 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
import com.daimler.mbcarkit.proto.Client.ClientMessage;
|
||||||
import com.daimler.mbcarkit.proto.Protos.AcknowledgeAssignedVehicles;
|
|
||||||
import com.daimler.mbcarkit.proto.VehicleEvents;
|
|
||||||
import com.daimler.mbcarkit.proto.VehicleEvents.AcknowledgeVEPUpdatesByVIN;
|
|
||||||
import com.daimler.mbcarkit.proto.VehicleEvents.PushMessage;
|
|
||||||
import com.daimler.mbcarkit.proto.Vehicleapi.AcknowledgeAppTwinCommandStatusUpdatesByVIN;
|
|
||||||
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinCommandStatusUpdatesByVIN;
|
|
||||||
import com.daimler.mbcarkit.proto.Vehicleapi.AppTwinPendingCommandsRequest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link MBWebsocket} as socket endpoint to communicate with Mercedes
|
* {@link MBWebsocket} as socket endpoint to communicate with Mercedes
|
||||||
@ -128,9 +121,10 @@ public class MBWebsocket {
|
|||||||
accountHandler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
accountHandler.updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR,
|
||||||
"@text/mercedesme.account.status.websocket-failure");
|
"@text/mercedesme.account.status.websocket-failure");
|
||||||
logger.warn("Websocket handling exception: {}", t.getMessage());
|
logger.warn("Websocket handling exception: {}", t.getMessage());
|
||||||
}
|
} finally {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
running = false;
|
running = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +151,7 @@ public class MBWebsocket {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendAcknowledgeMessage(ClientMessage message) {
|
public void sendAcknowledgeMessage(ClientMessage message) {
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
message.writeTo(baos);
|
message.writeTo(baos);
|
||||||
@ -169,10 +163,6 @@ public class MBWebsocket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRunning() {
|
|
||||||
return running;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void interrupt() {
|
public void interrupt() {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
runTill = Instant.MIN;
|
runTill = Instant.MIN;
|
||||||
@ -202,47 +192,20 @@ public class MBWebsocket {
|
|||||||
@OnWebSocketMessage
|
@OnWebSocketMessage
|
||||||
public void onBytes(InputStream is) {
|
public void onBytes(InputStream is) {
|
||||||
try {
|
try {
|
||||||
PushMessage pm = VehicleEvents.PushMessage.parseFrom(is);
|
byte[] array = is.readAllBytes();
|
||||||
if (pm.hasVepUpdates()) {
|
is.close();
|
||||||
boolean distributed = accountHandler.distributeVepUpdates(pm.getVepUpdates().getUpdatesMap());
|
accountHandler.enqueueMessage(array);
|
||||||
if (distributed) {
|
/**
|
||||||
AcknowledgeVEPUpdatesByVIN ack = AcknowledgeVEPUpdatesByVIN.newBuilder()
|
* https://community.openhab.org/t/mercedes-me/136866/12
|
||||||
.setSequenceNumber(pm.getVepUpdates().getSequenceNumber()).build();
|
* Release Websocket thread as early as possible to avoid execeptions
|
||||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeVepUpdatesByVin(ack).build();
|
*
|
||||||
sendAcknowledgeMessage(cm);
|
* 1. Websocket thread responsible for reading stream in bytes and enqueue for AccountHandler.
|
||||||
}
|
* 2. AccountHamdler thread responsible for encoding proto message. In case of update enqueue proto message
|
||||||
} else if (pm.hasAssignedVehicles()) {
|
* at VehicleHandöer
|
||||||
for (int i = 0; i < pm.getAssignedVehicles().getVinsCount(); i++) {
|
* 3. VehicleHandler responsible to update channels
|
||||||
String vin = pm.getAssignedVehicles().getVins(0);
|
*/
|
||||||
accountHandler.discovery(vin);
|
|
||||||
}
|
|
||||||
AcknowledgeAssignedVehicles ack = AcknowledgeAssignedVehicles.newBuilder().build();
|
|
||||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeAssignedVehicles(ack).build();
|
|
||||||
sendAcknowledgeMessage(cm);
|
|
||||||
} else if (pm.hasApptwinCommandStatusUpdatesByVin()) {
|
|
||||||
AppTwinCommandStatusUpdatesByVIN csubv = pm.getApptwinCommandStatusUpdatesByVin();
|
|
||||||
accountHandler.commandStatusUpdate(csubv.getUpdatesByVinMap());
|
|
||||||
AcknowledgeAppTwinCommandStatusUpdatesByVIN ack = AcknowledgeAppTwinCommandStatusUpdatesByVIN
|
|
||||||
.newBuilder().setSequenceNumber(csubv.getSequenceNumber()).build();
|
|
||||||
ClientMessage cm = ClientMessage.newBuilder().setAcknowledgeApptwinCommandStatusUpdateByVin(ack)
|
|
||||||
.build();
|
|
||||||
sendAcknowledgeMessage(cm);
|
|
||||||
} else if (pm.hasApptwinPendingCommandRequest()) {
|
|
||||||
AppTwinPendingCommandsRequest pending = pm.getApptwinPendingCommandRequest();
|
|
||||||
if (!pending.getAllFields().isEmpty()) {
|
|
||||||
logger.trace("Pending Command {}", pending.getAllFields());
|
|
||||||
}
|
|
||||||
} else if (pm.hasDebugMessage()) {
|
|
||||||
logger.trace("MB Debug Message: {}", pm.getDebugMessage().getMessage());
|
|
||||||
} else {
|
|
||||||
logger.trace("MB Message: {} not handled", pm.getAllFields());
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// don't report thing status errors here.
|
logger.debug("IOException reading input stream {}", e.getMessage());
|
||||||
// Sometimes messages cannot be decoded which doesn't effect the overall functionality
|
|
||||||
logger.trace("IOException {}", e.getMessage());
|
|
||||||
} catch (Error err) {
|
|
||||||
logger.trace("Error caught {}", err.getMessage());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.openhab.binding.mercedesme.internal.handler;
|
package org.openhab.binding.mercedesme.internal.handler;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -53,6 +56,7 @@ public class ThingCallbackListener implements ThingHandlerCallback {
|
|||||||
public Map<String, Map<String, State>> updatesPerGroupMap = new HashMap<>();
|
public Map<String, Map<String, State>> updatesPerGroupMap = new HashMap<>();
|
||||||
public boolean linked = false;
|
public boolean linked = false;
|
||||||
public Optional<ThingStatusInfo> status = Optional.empty();
|
public Optional<ThingStatusInfo> status = Optional.empty();
|
||||||
|
private Instant waitTime = Instant.MAX;
|
||||||
|
|
||||||
public ThingStatusInfo getThingStatus() {
|
public ThingStatusInfo getThingStatus() {
|
||||||
return status.get();
|
return status.get();
|
||||||
@ -78,6 +82,23 @@ public class ThingCallbackListener implements ThingHandlerCallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
groupMap.put(channelUID.toString(), state);
|
groupMap.put(channelUID.toString(), state);
|
||||||
|
synchronized (updatesReceived) {
|
||||||
|
waitTime = Instant.now().plus(500, ChronoUnit.MILLIS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitForUpdates() {
|
||||||
|
Instant maxWaitTime = Instant.now().plus(5000, ChronoUnit.MILLIS);
|
||||||
|
synchronized (updatesReceived) {
|
||||||
|
while (Instant.now().isBefore(maxWaitTime) && waitTime.isAfter(Instant.now())) {
|
||||||
|
try {
|
||||||
|
updatesReceived.wait(50);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waitTime = Instant.MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -115,7 +115,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
||||||
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
||||||
@ -151,7 +152,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-ImperialUnits.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-ImperialUnits.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
||||||
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
||||||
@ -187,7 +189,9 @@ class VehicleHandlerTest {
|
|||||||
// overwrite with EU Units
|
// overwrite with EU Units
|
||||||
json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
update = ProtoConverter.json2Proto(json, true);
|
update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals("%.1f °C", patternMock.patternMap.get("test::bev:hvac#temperature"), "Temperature Pattern");
|
assertEquals("%.1f °C", patternMock.patternMap.get("test::bev:hvac#temperature"), "Temperature Pattern");
|
||||||
commandOptionMock.getCommandList("test::bev:hvac#temperature").forEach(cmd -> {
|
commandOptionMock.getCommandList("test::bev:hvac#temperature").forEach(cmd -> {
|
||||||
assertTrue(cmd.getCommand().endsWith(" °C"), "Command Option Celsius Unit");
|
assertTrue(cmd.getCommand().endsWith(" °C"), "Command Option Celsius Unit");
|
||||||
@ -209,7 +213,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
||||||
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
||||||
@ -246,13 +251,17 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals("2023-09-09 13:54", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
assertEquals("2023-09-09 13:54", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
||||||
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
||||||
|
|
||||||
json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday-Underrun.json");
|
json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA-Charging-Weekday-Underrun.json");
|
||||||
update = ProtoConverter.json2Proto(json, true);
|
update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals("2023-09-11 13:55", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
assertEquals("2023-09-11 13:55", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
||||||
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
||||||
}
|
}
|
||||||
@ -272,7 +281,9 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Charging.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Charging.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(2, updateListener.updatesReceived.size(), "Update Count");
|
assertEquals(2, updateListener.updatesReceived.size(), "Update Count");
|
||||||
assertEquals("2023-09-19 20:45", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
assertEquals("2023-09-19 20:45", ((DateTimeType) updateListener.getResponse("test::bev:charge#end-time"))
|
||||||
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
.format("%1$tY-%1$tm-%1$td %1$tH:%1$tM"), "End of Charge Time");
|
||||||
@ -294,7 +305,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-GPS.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-GPS.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
|
assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
|
||||||
assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(), "GPS update");
|
assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(), "GPS update");
|
||||||
assertEquals("41.9 °", updateListener.getResponse("test::bev:position#heading").toFullString(),
|
assertEquals("41.9 °", updateListener.getResponse("test::bev:position#heading").toFullString(),
|
||||||
@ -316,7 +328,9 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Range.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/PartialUpdate-Range.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
VEPUpdate update = ProtoConverter.json2Proto(json, false);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
|
assertEquals(3, updateListener.updatesReceived.size(), "Update Count");
|
||||||
assertEquals("15017 km", updateListener.getResponse("test::bev:range#mileage").toFullString(),
|
assertEquals("15017 km", updateListener.getResponse("test::bev:range#mileage").toFullString(),
|
||||||
"Mileage Update");
|
"Mileage Update");
|
||||||
@ -341,7 +355,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
||||||
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
||||||
@ -374,7 +389,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Hybrid-Charging.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
// Test charged / uncharged battery and filled / unfilled tank volume
|
// Test charged / uncharged battery and filled / unfilled tank volume
|
||||||
assertEquals("5.800000190734863 kWh", updateListener.getResponse("test::hybrid:range#charged").toFullString(),
|
assertEquals("5.800000190734863 kWh", updateListener.getResponse("test::hybrid:range#charged").toFullString(),
|
||||||
@ -403,7 +419,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
assertEquals(GROUP_COUNT, updateListener.updatesPerGroupMap.size(), "Group Update Count");
|
||||||
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
assertEquals(10, updateListener.getUpdatesForGroup("doors"), "Doors Update Count");
|
||||||
@ -450,12 +467,14 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
assertFalse(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
|
assertFalse(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
|
||||||
"Proto Channel not updated");
|
"Proto Channel not updated");
|
||||||
|
|
||||||
updateListener.linked = true;
|
updateListener.linked = true;
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
|
assertTrue(updateListener.updatesReceived.containsKey("test::bev:vehicle#proto-update"),
|
||||||
"Proto Channel not updated");
|
"Proto Channel not updated");
|
||||||
}
|
}
|
||||||
@ -477,7 +496,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
assertEquals("22 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
|
assertEquals("22 °C", updateListener.getResponse("test::bev:hvac#temperature").toFullString(),
|
||||||
"Temperature Point One Updated");
|
"Temperature Point One Updated");
|
||||||
|
|
||||||
@ -508,7 +528,8 @@ class VehicleHandlerTest {
|
|||||||
vh.setCallback(updateListener);
|
vh.setCallback(updateListener);
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Unknown.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "temperature");
|
ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_HVAC, "temperature");
|
||||||
updateListener = new ThingCallbackListener();
|
updateListener = new ThingCallbackListener();
|
||||||
@ -538,7 +559,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vh.distributeContent(update);
|
vh.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "max-soc");
|
ChannelUID cuid = new ChannelUID(thingMock.getUID(), Constants.GROUP_CHARGE, "max-soc");
|
||||||
vh.handleCommand(cuid, QuantityType.valueOf("90 %"));
|
vh.handleCommand(cuid, QuantityType.valueOf("90 %"));
|
||||||
@ -586,7 +608,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vHandler.distributeContent(update);
|
vHandler.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count");
|
assertEquals(POSITIONING_UPDATE_COUNT, updateListener.getUpdatesForGroup("position"), "Position Update Count");
|
||||||
assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(),
|
assertEquals("1.23,4.56", updateListener.getResponse("test::bev:position#gps").toFullString(),
|
||||||
@ -608,7 +631,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vHandler.distributeContent(update);
|
vHandler.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
|
assertEquals(HVAC_UPDATE_COUNT, updateListener.getUpdatesForGroup("hvac"), "HVAC Update Count");
|
||||||
assertEquals(0, ((DecimalType) updateListener.getResponse("test::bev:hvac#ac-status")).intValue(),
|
assertEquals(0, ((DecimalType) updateListener.getResponse("test::bev:hvac#ac-status")).intValue(),
|
||||||
@ -627,7 +651,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-BEV-EQA.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vHandler.distributeContent(update);
|
vHandler.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals("72 %", updateListener.getResponse("test::bev:eco#accel").toFullString(), "Eco Acceleration");
|
assertEquals("72 %", updateListener.getResponse("test::bev:eco#accel").toFullString(), "Eco Acceleration");
|
||||||
assertEquals("81 %", updateListener.getResponse("test::bev:eco#coasting").toFullString(), "Eco Coasting");
|
assertEquals("81 %", updateListener.getResponse("test::bev:eco#coasting").toFullString(), "Eco Coasting");
|
||||||
@ -647,7 +672,8 @@ class VehicleHandlerTest {
|
|||||||
|
|
||||||
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Combustion.json");
|
String json = FileReader.readFileInString("src/test/resources/proto-json/MB-Combustion.json");
|
||||||
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
VEPUpdate update = ProtoConverter.json2Proto(json, true);
|
||||||
vHandler.distributeContent(update);
|
vHandler.enqueueUpdate(update);
|
||||||
|
updateListener.waitForUpdates();
|
||||||
|
|
||||||
assertEquals("29 %", updateListener.getResponse("test::combustion:range#adblue-level").toFullString(),
|
assertEquals("29 %", updateListener.getResponse("test::combustion:range#adblue-level").toFullString(),
|
||||||
"AdBlue Tank Level");
|
"AdBlue Tank Level");
|
||||||
|
Loading…
Reference in New Issue
Block a user