Commit 35cc7a8a authored by Olivier Kaufmann's avatar Olivier Kaufmann
Browse files

Merge branch 'mqtt' of gitlab-ssh.irstea.fr:reversaal/OhmPi into mqtt

Showing with 118 additions and 64 deletions
+118 -64
......@@ -20,7 +20,7 @@ OHMPI_CONFIG = {
CONTROL_CONFIG = {
'tcp_port': 5555,
'interface': 'mqtt_interface.py'
'interface': 'http_interface.py' # 'mqtt_interface'
}
# Execution logging configuration
EXEC_LOGGING_CONFIG = {
......@@ -56,13 +56,13 @@ SOH_LOGGING_CONFIG = {
# MQTT logging configuration parameters
MQTT_LOGGING_CONFIG = {
'hostname': 'ohmpy.umons.ac.be',
'hostname':'mg3d-dev.umons.ac.be',
'port': 1883,
'qos': 2,
'retain': False,
'keepalive': 60,
'will': None,
'auth': None,
'auth': { 'username': 'mqtt_user', 'password': 'mqtt_password' },
'tls': None,
'protocol': MQTTv31,
'transport': 'tcp',
......@@ -74,13 +74,13 @@ MQTT_LOGGING_CONFIG = {
# MQTT control configuration parameters
MQTT_CONTROL_CONFIG = {
'hostname': 'ohmpy.umons.ac.be',
'hostname': 'mg3d-dev.umons.ac.be',
'port': 1883,
'qos': 2,
'retain': False,
'keepalive': 60,
'will': None,
'auth': None,
'auth': { 'username': 'mqtt_user', 'password': 'mqtt_password' },
'tls': None,
'protocol': MQTTv31,
'transport': 'tcp',
......
from http.server import SimpleHTTPRequestHandler, HTTPServer
import time
import os
import json
import uuid
# from ohmpi import OhmPi
from config import CONTROL_CONFIG
from termcolor import colored
import threading
import pandas as pd
import shutil
import zmq # to write on TCP
import zmq # to write on TCP
# hostName = "raspberrypi.local" # works for AP-STA
# hostName = "192.168.50.1" # fixed IP in AP-STA mode
hostName = "0.0.0.0" # for AP mode (not AP-STA)
serverPort = 8080
# https://gist.github.com/MichaelCurrie/19394abc19abd0de4473b595c0e37a3a
# with open('ohmpi_settings.json') as json_file:
# pardict = json.load(json_file)
# ohmpi = OhmPi(pardict, sequence='dd.txt')
# ohmpi = OhmPi(pardict, sequence='dd16s0no8.txt')
tcp_port = CONTROL_CONFIG['tcp_port']
context = zmq.Context()
socket = context.socket(zmq.REQ)
......@@ -52,20 +42,20 @@ class MyServer(SimpleHTTPRequestHandler):
# global ohmpiThread, status, run
dic = json.loads(self.rfile.read(int(self.headers['Content-Length'])))
rdic = {} # response dictionnary
if dic['command'] == 'start':
# ohmpi.measure()
rdic = {} # response dictionnary
if dic['cmd'] == 'start':
#ohmpi.measure()
socket.send_string(json.dumps({
'cmd_id': cmd_id,
'command': 'start'
'cmd': 'start'
}))
elif dic['command'] == 'stop':
elif dic['cmd'] == 'stop':
# ohmpi.stop()
socket.send_string(json.dumps({
'cmd_id': cmd_id,
'command': 'stop'
'cmd': 'stop'
}))
elif dic['command'] == 'getData':
elif dic['cmd'] == 'getData':
# get all .csv file in data folder
fnames = [fname for fname in os.listdir('data/') if fname[-4:] == '.csv']
ddic = {}
......@@ -82,10 +72,10 @@ class MyServer(SimpleHTTPRequestHandler):
'rho': df['R [ohm]'].tolist(),
}
rdic['data'] = ddic
elif dic['command'] == 'removeData':
elif dic['cmd'] == 'removeData':
shutil.rmtree('data')
os.mkdir('data')
elif dic['command'] == 'update_settings':
elif dic['cmd'] == 'update_settings':
# ohmpi.stop()
socket.send_string(json.dumps({
'cmd_id': cmd_id,
......@@ -93,7 +83,7 @@ class MyServer(SimpleHTTPRequestHandler):
'args': dic['config']
}))
cdic = dic['config']
"""
ohmpi.pardict['nb_electrodes'] = int(cdic['nbElectrodes'])
ohmpi.pardict['injection_duration'] = float(cdic['injectionDuration'])
......@@ -107,11 +97,11 @@ class MyServer(SimpleHTTPRequestHandler):
print('new sequence set.')
print('setConfig', ohmpi.pardict)
"""
elif dic['command'] == 'invert':
elif dic['cmd'] == 'invert':
pass
elif dic['command'] == 'getResults':
elif dic['cmd'] == 'getResults':
pass
elif dic['command'] == 'rsCheck':
elif dic['cmd'] == 'rsCheck':
# ohmpi.rs_check()
socket.send_string(json.dumps({
'cmd_id': cmd_id,
......@@ -124,12 +114,12 @@ class MyServer(SimpleHTTPRequestHandler):
'res': df['RS [kOhm]'].tolist()
}
rdic['data'] = ddic
elif dic['command'] == 'download':
elif dic['cmd'] == 'download':
shutil.make_archive('data', 'zip', 'data')
elif dic['command'] == 'shutdown':
elif dic['cmd'] == 'shutdown':
print('shutting down...')
os.system('shutdown now -h')
elif dic['command'] == 'restart':
elif dic['cmd'] == 'restart':
print('shutting down...')
os.system('reboot')
else:
......@@ -142,7 +132,7 @@ class MyServer(SimpleHTTPRequestHandler):
message = socket.recv()
print('+++////', message)
rdic['data'] = message
rdic['data'] = message.decode('utf-8')
"""
while False:
message = socket.recv()
......
......@@ -17,7 +17,7 @@
<div class='container'>
<h1>OhmPi Acquisition Board</h1>
<!-- nb stacks, on-time -->
<button id="setConfigBtn" type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModal">Settings</button>
<button id="update_settingsBtn" type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModal">Settings</button>
<button id='startBtn' type="button" class="btn btn-primary">Start</button>
<button id='stopBtn' type="button" class="btn btn-warning">Stop</button>
<!-- upload button for csv which display the table ABMN -->
......@@ -142,7 +142,11 @@
// useful functions
function sendCommand(query, callback=null) {
<<<<<<< HEAD
// dic in the form: {'cmd': X, ...} as JSON
=======
// dic in the form: {'command': X, ...} as JSON
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
if (callback == null) {
function callback(x) {
console.log('default callback:', x)
......@@ -163,7 +167,11 @@
// start button
function startBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "start"}', function(x) {
=======
sendCommand('{"command": "start"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
console.log(x['status'])
if (x['status'] == 'running') {
output.innerHTML = 'Status: measuring...'
......@@ -175,7 +183,11 @@
// stop button
function stopBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "stop"}', function(x) {
=======
sendCommand('{"command": "stop"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
output.innerHTML = 'Status: ' + x['status']
clearInterval(interv)
getData()
......@@ -197,10 +209,17 @@
// define callback to send settigs to Pi
function configCallback() {
sendCommand(JSON.stringify({
<<<<<<< HEAD
'cmd': 'update_settings',
'config': formVals
}), function(x) {
console.log('update_settings', x)
=======
'command': 'setConfig',
'config': formVals
}), function(x) {
console.log('setconfig:', x)
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
})
}
......@@ -351,7 +370,11 @@
// run RS check
function rsBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "rsCheck"}', function (res) {
=======
sendCommand('{"command": "rsCheck"}', function (res) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
// update the bar plot
rsdata.push({
x: res['data']['AB'],
......@@ -376,7 +399,11 @@
// getData
function getData() {
sendCommand(JSON.stringify({
<<<<<<< HEAD
'cmd': 'getData',
=======
'command': 'getData',
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
'surveyNames': Object.keys(data).slice(0, -1)
// last survey is often partial so we download it again
}), function(ddic) {
......@@ -497,7 +524,11 @@
// remove data
function removeDataBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "removeData"}',function(x) {
=======
sendCommand('{"command": "removeData"}',function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
data = {}
output.innerHTML = 'Status: ' + x['status'] + ' (all data cleared)'
console.log('all data removed')
......@@ -508,7 +539,11 @@
// shutdown Pi
function shutdownBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "shutdown"}', function(x) {
=======
sendCommand('{"command": "shutdown"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
console.log('shuting down...')
})
}
......@@ -517,7 +552,11 @@
// restart Pi
function restartBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "restart"}', function(x) {
=======
sendCommand('{"command": "restart"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
console.log('rebooting...')
})
}
......@@ -526,7 +565,11 @@
// invert data
// function invertBtnFunc() {
<<<<<<< HEAD
// sendCommand('{"cmd": "invert"}', function(x) {
=======
// sendCommand('{"command": "invert"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
// console.log('inversion results', x)
// })
// }
......@@ -535,7 +578,11 @@
// download data
function downloadBtnFunc() {
<<<<<<< HEAD
sendCommand('{"cmd": "download"}', function(x) {
=======
sendCommand('{"command": "download"}', function(x) {
>>>>>>> a52ac9e5e0984f701ed4e4c3a437d7ae4cf0673a
let dwl = document.getElementById('download')
dwl.setAttribute('href', serverUrl + '/data.zip')
dwl.setAttribute('download', 'data.zip')
......
......@@ -6,7 +6,6 @@ import zmq
ctrl_queue = Queue()
def on_message(client, userdata, message):
global socket
......@@ -14,24 +13,40 @@ def on_message(client, userdata, message):
print(f'Sending command {message.payload.decode("utf-8")}')
socket.send_string(message.payload.decode("utf-8"))
# Get the reply.
# 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')
mqtt_client.connect(MQTT_CONTROL_CONFIG['hostname'])
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)
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)
......@@ -51,9 +51,12 @@ class MQTTHandler(logging.Handler):
cleanly.
"""
msg = self.format(record)
publish.single(self.topic, msg, self.qos, self.retain,
try:
publish.single(self.topic, msg, self.qos, self.retain,
hostname=self.hostname, port=self.port,
client_id=self.client_id, keepalive=self.keepalive,
will=self.will, auth=self.auth, tls=self.tls,
protocol=self.protocol, transport=self.transport)
except Exception as e:
print(e)
# -*- coding: utf-8 -*-
"""
created on January 6, 2020.
Update May 2022
Updates May 2022, Oct 2022.
Ohmpi.py is a program to control a low-cost and open hardware resistivity meter OhmPi that has been developed by
Rémi CLEMENT (INRAE),Vivien DUBOIS (INRAE), Hélène GUYARD (IGE), Nicolas FORQUET (INRAE), Yannick FARGIER (IFSTTAR)
Olivier KAUFMANN (UMONS) and Guillaume BLANCHY (ILVO).
......@@ -10,7 +10,6 @@ Olivier KAUFMANN (UMONS) and Guillaume BLANCHY (ILVO).
import os
import io
import json
# import subprocess
import numpy as np
import csv
......@@ -670,6 +669,7 @@ class OhmPi(object):
if cmd is not None and cmd_id is not None:
if cmd == 'update_settings' and args is not None:
self._update_acquisition_settings(args)
status = True
elif cmd == 'start':
self.measure(cmd_id)
while not self.status == 'idle':
......@@ -706,11 +706,13 @@ class OhmPi(object):
reply = {'cmd_id': cmd_id, 'status': status}
reply = json.dumps(reply)
self.exec_logger.debug(f'Execution report: {reply}')
self.exec_logger.debug(reply)
reply = bytes(reply, 'utf-8')
reply = reply.encode('utf-8')
socket.send(reply)
except zmq.Again:
time.sleep(.1)
except zmq.ZMQError as e:
if e.errno == zmq.EAGAIN:
pass # no message was ready (yet!)
else:
self.exec_logger.error(f'Unexpected error while process: {e}')
def measure(self, cmd_id=None):
"""Run the sequence in a separate thread. Can be stopped by 'OhmPi.stop()'.
......@@ -824,8 +826,5 @@ print(current_time.strftime("%Y-%m-%d %H:%M:%S"))
if __name__ == "__main__":
# start interface
Popen(['python', CONTROL_CONFIG['interface']])
print('done')
ohmpi = OhmPi(settings=OHMPI_CONFIG['settings'])
{
"nb_electrodes": 64,
"injection_duration":0.2,
"injection_duration": 0.2,
"nbr_meas": 1,
"sequence_delay": 1,
"nb_stack": 1,
......
[{"id":"ea6628fd.4d57e8","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"6ae7e77e.04c64","type":"mqtt-broker","name":"ohmpi_mqtt_broker","broker":"ohmpy.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":[]}]
\ No newline at end of file
[{"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":[]}]
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment