diff --git a/CMakeLists.txt b/CMakeLists.txt index 813fb571..a670f541 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,10 @@ if(NO_CANLIB) add_compile_definitions(NO_CANLIB) endif() +if(NO_INFLUX) + MESSAGE(STATUS "InfluxDB is not used") + add_compile_definitions(NO_INFLUX) +endif() if(UNIX AND NOT APPLE) set(LINUX TRUE) diff --git a/README.md b/README.md index e2b4ed3e..85bb1c0d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,97 @@ # Low Level Server for the Engine Control User Interface +# Development Setup +The LLServer is meant to be used in conjuction with a can-bus and an influxdb logging server. +For local development the following setup is recommended: + +## can interface +The LLServer still requires a can interface to be present on the system to function. +You can create a dummy can interface with the following commands: +```bash +sudo modprobe vcan +sudo ip link add dev vcan0 type vcan +sudo ip link set up vcan0 +``` + +## Building the LLServer +Use the following cmake variables to run the LLServer in Dev Mode: +```bash +mkdir build && cd build +cmake -D NO_PYTHON=true -D NO_CANLIB=true -D NO_INFLUX=true .. -o ./ +make -j +``` +This disables the python bindings, the canbus interface and the influxdb logging. + +## Running the LLServer +The LLServer requires a `config.json` and a `mapping.json` file to run. You can find examples in the `config` folder. + +To run the LLServer with the example config files, use the following command: +```bash + ECUI_CONFIG_PATH=$(dirname "$PWD")/sample_config ./llserver_ecui_houbolt +``` + +Please note that without the CAN Bus none of the commands will work. You can crudely some for testing like this in the LLInterface::init: + +```c++ + auto doStuff = [](std::vector &data, bool flag) { + std::string str = [&data] { + std::ostringstream oss; + std::copy(data.begin(), data.end(), std::ostream_iterator(oss, " ")); + return oss.str(); + }(); + Debug::print("doStuff flag: %d values: %s", flag, str.c_str()); + }; + + eventManager->AddCommands({{"doStuff", {doStuff, {}}}}); + +``` + + + +## Emulating the ECUI +The LLServer communicates over a TCP-Socket with the [ECUI](https://github.com/SpaceTeam/web_ecui_houbolt). +To emulate this one can use the [ECUIEmulator.py](scripts/ECUIEmulator.py) script. +You have to set the message `type` and `data` and it will send it to the LLServer. +Responses are logged to the console. + +Eg. Starting a sequence: +```bash +python3 scripts/ECUIEmulator.py +Starting JSON socket server. +Enter your message type(one of sequence-start, send-postseq-comment, abort, auto-abort-change, states-load, states-get, states-set, states-start, states-stop, gui-mapping-load, commands-load, commands-set): +sequence-start +Enter your JSON message (send with `END` in a new line): +{ + "globals": { + "endTime": 10, + "interpolation": { + "doStuff": "none" + }, + "interval": 0.01, + "startTime": -3 + }, + "data": [ + { + "timestamp": "START", + "name": "start", + "desc": "start", + "actions": [ + { + "timestamp": 0.0, + "doStuff": [ + 2 + ] + } + ] + } + + ] +} +END +Message sent. + +``` + ## Links Documentation of whole ECUI and Setup Guide diff --git a/sample_config/config.json b/sample_config/config.json new file mode 100644 index 00000000..7f2e3981 --- /dev/null +++ b/sample_config/config.json @@ -0,0 +1,111 @@ +{ + "version": "1.3.1@Lamarr", + "autoabort": false, + "pyenv": "/home/.local/lib/python3.8/site-packages", + "auto_start": true, + "DEBUG": { + "printWarnings": true, + "printInfos": true + }, + "socket_msg_size": 65536, + "LOGGING": { + "post_sequence_script": "scripts/plot.sh" + }, + "use_lora": false, + "LORA": { + "ip": "192.168.100.5", + "port": 5001, + "nodeIDsRef": [ + 33, + 31, + 32, + 29 + ], + "nodeIDs": [ + 13, + 11, + 12, + 19 + ], + "canMsgSizes": [ + 48, + 48, + 48, + 39 + ] + }, + "CAN": { + "node_count": 0, + "blocking_timeout": 2048, + "BUS": { + "ARBITRATION": { + "bitrate": 1000000, + "time_segment_1": 23, + "time_segment_2": 16, + "sync_jump_width": 1, + "no_sampling_points": 1 + }, + "DATA": { + "bitrate": 4000000, + "time_segment_1": 7, + "time_segment_2": 2, + "sync_jump_width": 2 + } + }, + "DRIVER": "SocketCAN", + "DEVICE": [ + "vcan0" + ], + "BUS_EXTRA": { + "1": { + "ARBITRATION": { + "bitrate": 1000000, + "time_segment_1": 7, + "time_segment_2": 2, + "sync_jump_width": 1, + "no_sampling_points": 1 + }, + "DATA": { + "bitrate": 8000000, + "time_segment_1": 7, + "time_segment_2": 2, + "sync_jump_width": 1 + } + } + }, + "canBusChannelIDs": [ + 0, + 1, + 2, + 3 + ] + }, + "LLSERVER": { + "sensor_state_sampling_rate": 10.0 + }, + "WEBSERVER": { + "ip": "127.0.0.1", + "port": 8080, + "state_transmission_rate": 10.0, + "timer_sync_rate": 10, + "sensors_smoothing_factor": 0.3 + }, + "INFLUXDB": { + "database_ip": "192.168.100.2", + "database_port": 8086, + "database_name": "gse", + "debug_measurement": "debug", + "state_measurement": "states", + "fast_sensor_measurement": "sensors", + "buffer_size": 2048, + "fast_sensor_buffer_size": 65536, + "enable_fast_sensor_logging": true + }, + "THRUST": { + "alpha": 0.785398, + "beta": 0.785398, + "gamma": 0.785398, + "d": 0.28, + "r": 0.14 + } +} diff --git a/sample_config/mapping.json b/sample_config/mapping.json new file mode 100644 index 00000000..2ced6b65 --- /dev/null +++ b/sample_config/mapping.json @@ -0,0 +1,1447 @@ +{ + "CANMapping": { + "3": { + "0": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "blmb_valve" + }, + "1": { + "stringID": "blmb_unused_unused_pressure" + }, + "2": { + "stringID": "blmb_unused_unused_what" + }, + "stringID": "blmb" + }, + "31": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "fuel_tank_pressure" + }, + "1": { + "offset": -100, + "slope": 0.125885, + "stringID": "fuel_pressurant_pressure" + }, + "10": { + "stringID": "fuel_igniter_1" + }, + "11": { + "stringID": "fuel_igniter_1_cont" + }, + "12": { + "stringID": "fuel_igniter_2" + }, + "13": { + "stringID": "fuel_igniter_2_cont" + }, + "14": { + "stringID": "fuel_igniter_3" + }, + "15": { + "stringID": "fuel_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "fuel_pi_controller" + }, + "17": { + "stringID": "fuel_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "fuel_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "fuel_sense_12V" + }, + "2": { + "offset": -100, + "slope": 0.125885, + "stringID": "fuel_pressure_2" + }, + "20": { + "slope": 0.008921110838, + "stringID": "fuel_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "fuel_pressure_3" + }, + "4": { + "offset": -313, + "slope": 0.0188, + "stringID": "fuel_temp_0" + }, + "5": { + "offset": -313, + "slope": 0.0188, + "stringID": "fuel_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "fuel_pressurant_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "fuel_servo_1" + }, + "8": { + "stringID": "fuel_vent" + }, + "9": { + "stringID": "fuel_vent_cont" + }, + "stringID": "fuel_ecu" + }, + "32": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "ox_tank_pressure" + }, + "1": { + "offset": -100, + "slope": 0.125885, + "stringID": "ox_pressurant_pressure" + }, + "10": { + "stringID": "ox_igniter_1" + }, + "11": { + "stringID": "ox_igniter_1_cont" + }, + "12": { + "stringID": "ox_igniter_2" + }, + "13": { + "stringID": "ox_igniter_2_cont" + }, + "14": { + "stringID": "ox_igniter_3" + }, + "15": { + "stringID": "ox_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "ox_pi_controller" + }, + "17": { + "stringID": "ox_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "ox_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "ox_sense_12V" + }, + "2": { + "offset": -100, + "slope": 0.125885, + "stringID": "ox_pressure_2" + }, + "20": { + "slope": 0.008921110838, + "stringID": "ox_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "ox_pressure_3" + }, + "4": { + "offset": -313, + "slope": 0.0188, + "stringID": "ox_temp_0" + }, + "5": { + "offset": -308, + "slope": 0.0188, + "stringID": "ox_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "ox_pressurant_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "ox_servo_1" + }, + "8": { + "stringID": "ox_vent" + }, + "9": { + "stringID": "ox_vent_cont" + }, + "stringID": "ox_ecu" + }, + "33": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "fuel_venturi_pressure" + }, + "1": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "ox_venturi_pressure" + }, + "10": { + "stringID": "internal_igniter_1" + }, + "11": { + "stringID": "internal_igniter_1_cont" + }, + "12": { + "stringID": "internal_igniter_2" + }, + "13": { + "stringID": "internal_igniter_2_cont" + }, + "14": { + "stringID": "engine_igniter_3" + }, + "15": { + "stringID": "engine_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "engine_ox_main_pi_controller" + }, + "17": { + "stringID": "rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "engine_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "engine_sense_12V" + }, + "2": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "chamber_pressure" + }, + "20": { + "slope": 0.008921110838, + "stringID": "engine_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "engine_pressure_3" + }, + "4": { + "stringID": "engine_temp_0" + }, + "5": { + "stringID": "engine_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "fuel_main_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "ox_main_valve" + }, + "8": { + "stringID": "engine_igniter_0" + }, + "9": { + "stringID": "engine_igniter_0_cont" + }, + "stringID": "engine_ecu" + }, + "34": { + "0": { + "offset": 2200, + "slope": -2, + "stringID": "pressurant_tanking_valve_feedback" + }, + "1": { + "offset": 2200, + "slope": -2, + "stringID": "pressurant_vent_valve_feedback" + }, + "10": { + "stringID": "pressurant_vent_valve" + }, + "11": { + "stringID": "pressurant_vent_valve_cont" + }, + "12": { + "stringID": "ox_tanking_valve" + }, + "13": { + "stringID": "ox_tanking_valve_cont" + }, + "14": { + "stringID": "holddown" + }, + "15": { + "stringID": "holddown_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "gse_pneu_unused_pi_controller" + }, + "17": { + "stringID": "gse_pneu_unused_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "gse_pneu_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "gse_pneu_sense_12V" + }, + "2": { + "offset": 2200, + "slope": -2, + "stringID": "ox_tanking_valve_feedback" + }, + "20": { + "slope": 0.008921110838, + "stringID": "gse_pneu_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "ox_decoupler_feedback" + }, + "4": { + "stringID": "gse_pneu_temp_0" + }, + "5": { + "stringID": "gse_pneu_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "gse_pneu_servo_0" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "gse_pneu_servo_1" + }, + "8": { + "stringID": "pressurant_tanking_valve" + }, + "9": { + "stringID": "pressurant_tanking_valve_cont" + }, + "stringID": "gse_pneu_ecu" + }, + "35": { + "0": { + "offset": -100, + "slope": 0.125885, + "stringID": "pressurant_tanking_pressure" + }, + "1": { + "offset": 0, + "slope": 1, + "stringID": "gse_elec_press_1" + }, + "10": { + "stringID": "strongback" + }, + "11": { + "stringID": "strongback_cont" + }, + "12": { + "stringID": "dewar_pressurize_solenoid" + }, + "13": { + "stringID": "dewar_pressurize_solenoid_cont" + }, + "14": { + "stringID": "gse_igniter_3" + }, + "15": { + "stringID": "gse_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "gse_elec_unused_pi_controller" + }, + "17": { + "stringID": "gse_elec_unused_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "gse_elec_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "gse_elec_sense_12V" + }, + "2": { + "offset": 0, + "slope": 1, + "stringID": "gse_elec_press_2" + }, + "20": { + "slope": 0.008921110838, + "stringID": "gse_elec_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "gse_elec_press_3" + }, + "4": { + "stringID": "gse_elec_temp_0" + }, + "5": { + "stringID": "gse_elec_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "gse_elec_servo_0" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "gse_elec_servo_1" + }, + "8": { + "stringID": "ox_decoupler" + }, + "9": { + "stringID": "ox_decoupler_cont" + }, + "stringID": "gse_elec_ecu" + }, + "8": { + "0": { + "offset": -18.935077, + "slope": 5.32e-06, + "stringID": "rocket_weight" + }, + "1": { + "offset": -37.171132400000005, + "slope": -1.48e-05, + "stringID": "dewar_weight" + }, + "2": { + "offset": -10.2876298, + "slope": 5.32e-06, + "stringID": "fuel_weight" + }, + "3": { + "offset": -14.20285865926, + "slope": 5.57269e-06, + "stringID": "ox_weight" + }, + "4": { + "offset": -0.23615210499999995, + "slope": 4.46075e-05, + "stringID": "unused_lcb_force_4" + }, + "5": { + "offset": -1794695.0, + "slope": 1.0, + "stringID": "unused_lcb_force_5" + }, + "6": { + "offset": -452668.0, + "slope": 1.0, + "stringID": "unused_lcb_force_6" + }, + "7": { + "offset": -1360714.0, + "slope": 1.0, + "stringID": "unused_lcb_force_7" + }, + "stringID": "teststand_lcb" + }, + "29": { + "18": { + "slope": 0.001622020152, + "stringID": "engine_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "engine_sense_12V" + }, + "0": { + "offset": 0, + "slope": 0.001622020152, + "stringID": "rcu_5V_voltage" + }, + "1": { + "offset": 0, + "slope": 0.00535, + "stringID": "rcu_12V_voltage" + }, + "10": { + "offset": 0, + "slope": 0.0000001, + "stringID": "gps_latitude" + }, + "11": { + "offset": 0, + "slope": 1.0, + "stringID": "gps_altitude" + }, + "2": { + "offset": 0, + "slope": 0.00024414, + "stringID": "rcu_barometer" + }, + "3": { + "offset": -16, + "slope": 0.0078125, + "stringID": "rcu_accel_x" + }, + "4": { + "offset": -16, + "slope": 0.0078125, + "stringID": "rcu_accel_y" + }, + "5": { + "offset": -16, + "slope": 0.0078125, + "stringID": "rcu_accel_z" + }, + "6": { + "offset": -2000, + "slope": 0.97656, + "stringID": "rcu_gyro_x" + }, + "7": { + "offset": -2000, + "slope": 0.97656, + "stringID": "rcu_gyro_y" + }, + "8": { + "offset": -2000, + "slope": 0.97656, + "stringID": "rcu_gyro_z" + }, + "9": { + "offset": 0, + "slope": 0.0000001, + "stringID": "gps_longitude" + }, + "12": { + "offset": 0, + "slope": 1.0, + "stringID": "gps_status" + }, + "13": { + "offset": 0, + "slope": 1.0, + "stringID": "rcu_out_0" + }, + "14": { + "offset": 0, + "slope": 1.0, + "stringID": "camera_1" + }, + "15": { + "offset": 0, + "slope": 1.0, + "stringID": "camera_2" + }, + "16": { + "offset": 0, + "slope": 1.0, + "stringID": "rcu_out_3" + }, + "stringID": "rcu" + }, + "11": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "lora:fuel_tank_pressure" + }, + "1": { + "offset": -100, + "slope": 0.125885, + "stringID": "lora:fuel_pressurant_pressure" + }, + "10": { + "stringID": "lora:fuel_igniter_1" + }, + "11": { + "stringID": "lora:fuel_igniter_1_cont" + }, + "12": { + "stringID": "lora:fuel_igniter_2" + }, + "13": { + "stringID": "lora:fuel_igniter_2_cont" + }, + "14": { + "stringID": "lora:fuel_igniter_3" + }, + "15": { + "stringID": "lora:fuel_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "lora:fuel_pi_controller" + }, + "17": { + "stringID": "lora:fuel_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "lora:fuel_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "lora:fuel_sense_12V" + }, + "2": { + "offset": -100, + "slope": 0.125885, + "stringID": "lora:fuel_pressure_2" + }, + "20": { + "slope": 0.008921110838, + "stringID": "lora:fuel_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "lora:fuel_pressure_3" + }, + "4": { + "offset": -313, + "slope": 0.0188, + "stringID": "lora:fuel_temp_0" + }, + "5": { + "offset": -313, + "slope": 0.0188, + "stringID": "lora:fuel_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:fuel_pressurant_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:fuel_servo_1" + }, + "8": { + "stringID": "lora:fuel_vent" + }, + "9": { + "stringID": "lora:fuel_vent_cont" + }, + "stringID": "lora:fuel_ecu" + }, + "12": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "lora:ox_tank_pressure" + }, + "1": { + "offset": -100, + "slope": 0.125885, + "stringID": "lora:ox_pressurant_pressure" + }, + "10": { + "stringID": "lora:ox_igniter_1" + }, + "11": { + "stringID": "lora:ox_igniter_1_cont" + }, + "12": { + "stringID": "lora:ox_igniter_2" + }, + "13": { + "stringID": "lora:ox_igniter_2_cont" + }, + "14": { + "stringID": "lora:ox_igniter_3" + }, + "15": { + "stringID": "lora:ox_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "lora:ox_pi_controller" + }, + "17": { + "stringID": "lora:ox_rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "lora:ox_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "lora:ox_sense_12V" + }, + "2": { + "offset": -100, + "slope": 0.125885, + "stringID": "lora:ox_pressure_2" + }, + "20": { + "slope": 0.008921110838, + "stringID": "lora:ox_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "lora:ox_pressure_3" + }, + "4": { + "offset": -313, + "slope": 0.0188, + "stringID": "lora:ox_temp_0" + }, + "5": { + "offset": -308, + "slope": 0.0188, + "stringID": "lora:ox_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:ox_pressurant_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:ox_servo_1" + }, + "8": { + "stringID": "lora:ox_vent" + }, + "9": { + "stringID": "lora:ox_vent_cont" + }, + "stringID": "lora:ox_ecu" + }, + "13": { + "0": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "lora:fuel_venturi_pressure" + }, + "1": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "lora:ox_venturi_pressure" + }, + "10": { + "stringID": "lora:internal_igniter_1" + }, + "11": { + "stringID": "lora:internal_igniter_1_cont" + }, + "12": { + "stringID": "lora:internal_igniter_2" + }, + "13": { + "stringID": "lora:internal_igniter_2_cont" + }, + "14": { + "stringID": "lora:engine_igniter_3" + }, + "15": { + "stringID": "lora:engine_igniter_3_cont" + }, + "16": { + "slope": 0.001525879, + "stringID": "lora:engine_ox_main_pi_controller" + }, + "17": { + "stringID": "lora:rocket" + }, + "18": { + "slope": 0.001622020152, + "stringID": "lora:engine_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "lora:engine_sense_12V" + }, + "2": { + "offset": -15, + "slope": 0.01888275146, + "stringID": "lora:chamber_pressure" + }, + "20": { + "slope": 0.008921110838, + "stringID": "lora:engine_sense_12VA" + }, + "3": { + "offset": 0, + "slope": 1, + "stringID": "lora:engine_pressure_3" + }, + "4": { + "stringID": "lora:engine_temp_0" + }, + "5": { + "stringID": "lora:engine_temp_1" + }, + "6": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:fuel_main_valve" + }, + "7": { + "offset": 0.0, + "slope": 0.00152590219, + "stringID": "lora:ox_main_valve" + }, + "8": { + "stringID": "lora:engine_igniter_0" + }, + "9": { + "stringID": "lora:engine_igniter_0_cont" + }, + "stringID": "lora:engine_ecu" + }, + "19": { + "18": { + "slope": 0.001622020152, + "stringID": "lora:engine_sense_5V" + }, + "19": { + "slope": 0.008921110838, + "stringID": "lora:engine_sense_12V" + }, + "0": { + "offset": 0, + "slope": 0.001622020152, + "stringID": "lora:rcu_5V_voltage" + }, + "1": { + "offset": 0, + "slope": 0.00535, + "stringID": "lora:rcu_12V_voltage" + }, + "10": { + "offset": 0, + "slope": 0.0000001, + "stringID": "lora:gps_latitude" + }, + "11": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:gps_altitude" + }, + "2": { + "offset": 0, + "slope": 0.00024414, + "stringID": "lora:rcu_barometer" + }, + "3": { + "offset": -16, + "slope": 0.0078125, + "stringID": "lora:rcu_accel_x" + }, + "4": { + "offset": -16, + "slope": 0.0078125, + "stringID": "lora:rcu_accel_y" + }, + "5": { + "offset": -16, + "slope": 0.0078125, + "stringID": "lora:rcu_accel_z" + }, + "6": { + "offset": -2000, + "slope": 0.97656, + "stringID": "lora:rcu_gyro_x" + }, + "7": { + "offset": -2000, + "slope": 0.97656, + "stringID": "lora:rcu_gyro_y" + }, + "8": { + "offset": -2000, + "slope": 0.97656, + "stringID": "lora:rcu_gyro_z" + }, + "9": { + "offset": 0, + "slope": 0.0000001, + "stringID": "lora:gps_longitude" + }, + "12": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:gps_status" + }, + "13": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:rcu_out_0" + }, + "14": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:camera_1" + }, + "15": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:camera_2" + }, + "16": { + "offset": 0, + "slope": 1.0, + "stringID": "lora:rcu_out_3" + }, + "stringID": "lora:rcu" + } + }, + "DefaultEventMapping": { + "DigitalOut": [ + { + "command": "DigitalOut:SetState", + "parameters": [ + "DigitalOut" + ] + } + ], + "Servo": [ + { + "command": "Servo:SetTargetPosition", + "parameters": [ + "Servo" + ] + } + ] + }, + "EventMapping": { + "engine_ecu:FlashStatus": [ + { + "state": "gui:Flash:Clear", + "triggerType": "!=", + "triggerValue": 0, + "value": 0 + } + ], + "ox_ecu:FlashStatus": [ + { + "state": "gui:Flash:Clear", + "triggerType": "!=", + "triggerValue": 0, + "value": 0 + } + ], + "fuel_ecu:FlashStatus": [ + { + "state": "gui:Flash:Clear", + "triggerType": "!=", + "triggerValue": 0, + "value": 0 + } + ], + "rcu:FlashStatus": [ + { + "state": "gui:Flash:Clear", + "triggerType": "!=", + "triggerValue": 0, + "value": 0 + } + ], + "gui:Flash:Clear": [ + { + "command": "engine_ecu:RequestFlashClear", + "parameters": [] + }, + { + "command": "ox_ecu:RequestFlashClear", + "parameters": [] + }, + { + "command": "fuel_ecu:RequestFlashClear", + "parameters": [] + }, + { + "command": "rcu:RequestFlashClear", + "parameters": [] + } + ], + "gui:FlushDatabase": [ + { + "command": "FlushDatabase", + "parameters": [] + } + ], + "gui:Logging": [ + { + "command": "engine_ecu:SetLoggingEnabled", + "parameters": [ + "gui:Logging" + ] + }, + { + "command": "ox_ecu:SetLoggingEnabled", + "parameters": [ + "gui:Logging" + ] + }, + { + "command": "fuel_ecu:SetLoggingEnabled", + "parameters": [ + "gui:Logging" + ] + }, + { + "command": "rcu:SetLoggingEnabled", + "parameters": [ + "gui:Logging" + ] + } + ], + "gui:LoraEnabled": [ + { + "command": "rcu:SetLoraEnabled", + "parameters": [ + "gui:LoraEnabled" + ] + } + ], + "gui:dewar_weight:Tare": [ + { + "command": "Tare", + "parameters": [ + 8, + 1, + "dewar_weight:sensor" + ] + } + ], + "gui:fuel_pi_controller:GetI_NEG": [ + { + "command": "fuel_pi_controller:GetI_NEG", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetI_POS": [ + { + "command": "fuel_pi_controller:GetI_POS", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetOperatingPoint": [ + { + "command": "fuel_pi_controller:GetOperatingPoint", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetP_NEG": [ + { + "command": "fuel_pi_controller:GetP_NEG", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetP_POS": [ + { + "command": "fuel_pi_controller:GetP_POS", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetSensorChannelID": [ + { + "command": "fuel_pi_controller:GetSensorChannelID", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetSensorOffset": [ + { + "command": "fuel_pi_controller:GetSensorOffset", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetSensorSlope": [ + { + "command": "fuel_pi_controller:GetSensorSlope", + "parameters": [] + } + ], + "gui:fuel_pi_controller:GetTarget": [ + { + "command": "fuel_pi_controller:GetTarget", + "parameters": [] + } + ], + "gui:fuel_weight:Tare": [ + { + "command": "Tare", + "parameters": [ + 8, + 2, + "fuel_weight:sensor" + ] + } + ], + "gui:holddown:sensor": [ + { + "command": "holddown:SetState", + "parameters": [ + 0 + ], + "triggerType": "==", + "triggerValue": 0 + }, + { + "command": "holddown:SetState", + "parameters": [ + 1 + ], + "triggerType": "==", + "triggerValue": 1 + } + ], + "gui:ox_pi_controller:GetI_NEG": [ + { + "command": "ox_pi_controller:GetI_NEG", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetI_POS": [ + { + "command": "ox_pi_controller:GetI_POS", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetOperatingPoint": [ + { + "command": "ox_pi_controller:GetOperatingPoint", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetP_NEG": [ + { + "command": "ox_pi_controller:GetP_NEG", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetP_POS": [ + { + "command": "ox_pi_controller:GetP_POS", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetSensorChannelID": [ + { + "command": "ox_pi_controller:GetSensorChannelID", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetSensorOffset": [ + { + "command": "ox_pi_controller:GetSensorOffset", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetSensorSlope": [ + { + "command": "ox_pi_controller:GetSensorSlope", + "parameters": [] + } + ], + "gui:ox_pi_controller:GetTarget": [ + { + "command": "ox_pi_controller:GetTarget", + "parameters": [] + } + ], + "gui:ox_weight:Tare": [ + { + "command": "Tare", + "parameters": [ + 8, + 3, + "ox_weight:sensor" + ] + } + ], + "gui:pressure_control:GetHysteresis": [ + { + "command": "pressure_control:GetHysteresis", + "parameters": [] + } + ], + "gui:pressure_control:SetEnabled": [ + { + "command": "pressure_control:SetEnabled", + "parameters": [ + "gui:pressure_control:SetEnabled" + ] + } + ], + "gui:pressure_control:SetHysteresis": [ + { + "command": "pressure_control:SetHysteresis", + "parameters": [ + "gui:pressure_control:SetHysteresis" + ] + } + ], + "gui:pressure_control:SetTarget": [ + { + "command": "pressure_control:SetTarget", + "parameters": [ + "gui:pressure_control:SetTarget" + ] + } + ], + "gui:rocket:Abort": [ + { + "command": "rocket:Abort", + "parameters": [] + } + ], + "gui:rocket:AutoCheck": [ + { + "command": "rocket:AutoCheck", + "parameters": [] + } + ], + "gui:rocket:EndOfFlight": [ + { + "command": "rocket:EndOfFlight", + "parameters": [] + } + ], + "gui:rocket:InternalControl": [ + { + "command": "rocket:ActivateInternalControl", + "parameters": [] + } + ], + "gui:rocket:ReleaseHolddown": [ + { + "command": "rocket:SetRocketState", + "parameters": [ + 4 + ] + }, + { + "command": "holddown:SetTargetPosition", + "parameters": [ + 65535 + ] + } + ], + "gui:rocket:RequestResetSettings": [ + { + "command": "rocket:RequestResetSettings", + "parameters": [] + } + ], + "gui:rocket:ResetStateMachine": [ + { + "command": "rocket:SetRocketState", + "parameters": [ + 0 + ] + } + ], + "gui:rocket:SetHolddownTimeout": [ + { + "command": "rocket:SetHolddownTimeout", + "parameters": [ + "gui:rocket:SetHolddownTimeout" + ] + } + ], + "gui:rocket:SetMinimumChamberPressure": [ + { + "command": "rocket:SetMinimumChamberPressure", + "parameters": [ + "gui:rocket:SetMinimumChamberPressure" + ] + } + ], + "gui:rocket:SetMinimumFuelPressure": [ + { + "command": "rocket:SetMinimumFuelPressure", + "parameters": [ + "gui:rocket:SetMinimumFuelPressure" + ] + } + ], + "gui:rocket:SetMinimumOxPressure": [ + { + "command": "rocket:SetMinimumOxPressure", + "parameters": [ + "gui:rocket:SetMinimumOxPressure" + ] + } + ], + "gui:rocket_weight:Tare": [ + { + "command": "Tare", + "parameters": [ + 8, + 0, + "rocket_weight:sensor" + ] + } + ], + "gui:thrust:Tare": [ + { + "command": "Tare", + "parameters": [ + 8, + 0, + "thrust:sensor" + ] + } + ], + "gui:venturi_weight:Tare": [ + { + "command": "Tare", + "parameters": [ + 9, + 1, + "venturi_weight:sensor" + ] + } + ], + "fuel_rocket:GetRocketState": [ + { + "state": "fuel_rocket:GetRocketState", + "parameters": [] + } + ], + "ox_rocket:GetRocketState": [ + { + "state": "ox_rocket:GetRocketState", + "parameters": [] + } + ], + "rocket:sensor": [ + { + "state": "rocket:PadIdle", + "triggerType": "==", + "triggerValue": 0, + "value": 1 + }, + { + "state": "rocket:PadIdle", + "triggerType": "!=", + "triggerValue": 0, + "value": 0 + }, + { + "state": "rocket:AutoCheck", + "triggerType": "==", + "triggerValue": 1, + "value": 1 + }, + { + "state": "rocket:AutoCheck", + "triggerType": "!=", + "triggerValue": 1, + "value": 0 + }, + { + "state": "rocket:IgnitionSequence", + "triggerType": "==", + "triggerValue": 2, + "value": 1 + }, + { + "state": "rocket:IgnitionSequence", + "triggerType": "!=", + "triggerValue": 2, + "value": 0 + }, + { + "state": "rocket:HoldDown", + "triggerType": "==", + "triggerValue": 3, + "value": 1 + }, + { + "state": "rocket:HoldDown", + "triggerType": "!=", + "triggerValue": 3, + "value": 0 + }, + { + "state": "rocket:PoweredAscent", + "triggerType": "==", + "triggerValue": 4, + "value": 1 + }, + { + "state": "rocket:PoweredAscent", + "triggerType": "!=", + "triggerValue": 4, + "value": 0 + }, + { + "state": "rocket:UnpoweredAscent", + "triggerType": "==", + "triggerValue": 5, + "value": 1 + }, + { + "state": "rocket:UnpoweredAscent", + "triggerType": "!=", + "triggerValue": 5, + "value": 0 + }, + { + "state": "rocket:Depress", + "triggerType": "==", + "triggerValue": 6, + "value": 1 + }, + { + "state": "rocket:Depress", + "triggerType": "!=", + "triggerValue": 6, + "value": 0 + }, + { + "state": "rocket:AbortFlowChart", + "triggerType": "==", + "triggerValue": 7, + "value": 1 + }, + { + "state": "rocket:AbortFlowChart", + "triggerType": "!=", + "triggerValue": 7, + "value": 0 + } + ] + }, + "GUIMapping": [], + "GUIMappingAdvanced": {} +} diff --git a/sample_config/sample_sequence.json b/sample_config/sample_sequence.json new file mode 100644 index 00000000..dde36be3 --- /dev/null +++ b/sample_config/sample_sequence.json @@ -0,0 +1,51 @@ +{ + "globals": { + "endTime": 10, + "interpolation": { + "doStuff": "none" + }, + "interval": 0.01, + "startTime": -3 + }, + "data": [ + { + "timestamp": "START", + "name": "start", + "desc": "start", + "actions": [ + { + "timestamp": 0.0, + "doStuff": [ + 2 + ] + } + ] + }, + { + "timestamp": 4.0, + "name": "start", + "desc": "start", + "actions": [ + { + "timestamp": 0.0, + "doStuff": [ + 10 + ] + } + ] + }, + { + "timestamp": "END", + "name": "end", + "desc": "end", + "actions": [ + { + "timestamp": 0.0, + "doStuff": [ + 15 + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/scripts/ECUIEmulator.py b/scripts/ECUIEmulator.py new file mode 100644 index 00000000..19e8c0fc --- /dev/null +++ b/scripts/ECUIEmulator.py @@ -0,0 +1,91 @@ +import socket +import threading +import json + + +HOST = '127.0.0.1' # localhost +PORT = 8080 # Port to listen on + +# Store connected clients +clients = [] +MAX_MSG_LENGTH = 65536-1 + +# Function to handle client connections +def handle_client(conn, addr): + print(f"Connected by {addr}") + clients.append(conn) + try: + while True: + data = conn.recv(1024) + if not data: + break + print(f"Received from client: {data}") + except Exception as e: + print(f"Connection error: {e}") + finally: + conn.close() + clients.remove(conn) + print(f"Connection with {addr} closed.") + +def start_server(): + server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + server.bind((HOST, PORT)) + server.listen(5) + print(f"Server listening on {HOST}:{PORT}") + + while True: + conn, addr = server.accept() + threading.Thread(target=handle_client, args=(conn, addr),daemon=True).start() + +# Function to send JSON messages to all clients, with a custom header +def send_message_to_all_clients(type,message): + msg = { + "type": type, + "content": [message,"",""] + } + + str_msg = json.dumps(msg) + '\n' + str_msg_len = len(str_msg) + + if str_msg_len <= MAX_MSG_LENGTH: + lsb = str_msg_len & 0x00FF + msb = str_msg_len >> 8 + + header = bytes([msb, lsb]) + msg_buffer = header + str_msg.encode('ascii') + + for client in clients: + try: + client.sendall(msg_buffer) + except Exception as e: + print(f"Error sending message to a client: {e}") + +if __name__ == "__main__": + print("Starting JSON socket server.") + threading.Thread(target=start_server, daemon=True).start() + while True: + try: + print("Enter your message type(one of sequence-start, send-postseq-comment, abort, auto-abort-change, states-load, states-get, states-set, states-start, states-stop, gui-mapping-load, commands-load, commands-set):") + type = input() + print("Enter your JSON message (send with `END` in a new line):") + lines = [] + while True: + line = input() + if line.strip() == "END": + break + lines.append(line) + + # Join the lines and parse as JSON + json_data = json.loads("\n".join(lines)) + + # Send the JSON data to all connected clients + send_message_to_all_clients(type,json_data) + print("Message sent.") + except json.JSONDecodeError: + print("Invalid JSON. Please try again.") + except KeyboardInterrupt: + print("Server shutting down.") + break + except Exception as e: + print(f"Unexpected error: {e}") diff --git a/src/SequenceManager.cpp b/src/SequenceManager.cpp index 3acefc01..ab0d9c59 100644 --- a/src/SequenceManager.cpp +++ b/src/SequenceManager.cpp @@ -138,6 +138,9 @@ void SequenceManager::SetupLogging() strftime(dateTime_string, 100, "%Y_%m_%d__%H_%M_%S", curr_tm); currentDirPath = "logs/" + std::string(dateTime_string); + std::experimental::filesystem::create_directory("logs"); + std::experimental::filesystem::create_directory(currentDirPath); + this->lastDir = currentDirPath; logFileName = std::string(dateTime_string) + ".csv"; std::experimental::filesystem::create_directory(currentDirPath); @@ -199,10 +202,14 @@ bool SequenceManager::LoadSequence(nlohmann::json jsonSeq) { if (sensorsIt.value().type() == nlohmann::json::value_t::array && sensorsIt.value().size() == 2) { - sensorsNominalRangeMap[sensorsIt.key()][timestampMicros][0] = sensorsIt.value()[0]; - sensorsNominalRangeMap[sensorsIt.key()][timestampMicros][1] = sensorsIt.value()[1]; - sensorsNominalRangeTimeMap[timestampMicros][sensorsIt.key()][0] = sensorsIt.value()[0]; - sensorsNominalRangeTimeMap[timestampMicros][sensorsIt.key()][1] = sensorsIt.value()[1]; + if(jsonSeq["globals"]["ranges"].contains(sensorsIt.key())) { + sensorsNominalRangeMap[sensorsIt.key()][timestampMicros][0] = sensorsIt.value()[0]; + sensorsNominalRangeMap[sensorsIt.key()][timestampMicros][1] = sensorsIt.value()[1]; + sensorsNominalRangeTimeMap[timestampMicros][sensorsIt.key()][0] = sensorsIt.value()[0]; + sensorsNominalRangeTimeMap[timestampMicros][sensorsIt.key()][1] = sensorsIt.value()[1]; + } else{ + Debug::warning("Sensor Ranges set for %s but not defined in globals", sensorsIt.key().c_str()); + } } else { @@ -248,19 +255,11 @@ void SequenceManager::StartSequence(nlohmann::json jsonSeq, nlohmann::json jsonA // } // msg += "Status;"; msg += "SequenceTime;"; - for (auto rangeName : jsonSeq["globals"]["ranges"]) + for (const auto& rangeName: sensorsNominalRangeMap) { - Debug::info("Sensor nominal range found: %s", ((std::string) rangeName).c_str()); - if (rangeName.type() == nlohmann::json::value_t::string) - { - msg += (std::string) rangeName + "Min;"; - msg += (std::string) rangeName + "Max;"; - } - else - { - Debug::error("range name in sequence globals not a string"); - } - + Debug::info("Sensor nominal range found: %s", ((std::string) rangeName.first).c_str()); + msg += rangeName.first + "Min;"; + msg += rangeName.first + "Max;"; } for (auto &item : deviceMap) { @@ -402,7 +401,7 @@ void SequenceManager::sequenceLoop(int64_t interval_us) if(sequenceTime_us >= nextTimePrint_us) { Debug::info("Sequence Time: %dus", sequenceTime_us); - nextTimePrint_us += 500000; + nextTimePrint_us += 300000; } static int32_t nextTimerSync_us = startTime_us; @@ -416,7 +415,8 @@ void SequenceManager::sequenceLoop(int64_t interval_us) syncMtx.lock(); //log nominal ranges - for (const auto &sensor : sensorsNominalRangeMap) + + for (const auto &sensor : sensorsNominalRangeMap) { msg += std::to_string(sensor.second.begin()->second[0]) + ";"; msg += std::to_string(sensor.second.begin()->second[1]) + ";"; diff --git a/src/StateController.cpp b/src/StateController.cpp index e80fdef2..4fb70c02 100644 --- a/src/StateController.cpp +++ b/src/StateController.cpp @@ -18,13 +18,14 @@ void StateController::Init(std::function onSt if (!initialized) { this->onStateChangeCallback = std::move(onStateChangeCallback); +#ifndef NO_INFLUX logger = new InfluxDbLogger(); logger->Init(config["/INFLUXDB/database_ip"], config["/INFLUXDB/database_port"], config["/INFLUXDB/database_name"], config["/INFLUXDB/state_measurement"], MICROSECONDS, config["/INFLUXDB/buffer_size"]); - +#endif initialized = true; } } @@ -121,7 +122,9 @@ void StateController::SetState(std::string stateName, double value, uint64_t tim std::get<1>(*state) = timestamp; std::get<2>(*state) = true; //Debug::print("%zd: %s, %zd", count, stateName.c_str(), count); +#ifndef NO_INFLUX logger->log(stateName, value, timestamp); +#endif if(timestamp != 0) { count++; } diff --git a/src/can/Node.cpp b/src/can/Node.cpp index 15bf9cc2..489268d2 100644 --- a/src/can/Node.cpp +++ b/src/can/Node.cpp @@ -89,6 +89,7 @@ Node::Node(uint8_t nodeID, std::string nodeChannelName, NodeInfoMsg_t& nodeInfo, if (logger == nullptr) { Debug::info("%d, %s, %d, %s, %s, %d", enableFastLogging, influxIP.c_str(), influxPort, databaseName.c_str(), measurementName.c_str(), influxBufferSize); +#ifndef NO_INFLUX if (enableFastLogging) { Debug::print("Fast logging enabled"); @@ -101,8 +102,12 @@ Node::Node(uint8_t nodeID, std::string nodeChannelName, NodeInfoMsg_t& nodeInfo, } else { +#endif Debug::print("Fast logging disabled"); +#ifndef NO_INFLUX } +#endif + } commandMap = { @@ -376,12 +381,14 @@ void Node::ProcessSensorDataAndWriteToRingBuffer(Can_MessageData_t *canMsg, uint latestSensorBuffer[channelID] = {currValue, timestamp}; +#ifndef NO_INFLUX if (enableFastLogging) { std::lock_guard lock(loggerMtx); logger->log(ch->GetSensorName(), currValue, timestamp); //logger->flush(); } +#endif //buffer.push_back(sensor); //TODO: uncomment if implemented } diff --git a/src/utility/Debug.cpp b/src/utility/Debug.cpp index 7f3be49b..c2afd294 100644 --- a/src/utility/Debug.cpp +++ b/src/utility/Debug.cpp @@ -27,13 +27,15 @@ void Debug::Init(Config &config) if (!initialized) { printWarnings = config["/DEBUG/printWarnings"]; printInfos = config["/DEBUG/printInfos"]; +#ifndef NO_INFLUX logger.reset(new InfluxDbLogger()); logger->Init(config["/INFLUXDB/database_ip"], config["/INFLUXDB/database_port"], config["/INFLUXDB/database_name"], config["/INFLUXDB/debug_measurement"], MILLISECONDS, config["/INFLUXDB/buffer_size"]); - initialized = true; +#endif + initialized = true; } } @@ -172,7 +174,10 @@ void Debug::close() info("in Debug close: log output file is not open yet, try Debug::changeOutputFile"); } if (initialized) { +#ifndef NO_INFLUX + logger->flush(); +#endif } } @@ -190,7 +195,9 @@ void Debug::flush() } if (initialized) { +#ifndef NO_INFLUX logger->flush(); +#endif } }