2019-09-21 16:04:58 +03:00
package com.chameleonvision.web ;
2019-10-13 21:58:34 +03:00
import com.chameleonvision.vision.Orientation ;
import com.chameleonvision.vision.SortMode ;
import com.chameleonvision.vision.TargetGroup ;
import com.chameleonvision.vision.TargetIntersection ;
2019-10-04 15:55:45 -04:00
import com.chameleonvision.vision.camera.CameraException ;
2019-09-21 16:04:58 +03:00
import com.chameleonvision.settings.SettingsManager ;
import com.chameleonvision.vision.camera.CameraManager ;
2019-10-14 11:21:20 +03:00
import com.fasterxml.jackson.core.JsonProcessingException ;
import com.fasterxml.jackson.core.type.TypeReference ;
import com.fasterxml.jackson.databind.ObjectMapper ;
2019-10-13 21:58:34 +03:00
import edu.wpi.cscore.VideoException ;
2019-10-11 02:25:25 +03:00
import io.javalin.websocket.* ;
2019-10-14 11:21:20 +03:00
2019-10-11 02:25:25 +03:00
import org.apache.commons.lang3.ArrayUtils ;
2019-10-14 11:21:20 +03:00
import org.eclipse.jetty.util.ArrayUtil ;
2019-10-12 03:38:42 +03:00
import org.msgpack.core.MessagePack ;
2019-10-14 11:21:20 +03:00
import org.msgpack.core.MessagePacker ;
2019-10-12 03:38:42 +03:00
import org.msgpack.core.MessageUnpacker ;
2019-10-14 11:21:20 +03:00
import org.msgpack.core.buffer.MessageBufferOutput ;
import org.msgpack.jackson.dataformat.MessagePackFactory ;
2019-10-12 03:38:42 +03:00
import org.msgpack.value.ImmutableArrayValue ;
import org.msgpack.value.ImmutableValue ;
import org.msgpack.value.Value ;
2019-10-13 22:59:36 +03:00
2019-10-14 11:21:20 +03:00
import java.io.IOException ;
2019-09-21 16:04:58 +03:00
import java.lang.reflect.Field ;
2019-10-14 11:21:20 +03:00
import java.nio.ByteBuffer ;
2019-10-11 02:25:25 +03:00
import java.util.* ;
2019-09-21 16:04:58 +03:00
2019-10-12 03:38:42 +03:00
2019-09-21 16:04:58 +03:00
public class ServerHandler {
private static List < WsContext > users ;
2019-10-14 11:21:20 +03:00
private static ObjectMapper objectMapper ;
2019-09-21 16:04:58 +03:00
2019-09-21 13:05:00 -04:00
ServerHandler ( ) {
users = new ArrayList < > ( ) ;
2019-10-14 11:21:20 +03:00
objectMapper = new ObjectMapper ( new MessagePackFactory ( ) ) ;
2019-09-21 16:04:58 +03:00
}
2019-09-21 13:05:00 -04:00
void onConnect ( WsConnectContext context ) {
2019-09-21 16:04:58 +03:00
users . add ( context ) ;
sendFullSettings ( ) ;
}
public void onClose ( WsCloseContext context ) {
users . remove ( context ) ;
}
2019-10-12 03:38:42 +03:00
void onBinaryMessage ( WsBinaryMessageContext data ) throws Exception {
2019-10-14 11:21:20 +03:00
Map < String , Object > deserialized = objectMapper . readValue ( ArrayUtils . toPrimitive ( data . data ( ) ) , new TypeReference < Map < String , Object > > ( ) { } ) ;
for ( Map . Entry < String , Object > entry : deserialized . entrySet ( ) ) {
2019-10-13 21:58:34 +03:00
try {
2019-10-14 11:21:20 +03:00
switch ( entry . getKey ( ) ) {
2019-10-13 22:59:36 +03:00
case " generalSettings " : {
//change general settings using a general settings object
break ;
}
case " cameraSettings " : {
//change camera settings using a camera settings object
break ;
}
case " command " : {
// used to define all incoming commands
break ;
}
case " currentCamera " : {
//camera name by string
break ;
}
case " currentPipeline " : {
// camera pipeline by index
break ;
}
default : { //Change pipeline values
//Two special cases for exposure and brightness changes
2019-10-14 11:21:20 +03:00
if ( entry . getKey ( ) . equals ( " exposure " ) )
2019-10-13 21:58:34 +03:00
try {
2019-10-14 11:21:20 +03:00
// CameraManager.getCurrentCamera().setExposure(value.asIntegerValue().toInt());
2019-10-13 21:58:34 +03:00
} catch ( VideoException e ) {
System . out . println ( " Exposure changes is not supported on your webcam/webcam's driver " ) ;
}
2019-10-14 11:21:20 +03:00
else if ( entry . getKey ( ) . equals ( " brightness " ) ) try {
// CameraManager.getCurrentCamera().setBrightness(value.asIntegerValue().toInt());
2019-10-13 22:59:36 +03:00
} catch ( VideoException e ) {
e . printStackTrace ( ) ;
}
else
2019-10-14 11:21:20 +03:00
// setValue(CameraManager.getCurrentPipeline(), entry.getKey(), entry.getValue());//All of the other assignments fields
2019-10-13 22:59:36 +03:00
break ;
2019-10-13 21:58:34 +03:00
}
}
2019-10-13 22:59:36 +03:00
} catch ( Exception e ) {
2019-10-14 00:03:22 +03:00
e . printStackTrace ( ) ;
2019-10-14 11:21:20 +03:00
// unexpectedData(key, value);
2019-10-13 21:58:34 +03:00
}
2019-10-12 03:38:42 +03:00
}
2019-09-21 16:04:58 +03:00
}
2019-10-13 22:59:36 +03:00
private void setValue ( Object obj , String fieldName , ImmutableValue value ) {
2019-09-21 16:04:58 +03:00
try {
2019-10-13 22:59:36 +03:00
boolean found = false ;
2019-10-13 21:58:34 +03:00
Field [ ] fields = obj . getClass ( ) . getFields ( ) ;
for ( Field f : fields ) {
if ( f . getName ( ) . equals ( fieldName ) ) {
2019-10-13 22:59:36 +03:00
found = true ;
if ( f . getType ( ) . isEnum ( ) ) //Field is enum like Orientation
f . set ( obj , f . getType ( ) . getEnumConstants ( ) [ value . asIntegerValue ( ) . toInt ( ) ] ) ;
else if ( value . isBooleanValue ( ) ) { //Field is boolean like erode
f . set ( obj , value . asBooleanValue ( ) . getBoolean ( ) ) ;
} else if ( value . isIntegerValue ( ) ) { //Field is int like M and B
f . set ( obj , value . asIntegerValue ( ) . toInt ( ) ) ;
} else if ( f . get ( obj ) instanceof List < ? > ) {
2019-10-13 21:58:34 +03:00
List < Value > valLst = ( ( ImmutableArrayValue ) value ) . list ( ) ;
2019-10-13 22:59:36 +03:00
if ( ( ( List ) f . get ( obj ) ) . get ( 0 ) . getClass ( ) . equals ( Float . class ) ) { //Field is List of Floats like area in pipeline
List < Float > lst = new ArrayList < > ( ) ;
for ( Value v : valLst ) {
lst . add ( v . isFloatValue ( ) ? v . asFloatValue ( ) . toFloat ( ) : ( float ) v . asIntegerValue ( ) . toInt ( ) ) ; //Adds float if value is float, casts value to float from int otherwise
}
f . set ( obj , lst ) ;
} else if ( ( ( List ) f . get ( obj ) ) . get ( 0 ) . getClass ( ) . equals ( Integer . class ) ) { //Fields is List of Integers like hue in pipeline
List < Integer > lst = new ArrayList < > ( ) ;
for ( Value v : valLst ) {
lst . add ( v . asIntegerValue ( ) . toInt ( ) ) ;
}
f . set ( obj , lst ) ;
2019-10-13 21:58:34 +03:00
}
}
2019-09-21 16:04:58 +03:00
}
}
2019-10-13 22:59:36 +03:00
if ( ! found )
unexpectedData ( fieldName , value ) ;
2019-10-12 03:38:42 +03:00
} catch ( Exception e ) {
2019-10-13 22:59:36 +03:00
System . out . println ( " Exception setting field " ) ;
2019-09-21 16:04:58 +03:00
e . printStackTrace ( ) ;
}
}
2019-10-13 22:59:36 +03:00
public void unexpectedData ( String key , ImmutableValue v ) {
System . err . println ( " Unexpected key or value, key= " + key + " Value= " + v . toString ( ) ) ;
//TODO send a error message to the user
//TODO in the very far future send a bug report?
2019-10-12 03:38:42 +03:00
}
private static void broadcastMessage ( Object obj , WsContext userToSkip ) {
if ( users ! = null )
for ( var user : users ) {
if ( userToSkip ! = null & & user . getSessionId ( ) . equals ( userToSkip . getSessionId ( ) ) ) {
continue ;
}
2019-10-14 11:21:20 +03:00
try {
ByteBuffer b = ByteBuffer . wrap ( objectMapper . writeValueAsBytes ( obj ) ) ;
user . send ( b ) ;
} catch ( JsonProcessingException e ) {
e . printStackTrace ( ) ;
}
2019-10-12 03:38:42 +03:00
}
2019-09-21 16:04:58 +03:00
}
2019-10-11 02:25:25 +03:00
public static void broadcastMessage ( Object obj ) { //TODO fix sending for msgpack
broadcastMessage ( obj , null ) ; //Broadcasts the message to every user
2019-09-21 16:04:58 +03:00
}
2019-10-13 21:58:34 +03:00
private static Map < String , Object > allFieldsToMap ( Object obj ) {
2019-09-21 16:04:58 +03:00
Map map = new HashMap < String , Object > ( ) ;
try {
Field [ ] fields = obj . getClass ( ) . getFields ( ) ;
for ( Field field : fields ) {
map . put ( field . getName ( ) , field . get ( obj ) ) ;
}
} catch ( IllegalAccessException e ) {
System . err . println ( " Illegal Access error: " + e . getStackTrace ( ) ) ;
}
return map ;
}
2019-09-22 02:49:30 -04:00
public static void sendFullSettings ( ) {
2019-09-21 16:04:58 +03:00
//General settings
Map < String , Object > fullSettings = new HashMap < > ( allFieldsToMap ( SettingsManager . GeneralSettings ) ) ;
fullSettings . put ( " cameraList " , CameraManager . getAllCamerasByName ( ) . keySet ( ) ) ;
try {
var currentCamera = CameraManager . getCurrentCamera ( ) ;
fullSettings . putAll ( allFieldsToMap ( currentCamera . getCurrentPipeline ( ) ) ) ;
fullSettings . put ( " pipelineList " , currentCamera . getPipelines ( ) . keySet ( ) ) ;
fullSettings . put ( " resolutionList " , CameraManager . getResolutionList ( ) ) ;
fullSettings . put ( " resolution " , currentCamera . getVideoModeIndex ( ) ) ;
fullSettings . put ( " FOV " , currentCamera . getFOV ( ) ) ;
2019-09-22 02:49:30 -04:00
fullSettings . put ( " port " , currentCamera . getStreamPort ( ) ) ;
2019-09-21 16:04:58 +03:00
} catch ( CameraException e ) {
System . err . println ( " No camera found! " ) ;
//TODO: add message to ui to inform that there are no cameras
}
2019-10-14 00:03:22 +03:00
// broadcastMessage(fullSettings);
2019-09-21 16:04:58 +03:00
}
}