proxy progress - hopefully getting closer?!

This commit is contained in:
rusefi 2020-07-22 20:13:12 -04:00
parent 2de7d590f5
commit 2fdbf01a5d
8 changed files with 107 additions and 63 deletions

View File

@ -9,10 +9,7 @@ import com.rusefi.Timeouts;
import com.rusefi.composite.CompositeEvent; import com.rusefi.composite.CompositeEvent;
import com.rusefi.composite.CompositeParser; import com.rusefi.composite.CompositeParser;
import com.rusefi.config.generated.Fields; import com.rusefi.config.generated.Fields;
import com.rusefi.core.MessagesCentral; import com.rusefi.core.*;
import com.rusefi.core.Pair;
import com.rusefi.core.Sensor;
import com.rusefi.core.SensorCentral;
import com.rusefi.io.*; import com.rusefi.io.*;
import com.rusefi.io.commands.GetOutputsCommand; import com.rusefi.io.commands.GetOutputsCommand;
import com.rusefi.stream.LogicdataStreamFile; import com.rusefi.stream.LogicdataStreamFile;
@ -588,45 +585,10 @@ public class BinaryProtocol implements BinaryProtocolCommands {
state.setCurrentOutputs(response); state.setCurrentOutputs(response);
for (Sensor sensor : Sensor.values()) { SensorCentral.getInstance().grabSensorValues(response);
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);
}
return true; 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) { public void setRange(byte[] src, int scrPos, int offset, int count) {
state.setRange(src, scrPos, offset, count); state.setRange(src, scrPos, offset, count);
} }

View File

@ -4,11 +4,7 @@ package com.rusefi.core;
* 11/16/2017 * 11/16/2017
* Andrey Belomutskiy, (c) 2013-2020 * Andrey Belomutskiy, (c) 2013-2020
*/ */
public interface ISensorCentral { public interface ISensorCentral extends ISensorHolder {
double getValue(Sensor sensor);
void setValue(double value, Sensor sensor);
void setAnySensorListener(SensorCentral.SensorListener2 anySensorListener); void setAnySensorListener(SensorCentral.SensorListener2 anySensorListener);
void addListener(Sensor sensor, SensorCentral.SensorListener listener); void addListener(Sensor sensor, SensorCentral.SensorListener listener);

View File

@ -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);
}

View File

@ -6,6 +6,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.DataOutputStream; import java.io.DataOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Set; import java.util.Set;
@ -201,6 +202,29 @@ public enum Sensor {
throw new IllegalStateException("Sensor not found: " + value); 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() { public String getName() {
return name; return name;
} }

View File

@ -16,7 +16,7 @@ public class SensorCentral implements ISensorCentral {
public static final String RPM_KEY = "rpm"; public static final String RPM_KEY = "rpm";
private static final SensorCentral INSTANCE = new SensorCentral(); private static final SensorCentral INSTANCE = new SensorCentral();
private final Map<Sensor, Double> values = new EnumMap<>(Sensor.class); private final SensorsHolder sensorsHolder = new SensorsHolder();
private final Map<Sensor, List<SensorListener>> allListeners = new EnumMap<>(Sensor.class); private final Map<Sensor, List<SensorListener>> allListeners = new EnumMap<>(Sensor.class);
private SensorListener2 anySensorListener; private SensorListener2 anySensorListener;
@ -30,17 +30,12 @@ public class SensorCentral implements ISensorCentral {
@Override @Override
public double getValue(Sensor sensor) { public double getValue(Sensor sensor) {
Double value = values.get(sensor); return sensorsHolder.getValue(sensor);
if (value == null)
return Double.NaN;
return value;
} }
@Override @Override
public void setValue(double value, final Sensor sensor) { public boolean setValue(double value, final Sensor sensor) {
Double oldValue = values.get(sensor); boolean isUpdated = sensorsHolder.setValue(value, sensor);
boolean isUpdated = oldValue == null || !oldValue.equals(value);
values.put(sensor, value);
List<SensorListener> listeners; List<SensorListener> listeners;
synchronized (allListeners) { synchronized (allListeners) {
listeners = allListeners.get(sensor); listeners = allListeners.get(sensor);
@ -50,9 +45,10 @@ public class SensorCentral implements ISensorCentral {
applyValueToTables(value, sensor, isUpdated); applyValueToTables(value, sensor, isUpdated);
if (listeners == null) if (listeners == null)
return; return isUpdated;
for (SensorListener listener : listeners) for (SensorListener listener : listeners)
listener.onSensorUpdate(value); listener.onSensorUpdate(value);
return isUpdated;
} }
private void applyValueToTables(double value, final Sensor sensor, boolean isUpdated) { private void applyValueToTables(double value, final Sensor sensor, boolean isUpdated) {

View File

@ -0,0 +1,22 @@
package com.rusefi.core;
import java.util.EnumMap;
import java.util.Map;
public class SensorsHolder implements ISensorHolder {
private final Map<Sensor, Double> 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;
}
}

View File

@ -4,6 +4,7 @@ import com.opensr5.Logger;
import com.rusefi.Listener; import com.rusefi.Listener;
import com.rusefi.Timeouts; import com.rusefi.Timeouts;
import com.rusefi.binaryprotocol.BinaryProtocol; import com.rusefi.binaryprotocol.BinaryProtocol;
import com.rusefi.core.Sensor;
import com.rusefi.io.IoStream; import com.rusefi.io.IoStream;
import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.commands.HelloCommand;
import com.rusefi.io.tcp.BinaryProtocolProxy; 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 (System.currentTimeMillis() - controller.getStream().getStreamStats().getPreviousPacketArrivalTime() > 20 * SECOND) {
if (controller.getTwoKindSemaphore().acquireForShortTermUsage()) { if (controller.getTwoKindSemaphore().acquireForShortTermUsage()) {
try { try {
controller.grabOutputs();
} finally { } finally {
controller.getTwoKindSemaphore().releaseFromShortTermUsage(); controller.getTwoKindSemaphore().releaseFromShortTermUsage();
} }
@ -257,10 +259,16 @@ public class Backend implements Closeable {
JsonArrayBuilder builder = Json.createArrayBuilder(); JsonArrayBuilder builder = Json.createArrayBuilder();
List<ControllerConnectionState> clients = getControllers(); List<ControllerConnectionState> clients = getControllers();
for (ControllerConnectionState client : clients) { 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() JsonObject controllerObject = Json.createObjectBuilder()
.add(UserDetails.USER_ID, client.getUserDetails().getUserId()) .add(UserDetails.USER_ID, client.getUserDetails().getUserId())
.add(UserDetails.USERNAME, client.getUserDetails().getUserName()) .add(UserDetails.USERNAME, client.getUserDetails().getUserName())
.add(IS_USED, client.getTwoKindSemaphore().isUsed()) .add(IS_USED, client.getTwoKindSemaphore().isUsed())
.add("RPM", rpm)
.add("CLT", clt)
.add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature()) .add(ControllerInfo.SIGNATURE, client.getSessionDetails().getControllerInfo().getSignature())
.add(ControllerInfo.VEHICLE_NAME, client.getSessionDetails().getControllerInfo().getVehicleName()) .add(ControllerInfo.VEHICLE_NAME, client.getSessionDetails().getControllerInfo().getVehicleName())
.add(ControllerInfo.ENGINE_MAKE, client.getSessionDetails().getControllerInfo().getEngineMake()) .add(ControllerInfo.ENGINE_MAKE, client.getSessionDetails().getControllerInfo().getEngineMake())

View File

@ -3,16 +3,16 @@ package com.rusefi.server;
import com.opensr5.Logger; import com.opensr5.Logger;
import com.rusefi.auth.AutoTokenUtil; import com.rusefi.auth.AutoTokenUtil;
import com.rusefi.binaryprotocol.IncomingDataBuffer; import com.rusefi.binaryprotocol.IncomingDataBuffer;
import com.rusefi.core.SensorsHolder;
import com.rusefi.io.IoStream; import com.rusefi.io.IoStream;
import com.rusefi.io.commands.GetOutputsCommand; import com.rusefi.io.commands.GetOutputsCommand;
import com.rusefi.io.commands.HelloCommand; import com.rusefi.io.commands.HelloCommand;
import com.rusefi.io.tcp.TcpIoStream; import com.rusefi.io.tcp.TcpIoStream;
import com.rusefi.shared.FileUtil; import com.rusefi.shared.FileUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
public class ControllerConnectionState { public class ControllerConnectionState {
private final Socket clientSocket; private final Socket clientSocket;
@ -33,6 +33,7 @@ public class ControllerConnectionState {
private ControllerKey controllerKey; private ControllerKey controllerKey;
private final TwoKindSemaphore twoKindSemaphore = new TwoKindSemaphore(); private final TwoKindSemaphore twoKindSemaphore = new TwoKindSemaphore();
private final SensorsHolder sensorsHolder = new SensorsHolder();
public ControllerConnectionState(Socket clientSocket, Logger logger, UserDetailsResolver userDetailsResolver) { public ControllerConnectionState(Socket clientSocket, Logger logger, UserDetailsResolver userDetailsResolver) {
this.clientSocket = clientSocket; this.clientSocket = clientSocket;
@ -89,12 +90,6 @@ public class ControllerConnectionState {
return sessionDetails; return sessionDetails;
} }
public void runEndlessLoop() throws IOException {
while (true) {
getOutputs();
}
}
public void getOutputs() throws IOException { public void getOutputs() throws IOException {
byte[] commandPacket = GetOutputsCommand.createRequest(); byte[] commandPacket = GetOutputsCommand.createRequest();
@ -103,9 +98,24 @@ public class ControllerConnectionState {
byte[] packet = incomingData.getPacket(logger, "msg", true); byte[] packet = incomingData.getPacket(logger, "msg", true);
if (packet == null) if (packet == null)
throw new IOException("getOutputs: No response"); throw new IOException("getOutputs: No response");
sensorsHolder.grabSensorValues(packet);
} }
@NotNull
public TwoKindSemaphore getTwoKindSemaphore() { public TwoKindSemaphore getTwoKindSemaphore() {
return twoKindSemaphore; return twoKindSemaphore;
} }
@NotNull
public SensorsHolder getSensorsHolder() {
return sensorsHolder;
}
public void grabOutputs() {
try {
getOutputs();
} catch (IOException e) {
close();
}
}
} }