diff --git a/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java b/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java index 40aeab160d..7509f55585 100644 --- a/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java +++ b/java_console/io/src/main/java/com/rusefi/binaryprotocol/BinaryProtocol.java @@ -9,10 +9,7 @@ import com.rusefi.Timeouts; import com.rusefi.composite.CompositeEvent; import com.rusefi.composite.CompositeParser; import com.rusefi.config.generated.Fields; -import com.rusefi.core.MessagesCentral; -import com.rusefi.core.Pair; -import com.rusefi.core.Sensor; -import com.rusefi.core.SensorCentral; +import com.rusefi.core.*; import com.rusefi.io.*; import com.rusefi.io.commands.GetOutputsCommand; import com.rusefi.stream.LogicdataStreamFile; @@ -588,45 +585,10 @@ public class BinaryProtocol implements BinaryProtocolCommands { state.setCurrentOutputs(response); - for (Sensor sensor : Sensor.values()) { - if (sensor.getType() == null) { - // for example ETB_CONTROL_QUALITY, weird use-case - continue; - } - - ByteBuffer bb = ByteBuffer.wrap(response, 1 + sensor.getOffset(), 4); - bb.order(ByteOrder.LITTLE_ENDIAN); - - double rawValue = getValueForChannel(bb, sensor); - double scaledValue = rawValue * sensor.getScale(); - SensorCentral.getInstance().setValue(scaledValue, sensor); - } + SensorCentral.getInstance().grabSensorValues(response); return true; } - private static double getValueForChannel(ByteBuffer bb, Sensor sensor) { - switch (sensor.getType()) { - case FLOAT: - return bb.getFloat(); - case INT: - return bb.getInt(); - case UINT16: - // no cast - we want to discard sign - return bb.getInt() & 0xFFFF; - case INT16: - // cast - we want to retain sign - return (short)(bb.getInt() & 0xFFFF); - case UINT8: - // no cast - discard sign - return bb.getInt() & 0xFF; - case INT8: - // cast - retain sign - return (byte)(bb.getInt() & 0xFF); - default: - throw new UnsupportedOperationException("type " + sensor.getType()); - } - } - public void setRange(byte[] src, int scrPos, int offset, int count) { state.setRange(src, scrPos, offset, count); } diff --git a/java_console/models/src/main/java/com/rusefi/core/ISensorCentral.java b/java_console/models/src/main/java/com/rusefi/core/ISensorCentral.java index 94fb66939f..5824a25a48 100644 --- a/java_console/models/src/main/java/com/rusefi/core/ISensorCentral.java +++ b/java_console/models/src/main/java/com/rusefi/core/ISensorCentral.java @@ -4,11 +4,7 @@ package com.rusefi.core; * 11/16/2017 * Andrey Belomutskiy, (c) 2013-2020 */ -public interface ISensorCentral { - double getValue(Sensor sensor); - - void setValue(double value, Sensor sensor); - +public interface ISensorCentral extends ISensorHolder { void setAnySensorListener(SensorCentral.SensorListener2 anySensorListener); void addListener(Sensor sensor, SensorCentral.SensorListener listener); diff --git a/java_console/models/src/main/java/com/rusefi/core/ISensorHolder.java b/java_console/models/src/main/java/com/rusefi/core/ISensorHolder.java new file mode 100644 index 0000000000..53e4596cfe --- /dev/null +++ b/java_console/models/src/main/java/com/rusefi/core/ISensorHolder.java @@ -0,0 +1,26 @@ +package com.rusefi.core; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +public interface ISensorHolder { + default void grabSensorValues(byte[] response) { + for (Sensor sensor : Sensor.values()) { + if (sensor.getType() == null) { + // for example ETB_CONTROL_QUALITY, weird use-case + continue; + } + + ByteBuffer bb = ByteBuffer.wrap(response, 1 + sensor.getOffset(), 4); + bb.order(ByteOrder.LITTLE_ENDIAN); + + double rawValue = sensor.getValueForChannel(bb); + double scaledValue = rawValue * sensor.getScale(); + setValue(scaledValue, sensor); + } + } + + double getValue(Sensor sensor); + + boolean setValue(double value, Sensor sensor); +} diff --git a/java_console/models/src/main/java/com/rusefi/core/Sensor.java b/java_console/models/src/main/java/com/rusefi/core/Sensor.java index b553b712e3..4e48e84366 100644 --- a/java_console/models/src/main/java/com/rusefi/core/Sensor.java +++ b/java_console/models/src/main/java/com/rusefi/core/Sensor.java @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable; import java.io.DataOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; import java.util.Collection; import java.util.Comparator; import java.util.Set; @@ -201,6 +202,29 @@ public enum Sensor { throw new IllegalStateException("Sensor not found: " + value); } + public double getValueForChannel(ByteBuffer bb) { + switch (getType()) { + case FLOAT: + return bb.getFloat(); + case INT: + return bb.getInt(); + case UINT16: + // no cast - we want to discard sign + return bb.getInt() & 0xFFFF; + case INT16: + // cast - we want to retain sign + return (short)(bb.getInt() & 0xFFFF); + case UINT8: + // no cast - discard sign + return bb.getInt() & 0xFF; + case INT8: + // cast - retain sign + return (byte)(bb.getInt() & 0xFF); + default: + throw new UnsupportedOperationException("type " + getType()); + } + } + public String getName() { return name; } diff --git a/java_console/models/src/main/java/com/rusefi/core/SensorCentral.java b/java_console/models/src/main/java/com/rusefi/core/SensorCentral.java index 281e284268..32f15d4af9 100644 --- a/java_console/models/src/main/java/com/rusefi/core/SensorCentral.java +++ b/java_console/models/src/main/java/com/rusefi/core/SensorCentral.java @@ -16,7 +16,7 @@ public class SensorCentral implements ISensorCentral { public static final String RPM_KEY = "rpm"; private static final SensorCentral INSTANCE = new SensorCentral(); - private final Map values = new EnumMap<>(Sensor.class); + private final SensorsHolder sensorsHolder = new SensorsHolder(); private final Map> allListeners = new EnumMap<>(Sensor.class); private SensorListener2 anySensorListener; @@ -30,17 +30,12 @@ public class SensorCentral implements ISensorCentral { @Override public double getValue(Sensor sensor) { - Double value = values.get(sensor); - if (value == null) - return Double.NaN; - return value; + return sensorsHolder.getValue(sensor); } @Override - public void setValue(double value, final Sensor sensor) { - Double oldValue = values.get(sensor); - boolean isUpdated = oldValue == null || !oldValue.equals(value); - values.put(sensor, value); + public boolean setValue(double value, final Sensor sensor) { + boolean isUpdated = sensorsHolder.setValue(value, sensor); List listeners; synchronized (allListeners) { listeners = allListeners.get(sensor); @@ -50,9 +45,10 @@ public class SensorCentral implements ISensorCentral { applyValueToTables(value, sensor, isUpdated); if (listeners == null) - return; + return isUpdated; for (SensorListener listener : listeners) listener.onSensorUpdate(value); + return isUpdated; } private void applyValueToTables(double value, final Sensor sensor, boolean isUpdated) { diff --git a/java_console/models/src/main/java/com/rusefi/core/SensorsHolder.java b/java_console/models/src/main/java/com/rusefi/core/SensorsHolder.java new file mode 100644 index 0000000000..42a44df750 --- /dev/null +++ b/java_console/models/src/main/java/com/rusefi/core/SensorsHolder.java @@ -0,0 +1,22 @@ +package com.rusefi.core; + +import java.util.EnumMap; +import java.util.Map; + +public class SensorsHolder implements ISensorHolder { + private final Map values = new EnumMap<>(Sensor.class); + + public double getValue(Sensor sensor) { + Double value = values.get(sensor); + if (value == null) + return Double.NaN; + return value; + } + + public boolean setValue(double value, final Sensor sensor) { + Double oldValue = values.get(sensor); + boolean isUpdated = oldValue == null || !oldValue.equals(value); + values.put(sensor, value); + return isUpdated; + } +} diff --git a/java_tools/proxy_server/src/main/java/com/rusefi/server/Backend.java b/java_tools/proxy_server/src/main/java/com/rusefi/server/Backend.java index 2a1d1f4954..3d0568ecfa 100644 --- a/java_tools/proxy_server/src/main/java/com/rusefi/server/Backend.java +++ b/java_tools/proxy_server/src/main/java/com/rusefi/server/Backend.java @@ -4,6 +4,7 @@ import com.opensr5.Logger; import com.rusefi.Listener; import com.rusefi.Timeouts; import com.rusefi.binaryprotocol.BinaryProtocol; +import com.rusefi.core.Sensor; import com.rusefi.io.IoStream; import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.tcp.BinaryProtocolProxy; @@ -128,6 +129,7 @@ public class Backend implements Closeable { if (System.currentTimeMillis() - controller.getStream().getStreamStats().getPreviousPacketArrivalTime() > 20 * SECOND) { if (controller.getTwoKindSemaphore().acquireForShortTermUsage()) { try { + controller.grabOutputs(); } finally { controller.getTwoKindSemaphore().releaseFromShortTermUsage(); } @@ -257,10 +259,16 @@ public class Backend implements Closeable { JsonArrayBuilder builder = Json.createArrayBuilder(); List clients = getControllers(); for (ControllerConnectionState client : clients) { + // todo: at the moment we use current OutputChannel layout - a better way would be to take + // todo: OutputChannel from .ini file based on controller signature + int rpm = (int) client.getSensorsHolder().getValue(Sensor.RPM); + double clt = client.getSensorsHolder().getValue(Sensor.CLT); JsonObject controllerObject = Json.createObjectBuilder() .add(UserDetails.USER_ID, client.getUserDetails().getUserId()) .add(UserDetails.USERNAME, client.getUserDetails().getUserName()) .add(IS_USED, client.getTwoKindSemaphore().isUsed()) + .add("RPM", rpm) + .add("CLT", clt) .add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature()) .add(ControllerInfo.VEHICLE_NAME, client.getSessionDetails().getControllerInfo().getVehicleName()) .add(ControllerInfo.ENGINE_MAKE, client.getSessionDetails().getControllerInfo().getEngineMake()) diff --git a/java_tools/proxy_server/src/main/java/com/rusefi/server/ControllerConnectionState.java b/java_tools/proxy_server/src/main/java/com/rusefi/server/ControllerConnectionState.java index 89a6e37529..c987d73d97 100644 --- a/java_tools/proxy_server/src/main/java/com/rusefi/server/ControllerConnectionState.java +++ b/java_tools/proxy_server/src/main/java/com/rusefi/server/ControllerConnectionState.java @@ -3,16 +3,16 @@ package com.rusefi.server; import com.opensr5.Logger; import com.rusefi.auth.AutoTokenUtil; import com.rusefi.binaryprotocol.IncomingDataBuffer; +import com.rusefi.core.SensorsHolder; import com.rusefi.io.IoStream; import com.rusefi.io.commands.GetOutputsCommand; import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.tcp.TcpIoStream; import com.rusefi.shared.FileUtil; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.net.Socket; -import java.util.concurrent.Semaphore; -import java.util.concurrent.TimeUnit; public class ControllerConnectionState { private final Socket clientSocket; @@ -33,6 +33,7 @@ public class ControllerConnectionState { private ControllerKey controllerKey; private final TwoKindSemaphore twoKindSemaphore = new TwoKindSemaphore(); + private final SensorsHolder sensorsHolder = new SensorsHolder(); public ControllerConnectionState(Socket clientSocket, Logger logger, UserDetailsResolver userDetailsResolver) { this.clientSocket = clientSocket; @@ -89,12 +90,6 @@ public class ControllerConnectionState { return sessionDetails; } - public void runEndlessLoop() throws IOException { - while (true) { - getOutputs(); - } - } - public void getOutputs() throws IOException { byte[] commandPacket = GetOutputsCommand.createRequest(); @@ -103,9 +98,24 @@ public class ControllerConnectionState { byte[] packet = incomingData.getPacket(logger, "msg", true); if (packet == null) throw new IOException("getOutputs: No response"); + sensorsHolder.grabSensorValues(packet); } + @NotNull public TwoKindSemaphore getTwoKindSemaphore() { return twoKindSemaphore; } + + @NotNull + public SensorsHolder getSensorsHolder() { + return sensorsHolder; + } + + public void grabOutputs() { + try { + getOutputs(); + } catch (IOException e) { + close(); + } + } }