From 873eed9e1ad6962f82267c2117ca0fd6c8e1c1c3 Mon Sep 17 00:00:00 2001 From: jkl <sagitta1618@gmail.com> Date: Tue, 17 Oct 2023 21:55:08 +0200 Subject: [PATCH] WIP mqtt index.html with inversion --- dev/start_mqtt_html.py | 18 ++++++++ index-mqtt.html | 94 ++++++++++++++++++++++++++++++++------- ohmpi/config.py | 39 +++++++++------- ohmpi/ohmpi.py | 9 +++- requirements-optional.txt | 16 +++++++ 5 files changed, 144 insertions(+), 32 deletions(-) create mode 100644 dev/start_mqtt_html.py create mode 100644 requirements-optional.txt diff --git a/dev/start_mqtt_html.py b/dev/start_mqtt_html.py new file mode 100644 index 00000000..67b66851 --- /dev/null +++ b/dev/start_mqtt_html.py @@ -0,0 +1,18 @@ + +# we need to start the OhmPi instance so that it listens +# to message from the MQTT broker + +import subprocess +# launch webserver + +from ohmpi.utils import change_config +change_config('../configs/config_mb_2023.py', verbose=False) + +from ohmpi.ohmpi import OhmPi +from ohmpi.config import OHMPI_CONFIG +ohmpi = OhmPi(settings=OHMPI_CONFIG['settings']) +if ohmpi.controller is not None: + ohmpi.controller.loop_forever() + +# restore default config +change_config('../configs/config_default.py', verbose=False) diff --git a/index-mqtt.html b/index-mqtt.html index e8a8aa04..e90f129f 100755 --- a/index-mqtt.html +++ b/index-mqtt.html @@ -61,8 +61,10 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl <div id="rs"></div> <!-- Inversion plot --> - <select id="surveySelectInv" class='custom-select'></select> - <button id="invertBtn" type="button" class="btn btn-info">Invert</button> + <select id="surveySelectInv" class='custom-select'> + <option>measurement_20220206T194552.csv</option> + </select> + <button id="invertBtn" type="button" class="btn btn-info">Run inversion</button> <input id="cminInv" type="number" value="0"/> <input id="cmaxInv" type="number" value="150"/> <button id="capplyBtnInv" type="button" class="btn btn-info">Apply</button> @@ -154,6 +156,15 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let squads = [] // selected quadrupoles for time-serie figure let commands = {} // store commands and their id let callbacks = {} // store callback (might not be needed) + let invertData = [{ + rho: [[10, 10.625, 12.5, 15.625, 20], + [5.625, 6.25, 8.125, 11.25, 15.625], + [2.5, 3.125, 5., 8.125, 12.5], + [0.625, 1.25, 3.125, 6.25, 10.625], + [0, 0.625, 2.5, 5.625, 10]], + x: [-9, -6, -5 , -3, -1], + y: [0, 1, 4, 5, 7], + }] // store inverted data // function with MQTT let topic = 'ohmpi_0001' // we could change this through a drop-down to connect to a different ohmpi @@ -202,7 +213,7 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let ddic = JSON.parse(payload.split('INFO:')[1]) // check cmd_id is any - processData(ddic) + processMessage(ddic) // usually these don't have a cmd_id so we are not sure when @@ -481,9 +492,6 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let rsClearBtn = document.getElementById('rsClearBtn') rsClearBtn.addEventListener('click', rsClearBtnFunc) - // Run inversion - - // getData function getData() { sendCommand(JSON.stringify({ @@ -494,6 +502,19 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl ) } + // processMessage + function processMessage(ddic) { + if ('status' in ddic) { + // acquisition related + processData(ddic) + } else { + // inversion related + console.log('--------', ddic) + let invertData = ddic[0] + showInvFunc() + } + } + // processData function processData(ddic) { // update status @@ -600,6 +621,58 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl surveySelectFunc({'target': surveySelect}) }) + // plot inverted data + function showInvFunc() { + let cmin = document.getElementById('cminInv').value + let cmax = document.getElementById('cmaxInv').value + + var data = [{ + z: invertData[0]['rho'], + x: invertData[0]['x'], + y: invertData[0]['z'], + type: 'contour', + colorscale: 'Jet', + autocontour: true, // set to false if cmin is given + contours: { + start: cmin, + end: cmax, + size: 10 + }, + }] + + var layout = { + title: 'Inverted section', + yaxis: { + title: 'Z [m]', + }, + xaxis: { + title: 'X [m]' + } + } + Plotly.newPlot('inv', data, layout) + } + + //invert data + function invertBtnFunc() { + let survey_name = document.getElementById('surveySelectInv').value + sendCommand(JSON.stringify({ + 'cmd': 'run_inversion', + 'kwargs': { + 'survey_names': [survey_name] + } + }), function(x) { + console.log('inversion results', x) + }) + } + let invertBtn = document.getElementById('invertBtn') + invertBtn.addEventListener('click', invertBtnFunc) + + // apply new colorscale for inversion + let capplyBtnInv = document.getElementById('capplyBtnInv') + capplyBtnInv.addEventListener('click', function() { + showInvFunc() + }) + // checkbox interaction for data download function dataRetrievalCheckFunc(x) { if (x['target'].checked == true) { @@ -640,15 +713,6 @@ mosquitto_sub -h raspberrypi.local -t ohmpi_0001/ctrl let restartBtn = document.getElementById('restartBtn') restartBtn.addEventListener('click', restartBtnFunc) - // invert data - // function invertBtnFunc() { - // sendCommand('{"cmd": "invert"}', function(x) { - // console.log('inversion results', x) - // }) - // } - // let invertBtn = document.getElementById('invertBtn') - // invertBtn.addEventListener('click', invertBtnFunc) - // download data function downloadBtnFunc() { sendCommand('{"cmd": "download"}', function(x) { diff --git a/ohmpi/config.py b/ohmpi/config.py index 0763f48c..8bd970d8 100644 --- a/ohmpi/config.py +++ b/ohmpi/config.py @@ -1,7 +1,7 @@ import logging from ohmpi.utils import get_platform -from paho.mqtt.client import MQTTv31 +from paho.mqtt.client import MQTTv31 # noqa _, on_pi = get_platform() # DEFINE THE ID OF YOUR OhmPi @@ -18,25 +18,34 @@ OHMPI_CONFIG = { } HARDWARE_CONFIG = { - 'ctl': {'model' : 'dummy_ctl' - }, - 'tx' : {'model' : 'dummy_tx', - 'current_max': 4800 / 50 / 2, # Maximum current mA - 'r_shunt': 2, # Shunt resistance in Ohms - 'low_battery': 12. # Volts + 'ctl': {'model': 'raspberry_pi'}, + 'pwr': {'model': 'pwr_batt', 'voltage': 12., 'interface_name': 'none'}, + 'tx': {'model': 'mb_2023_0_X', + 'voltage_max': 12., # Maximum voltage supported by the TX board [V] + 'adc_voltage_max': 4800., # Maximum voltage read by the current ADC on the TX board [mA] + 'r_shunt': 2., # Shunt resistance in Ohms + 'interface_name': 'i2c', }, - 'rx' : {'model': 'dummy_rx', + 'rx': {'model': 'mb_2023_0_X', + 'coef_p2': 2.50, # slope for conversion for ADS, measurement in V/V + 'sampling_rate': 50., # number of samples per second + 'interface_name': 'i2c', }, - 'mux': {'model' : 'dummy_mux', - 'max_elec': 64, - 'voltage_max' : 100, - 'current_max' : 3 - } + 'mux': # default properties given in config are system properties that will be + # overwritten by properties defined in each the board dict below. + # if defined in board specs, values out of specs will be bounded to remain in specs + # omitted properties in config will be set to board specs default values if they exist + {'boards': {}, + 'default': {'interface_name': 'i2c', + 'voltage_max': 100., + 'current_max': 3.} + } } + # SET THE LOGGING LEVELS, MQTT BROKERS AND MQTT OPTIONS ACCORDING TO YOUR NEEDS # Execution logging configuration EXEC_LOGGING_CONFIG = { - 'logging_level': logging.INFO, + 'logging_level': logging.DEBUG, # TODO: set logging level back to INFO 'log_file_logging_level': logging.DEBUG, 'logging_to_console': True, 'file_name': f'exec{logging_suffix}.log', @@ -60,8 +69,8 @@ DATA_LOGGING_CONFIG = { # State of Health logging configuration (For a future release) SOH_LOGGING_CONFIG = { 'logging_level': logging.INFO, - 'log_file_logging_level': logging.DEBUG, 'logging_to_console': True, + 'log_file_logging_level': logging.DEBUG, 'file_name': f'soh{logging_suffix}.log', 'max_bytes': 16777216, 'backup_count': 1024, diff --git a/ohmpi/ohmpi.py b/ohmpi/ohmpi.py index ccbb5bc8..efecdb58 100644 --- a/ohmpi/ohmpi.py +++ b/ohmpi/ohmpi.py @@ -940,7 +940,7 @@ class OhmPi(object): """ # check if we have any files to be inverted if len(survey_names) == 0: - self.exec_logger('No file to invert') + self.exec_logger.error('No file to invert') return [] # check if user didn't provide a single string instead of a list @@ -1013,13 +1013,18 @@ class OhmPi(object): grid_x, grid_z = np.meshgrid(x, z) grid_z = griddata(df[['X', 'Z']].values, df['Resistivity(ohm.m)'].values, (grid_x, grid_z), method='linear') + + # set nan to -1 + inan = np.isnan(grid_z) + grid_z[inan] = -1 + xzv.append({ 'x': x.tolist(), 'z': z.tolist(), 'rho': grid_z.tolist(), }) - self.data_logger.info(xzv) + self.data_logger.info(json.dumps(xzv)) # limited to one survey return xzv # Properties diff --git a/requirements-optional.txt b/requirements-optional.txt new file mode 100644 index 00000000..952b0be7 --- /dev/null +++ b/requirements-optional.txt @@ -0,0 +1,16 @@ +RPi.GPIO +adafruit-blinka +adafruit-circuitpython-ads1x15 +adafruit-circuitpython-tca9548a +adafruit-circuitpython-mcp230xx +adafruit_extended_bus +minimalmodbus +gpiozero +numpy +paho-mqtt +termcolor +pandas +matplotlib +scipy +requests +psutil \ No newline at end of file -- GitLab