diff --git a/Pipfile b/Pipfile
new file mode 100644
index 0000000000000000000000000000000000000000..4c69a3bc4a2383ea892207e3c90e76e7614092f4
--- /dev/null
+++ b/Pipfile
@@ -0,0 +1,23 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+
+[packages]
+numpy = "*"
+# cython = "*"
+# pandas = "*"
+paho-mqtt = "*"
+pytz = "*"
+six = "*"
+gpiozero = "*"
+adafruit-blinka = "*"
+adafruit-circuitpython-ads1x15 = "*"
+adafruit-circuitpython-tca9548a = "*"
+adafruit-circuitpython-mcp230xx = "*"
+termcolor ="*"
+
+[requires]
+python_version = "3.9"
diff --git a/Proposition MQTT interface.pdf b/Proposition MQTT interface.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..96a92bca0e11dc1fe46c40cf61f8818744b6ba1f
Binary files /dev/null and b/Proposition MQTT interface.pdf differ
diff --git a/Proposition interface.pdf b/Proposition interface.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..30b8a7cb770b79647dc64f4d7f88edef50f88c09
Binary files /dev/null and b/Proposition interface.pdf differ
diff --git a/deploy_virtual_env.sh b/deploy_virtual_env.sh
new file mode 100644
index 0000000000000000000000000000000000000000..6590536381e3428c97f684fe1cbeade84987a916
--- /dev/null
+++ b/deploy_virtual_env.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+sudo apt-get install -y libatlas-base-dev
+python -m venv ohmpy
+source ohmpy/bin/activate || exit 1  # NOTE: Added || exit to avoid installing requirements in system python
+export CFLAGS=-fcommon
+pip install -r requirements.txt
+
diff --git a/doc/source/Ohmpi_V2_00/V2_00_usage.rst b/doc/source/Ohmpi_V2_00/V2_00_usage.rst
new file mode 100644
index 0000000000000000000000000000000000000000..a85ed70e2fa3ce7cbc83c4bbcb3a13659fc34f75
--- /dev/null
+++ b/doc/source/Ohmpi_V2_00/V2_00_usage.rst
@@ -0,0 +1,103 @@
+
+.. warning::
+	**Ohmpi is a participative project open to all, it requires skills in electronics and to respect the safety rules. Ohmpi must be assembled in a professional context and by people competent in electronics. The Ohmpi team cannot be held responsible for any material or human damage which would be associated with the use or the assembly of OHMPI. The Ohmpi team cannot be held responsible if the equipment does not work after assembly.**
+
+
+
+
+
+
+**Usage** Interfaces and applications
+****************************************************
+
+Different interfaces can be used to communicated with the OhmPi.
+
+*** Web interface ***
+
+The raspberrypi of the OhmPi is used as a Wifi Access Point (AP) and run
+a small webserver to serve the 'index.html' interface. Using a laptop or
+a mobile phone connected to the wifi of the Raspberry Pi, one can see this
+interface, upload sequence, change parameters, run sequence and download data.
+
+To configure the Raspberry Pi to act as an access point and run
+the webserver automatically on start, see instructions in 'runOnStart.sh'.
+
+Once configure, the webserver should start by itself on start and once
+connected to the Pi, the user can go to `10.3.141.1:8080<http://10.3.141.1:8080>`
+ to access the interface.
+ 
+ 
+TODO add screenshot of interface
+ 
+
+
+*** Python interface***
+
+By importing the `OhmPi` class from the ohmpi.py, one can controle the OhmPi using interactive IPython.
+Typically, it involves using the Thonny on the Raspberry Pi or the Terminal. Once can also connect using 
+ssh and run the Python interface (see PuTTY on Windows or ssh command on macOS/Linux).
+
+To access the Python API, make sure the file ohmpi.py is in the same
+directory as where you run the commands/script. The file ohmpi.py can
+be found on the OhmPi gitlab repository. We recommend downloading the 
+entire repository as ohmpi.py import other .py files and default configuration
+files (.json and .py).
+
+
+.. codeblock:: python
+   :caption: Example of using the Python API to control OhmPi
+
+
+   from ohmpi import OhmPi
+   k = OhmPi(idps=True)  # if V3.0 make sure to set idps to True
+   # the DPS5005 is used in V3.0 to inject higher voltage
+   
+   # default parameters are stored in the pardict argument
+   # they can be manually changed
+   k.pardict['injection_duration'] = 0.5  # injection time in seconds
+   k.pardict['nb_stack'] = 1  # one stack is two half-cycles
+   k.pardict['nbr_meas'] = 1  # number of time the sequence is repeated
+   
+   # without multiplexer, one can simple measure using
+   out = k.run_measurement()
+   # out contains information about the measurement and can be save as
+   k.append_and_save('out.csv', out)
+   
+   # custom or adaptative argument (see help of run_measurement())
+   k.run_measurement(nb_stack=4,  # do 4 stacks (8 half-cycles)
+                     injection_duration=2,  # inject for 2 seconds
+                     autogain=True,  # adapt gain of ADS to get good resolution
+                     strategy='vmin',  # inject min voltage for Vab (v3.0)
+                     tx_volt=5)  # vab for finding vmin or vab injectected
+                     # if 'strategy' is 'constant'
+   
+   # if a multiplexer is connected, we can also manually switch it
+   k.reset_mux()  # check that all mux are closed (do this FIRST)
+   k.switch_mux_on([1, 4, 2, 3])
+   k.run_measurement()
+   k.switch_mux_off([1, 4, 2, 3])  # don't forget this! risk of short-circuit
+   
+   # import a sequence
+   k.read_quad('sequence.txt')  # four columns, no header, space as separator
+   print(k.sequence)  # where the sequence is stored
+   
+   # rs check
+   k.rs_check()  # run an RS check (check contact resistances) for all
+   # electrodes of the given sequence
+   
+   # run a sequence
+   k.measure()  # measure accept same arguments as run_measurement()
+   # NOTE: this is an asynchronous command that runs in a separate thread
+   # after executing the command, the prompt will return immediately
+   # the asynchronous thread can be stopped during execution using
+   k.stop()
+   # otherwise, it will exit by itself at the end of the sequence
+   # if multiple measurement are to be taken, the sequence will be repeated
+   
+
+
+   
+***MQTT interface***
+
+Interface to communicate with the Pi designed for the Internet of Things (IoT).
+   
diff --git a/http_interface.py b/http_interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..992118261ed9f05e07523b30fcd67bf17b2ac579
--- /dev/null
+++ b/http_interface.py
@@ -0,0 +1,168 @@
+from http.server import SimpleHTTPRequestHandler, HTTPServer
+import os
+import json
+import uuid
+from config import CONTROL_CONFIG
+from termcolor import colored
+import threading
+import pandas as pd
+import shutil
+import zmq # to write on TCP
+
+hostName = "0.0.0.0"  # for AP mode (not AP-STA)
+serverPort = 8080
+
+# https://gist.github.com/MichaelCurrie/19394abc19abd0de4473b595c0e37a3a
+
+tcp_port = CONTROL_CONFIG['tcp_port']
+context = zmq.Context()
+socket = context.socket(zmq.REQ)
+socket.connect(f'tcp://localhost:{CONTROL_CONFIG["tcp_port"]}')
+print(colored(f'Sending commands and listening on tcp port {tcp_port}.'))
+
+
+class MyServer(SimpleHTTPRequestHandler):
+    # because we use SimpleHTTPRequestHandler, we do not need to implement
+    # the do_GET() method (if we use the BaseHTTPRequestHandler, we would need to)
+
+    # def do_GET(self):
+    #     # normal get for wepages (not so secure!)
+    #     print(self.command)
+    #     print(self.headers)
+    #     print(self.request)
+    #     self.send_response(200)
+    #     self.send_header("Content-type", "text/html")
+    #     self.end_headers()
+    #     with open(os.path.join('.', self.path[1:]), 'r') as f:
+    #         self.wfile.write(bytes(f.read(), "utf-8"))
+
+    def do_POST(self):
+        cmd_id = uuid.uuid4().hex
+        global socket
+
+        # global ohmpiThread, status, run
+        dic = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
+        rdic = {} # response dictionnary
+        if dic['cmd'] == 'start':
+            #ohmpi.measure()
+            socket.send_string(json.dumps({
+                'cmd_id': cmd_id,
+                'cmd': 'start'
+            }))
+        elif dic['cmd'] == 'stop':
+            # ohmpi.stop()
+            socket.send_string(json.dumps({
+                'cmd_id': cmd_id,
+                'cmd': 'stop'
+            }))
+        elif dic['cmd'] == 'getData':
+            # get all .csv file in data folder
+            fnames = [fname for fname in os.listdir('data/') if fname[-4:] == '.csv']
+            ddic = {}
+            for fname in fnames:
+                if (fname.replace('.csv', '') not in dic['surveyNames']
+                        and fname != 'readme.txt'
+                        and '_rs' not in fname):
+                    df = pd.read_csv('data/' + fname)
+                    ddic[fname.replace('.csv', '')] = {
+                        'a': df['A'].tolist(),
+                        'b': df['B'].tolist(),
+                        'm': df['M'].tolist(),
+                        'n': df['N'].tolist(),
+                        'rho': df['R [ohm]'].tolist(),
+                    }
+            rdic['data'] = ddic
+        elif dic['cmd'] == 'removeData':
+            shutil.rmtree('data')
+            os.mkdir('data')
+        elif dic['cmd'] == 'update_settings':
+            # ohmpi.stop()
+            socket.send_string(json.dumps({
+                'cmd_id': cmd_id,
+                'cmd': 'update_settings',
+                'args': dic['config']
+            }))
+            cdic = dic['config']
+            
+            """
+            ohmpi.pardict['nb_electrodes'] = int(cdic['nbElectrodes'])
+            ohmpi.pardict['injection_duration'] = float(cdic['injectionDuration'])
+            ohmpi.pardict['nbr_meas'] = int(cdic['nbMeasurements'])
+            ohmpi.pardict['nb_stack'] = int(cdic['nbStack'])
+            ohmpi.pardict['sequence_delay'] = int(cdic['sequenceDelay'])
+            if cdic['sequence'] != '':
+                with open('sequence.txt', 'w') as f:
+                    f.write(cdic['sequence'])
+                ohmpi.read_quad('sequence.txt')
+                print('new sequence set.')
+            print('setConfig', ohmpi.pardict)
+            """
+        elif dic['cmd'] == 'invert':
+            pass
+        elif dic['cmd'] == 'getResults':
+            pass
+        elif dic['cmd'] == 'rsCheck':
+            # ohmpi.rs_check()
+            socket.send_string(json.dumps({
+                'cmd_id': cmd_id,
+                'cmd': 'rs_check'
+            }))
+            fnames = sorted([fname for fname in os.listdir('data/') if fname[-7:] == '_rs.csv'])
+            df = pd.read_csv('data/' + fnames[-1])
+            ddic = {
+                'AB': (df['A'].astype('str') + '-' + df['B'].astype(str)).tolist(),
+                'res': df['RS [kOhm]'].tolist()
+            }
+            rdic['data'] = ddic
+        elif dic['cmd'] == 'download':
+            shutil.make_archive('data', 'zip', 'data')
+        elif dic['cmd'] == 'shutdown':
+            print('shutting down...')
+            os.system('shutdown now -h')
+        elif dic['cmd'] == 'restart':
+            print('shutting down...')
+            os.system('reboot')
+        else:
+            # command not found
+            rdic['response'] = 'command not found'
+
+        # rdic['status'] = ohmpi.status
+        rdic['status'] = 'unknown'  # socket_out.
+        # wait for reply
+
+        message = socket.recv()
+        print('+++////', message)
+        rdic['data'] = message.decode('utf-8')
+        """
+        while False:
+            message = socket.recv()
+            print(f'Received command: {message}')
+            e = None
+            try:
+                decoded_message = json.loads(message.decode('utf-8'))
+                cmd = decoded_message.pop('cmd', None)
+                args = decoded_message.pop('args', None)
+                status = False
+                e = None
+                if cmd is not None and cmd_id is decoded_message.pop('cmd_id', None):
+                    print('reply=', decoded_message)
+            except Exception as e:
+                print(f'Unable to decode command {message}: {e}')
+            """
+        self.send_response(200)
+        self.send_header('Content-Type', 'text/json')
+        self.end_headers()
+        self.wfile.write(bytes(json.dumps(rdic), 'utf8'))
+
+
+if __name__ == "__main__":
+    webServer = HTTPServer((hostName, serverPort), MyServer)
+    print("Server started http://%s:%s" % (hostName, serverPort))
+
+    try:
+        webServer.serve_forever()
+    except KeyboardInterrupt:
+        pass
+
+    webServer.server_close()
+    print("Server stopped.")
diff --git a/mqtt_controller.py b/mqtt_controller.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd2e6a5c21636c82faa5294c961aa331d8137a65
--- /dev/null
+++ b/mqtt_controller.py
@@ -0,0 +1,45 @@
+import json
+
+import paho.mqtt.client as mqtt
+import paho.mqtt.publish as publish
+from config import MQTT_CONTROL_CONFIG, OHMPI_CONFIG
+import time
+import uuid
+
+client = mqtt.Client(f'ohmpi_{OHMPI_CONFIG["id"]}_controller', clean_session=False)  # create new instance
+print('connecting controller to broker')
+client.connect(MQTT_CONTROL_CONFIG['hostname'])
+client.loop_start()
+publisher_config = MQTT_CONTROL_CONFIG.copy()
+publisher_config['topic'] = MQTT_CONTROL_CONFIG['ctrl_topic']
+publisher_config.pop('ctrl_topic')
+settings = {
+            'injection_duration': 0.2,
+            'nbr_meas': 1,
+            'sequence_delay': 1,
+            'nb_stack': 1,
+            'export_path': 'data/measurement.csv'
+        }
+
+cmd_id = uuid.uuid4().hex
+payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'update_settings', 'args': settings})
+print(f'Update settings setup message: {payload} to {publisher_config["topic"]} with config {publisher_config}')
+publish.single(payload=payload, **publisher_config)
+
+sequence = [[1, 2, 3, 4]]
+cmd_id = uuid.uuid4().hex
+payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'set_sequence', 'args': sequence})
+print(f'Set sequence message: {payload} to {publisher_config["topic"]} with config {publisher_config}')
+publish.single(payload=payload, **publisher_config)
+cmd_id = uuid.uuid4().hex
+payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'rs_check'})
+print(f'Run rs_check: {payload} to {publisher_config["topic"]} with config {publisher_config}')
+publish.single(payload=payload, **publisher_config)
+
+for i in range(4):
+    cmd_id = uuid.uuid4().hex
+    payload = json.dumps({'cmd_id': cmd_id, 'cmd': 'start'})
+    print(f'Publishing message {i}: {payload} to {publisher_config["topic"]} with config {publisher_config}')
+    publish.single(payload=payload, **publisher_config)
+    time.sleep(1)
+client.loop_stop()
diff --git a/mqtt_interface.py b/mqtt_interface.py
new file mode 100644
index 0000000000000000000000000000000000000000..6968a29594eee7647f3b9d03c4c2960ed4ac57d5
--- /dev/null
+++ b/mqtt_interface.py
@@ -0,0 +1,51 @@
+import paho.mqtt.client as mqtt
+from config import MQTT_CONTROL_CONFIG, CONTROL_CONFIG, OHMPI_CONFIG
+import time
+from queue import Queue
+import zmq
+
+ctrl_queue = Queue()
+
+def on_message(client, userdata, message):
+    global socket
+
+    # Send the command
+    print(f'Sending command {message.payload.decode("utf-8")}')
+    socket.send(message.payload)
+
+    #  Get the reply
+    reply = socket.recv()
+    print(f'Received reply {message.payload.decode("utf-8")}: {reply}')
+
+mqtt_client = mqtt.Client(f'ohmpi_{OHMPI_CONFIG["id"]}_listener', clean_session=False)  # create new instance
+print('connecting command listener to broker')
+trials = 0
+trials_max = 10
+broker_connected = False
+while trials < trials_max:
+    try:
+        mqtt_client.username_pw_set(MQTT_CONTROL_CONFIG['auth'].get('username'),MQTT_CONTROL_CONFIG['auth']['password'])
+        mqtt_client.connect(MQTT_CONTROL_CONFIG['hostname'])
+        trials = trials_max
+        broker_connected = True
+    except:
+        print('trying again...')
+        time.sleep(2)
+        trials+=1
+if broker_connected:
+    print('Subscribing to topic', MQTT_CONTROL_CONFIG['ctrl_topic'])
+    mqtt_client.subscribe(MQTT_CONTROL_CONFIG['ctrl_topic'], MQTT_CONTROL_CONFIG['qos'])
+    mqtt_client.on_message = on_message
+    mqtt_client.loop_start()
+
+    context = zmq.Context()
+    #  Socket to talk to server
+    print("Connecting to ohmpi control server")
+    socket = context.socket(zmq.REQ)
+    socket.connect(f'tcp://localhost:{CONTROL_CONFIG["tcp_port"]}')
+
+    while True:
+       time.sleep(.1)
+else:
+    print("Unable to connect to broker")
+    exit(1)
diff --git a/ohmpi_settings.json b/ohmpi_settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..fe28a272124e643c4f6f8f8f61a864b5bfb99836
--- /dev/null
+++ b/ohmpi_settings.json
@@ -0,0 +1,8 @@
+{
+    "nb_electrodes": 64,
+    "injection_duration": 0.2,
+    "nbr_meas": 1,
+    "sequence_delay": 1,
+    "nb_stack": 1,
+    "export_path": "data/measurement.csv"
+}
diff --git a/requirements_not_on_pi.txt b/requirements_not_on_pi.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d26aec9769d214526d1194413304c3ae460be25e
--- /dev/null
+++ b/requirements_not_on_pi.txt
@@ -0,0 +1,5 @@
+numpy
+paho-mqtt
+termcolor
+pandas
+pyzmq
diff --git a/simple_ohmpi_flow.json b/simple_ohmpi_flow.json
new file mode 100644
index 0000000000000000000000000000000000000000..17df4bd741b1a7e62d377b50136b8b0146a3afdd
--- /dev/null
+++ b/simple_ohmpi_flow.json
@@ -0,0 +1 @@
+[{"id":"ea6628fd.4d57e8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"6ae7e77e.04c64","type":"mqtt-broker","name":"ohmpi_mqtt_broker","broker":"mg3d-dev.umons.ac.be","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"64a75353.37700c","type":"ui_group","name":"Messages","tab":"5d888f29.07334","order":1,"disp":true,"width":"16","collapse":true},{"id":"142ad6ae.d55e29","type":"ui_group","name":"Buttons","tab":"5d888f29.07334","order":3,"disp":true,"width":"6","collapse":false},{"id":"5d888f29.07334","type":"ui_tab","name":"Home","icon":"dashboard","disabled":false,"hidden":false},{"id":"ea73b76b.ee0738","type":"ui_base","theme":{"name":"theme-light","lightTheme":{"default":"#0094CE","baseColor":"#0094CE","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":false},"darkTheme":{"default":"#097479","baseColor":"#097479","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif","edited":false},"customTheme":{"name":"Untitled Theme 1","default":"#4B7930","baseColor":"#4B7930","baseFont":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"},"themeState":{"base-color":{"default":"#0094CE","value":"#0094CE","edited":false},"page-titlebar-backgroundColor":{"value":"#0094CE","edited":false},"page-backgroundColor":{"value":"#fafafa","edited":false},"page-sidebar-backgroundColor":{"value":"#ffffff","edited":false},"group-textColor":{"value":"#1bbfff","edited":false},"group-borderColor":{"value":"#ffffff","edited":false},"group-backgroundColor":{"value":"#ffffff","edited":false},"widget-textColor":{"value":"#111111","edited":false},"widget-backgroundColor":{"value":"#0094ce","edited":false},"widget-borderColor":{"value":"#ffffff","edited":false},"base-font":{"value":"-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif"}},"angularTheme":{"primary":"indigo","accents":"blue","warn":"red","background":"grey","palette":"light"}},"site":{"name":"Node-RED Dashboard","hideToolbar":"false","allowSwipe":"false","lockMenu":"false","allowTempTheme":"true","dateFormat":"DD/MM/YYYY","sizes":{"sx":48,"sy":48,"gx":6,"gy":6,"cx":6,"cy":6,"px":0,"py":0}}},{"id":"147e389f.fc5a6f","type":"mqtt in","z":"ea6628fd.4d57e8","name":"","topic":"ohmpi_0001/exec","qos":"2","datatype":"auto","broker":"6ae7e77e.04c64","inputs":0,"x":110,"y":40,"wires":[["ddcc63.c93813a","40efede3.33021c"]]},{"id":"ddcc63.c93813a","type":"debug","z":"ea6628fd.4d57e8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":390,"y":40,"wires":[]},{"id":"40efede3.33021c","type":"ui_text","z":"ea6628fd.4d57e8","group":"64a75353.37700c","order":0,"width":"0","height":"0","name":"MQTT exec","label":"Execution","format":"{{msg.payload}}","layout":"row-spread","x":390,"y":80,"wires":[]},{"id":"64e06023.868f58","type":"mqtt in","z":"ea6628fd.4d57e8","name":"","topic":"ohmpi_0001/data","qos":"2","datatype":"auto","broker":"6ae7e77e.04c64","inputs":0,"x":100,"y":140,"wires":[["ac400b27.992c78","8d7f5d51.c06c4"]]},{"id":"ac400b27.992c78","type":"debug","z":"ea6628fd.4d57e8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":390,"y":140,"wires":[]},{"id":"8d7f5d51.c06c4","type":"ui_text","z":"ea6628fd.4d57e8","group":"64a75353.37700c","order":1,"width":0,"height":0,"name":"MQTT Data","label":"Data","format":"{{msg.payload}}","layout":"row-spread","x":390,"y":180,"wires":[]},{"id":"e1cc28ee.d2dd6","type":"mqtt out","z":"ea6628fd.4d57e8","name":"MQTT ctrl","topic":"ohmpi_0001/ctrl","qos":"0","retain":"false","broker":"6ae7e77e.04c64","x":380,"y":340,"wires":[]},{"id":"a144e7f8.416768","type":"ui_button","z":"ea6628fd.4d57e8","name":"","group":"142ad6ae.d55e29","order":0,"width":"2","height":"1","passthru":false,"label":"Start","tooltip":"","color":"","bgcolor":"green","className":"","icon":"","payload":"start","payloadType":"str","topic":"topic","topicType":"msg","x":70,"y":340,"wires":[["e1cc28ee.d2dd6","4a86345b.fb400c"]]},{"id":"abd65786.c433c8","type":"ui_button","z":"ea6628fd.4d57e8","name":"","group":"142ad6ae.d55e29","order":0,"width":"2","height":"1","passthru":false,"label":"Stop","tooltip":"","color":"","bgcolor":"red","icon":"","payload":"stop","payloadType":"str","topic":"topic","topicType":"msg","x":70,"y":400,"wires":[["e1cc28ee.d2dd6","4a86345b.fb400c"]]},{"id":"4a86345b.fb400c","type":"ui_audio","z":"ea6628fd.4d57e8","name":"","group":"142ad6ae.d55e29","voice":"urn:moz-tts:speechd:English%20(Received%20Pronunciation)?en","always":"","x":380,"y":400,"wires":[]},{"id":"398460c6.27a9e8","type":"mqtt in","z":"ea6628fd.4d57e8","name":"","topic":"ohmpi_0001/soh","qos":"2","datatype":"auto","broker":"6ae7e77e.04c64","inputs":0,"x":100,"y":240,"wires":[["21b85b73.b7ef34","498c2864.b36b18"]]},{"id":"21b85b73.b7ef34","type":"debug","z":"ea6628fd.4d57e8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":390,"y":240,"wires":[]},{"id":"498c2864.b36b18","type":"ui_text","z":"ea6628fd.4d57e8","group":"64a75353.37700c","order":1,"width":0,"height":0,"name":"MQTT SOH","label":"SOH","format":"{{msg.payload}}","layout":"row-spread","x":390,"y":280,"wires":[]},{"id":"3dbcbc0e.3d24ac","type":"ui_form","z":"ea6628fd.4d57e8","name":"Commands","label":"","group":"142ad6ae.d55e29","order":4,"width":0,"height":0,"options":[{"label":"cmd_id","value":"cmd_id","type":"text","required":false,"rows":null},{"label":"cmd","value":"cmd","type":"text","required":true,"rows":null},{"label":"args","value":"args","type":"text","required":false,"rows":null}],"formValue":{"cmd_id":"","cmd":"","args":""},"payload":"","submit":"submit","cancel":"cancel","topic":"topic","topicType":"msg","splitLayout":"","className":"","x":120,"y":640,"wires":[["e1cc28ee.d2dd6","bfc5c3.3e79724"]]},{"id":"bfc5c3.3e79724","type":"ui_text","z":"ea6628fd.4d57e8","group":"64a75353.37700c","order":3,"width":0,"height":0,"name":"","label":"text","format":"{{msg.payload}}","layout":"row-spread","className":"","x":380,"y":640,"wires":[]}]