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