Commit 4968d55c authored by Joanne Hugé's avatar Joanne Hugé

ors-amarisoft: get eNB stats and add promises

parent 5c411cb7
Pipeline #25057 failed with stage
#!{{ python_path }}
import json
import logging
from logging.handlers import RotatingFileHandler
import time
from websocket import create_connection
class enbWebSocket:
def __init__(self):
log_file = "{{ log_file }}"
self.logger = logging.getLogger('logger')
self.logger.setLevel(logging.INFO)
handler = RotatingFileHandler(log_file, maxBytes=30000, backupCount=2)
formatter = logging.Formatter('{"time": "%(asctime)s", "log_level": "%(levelname)s", "message": "%(message)s", "data": %(data)s}')
handler.setFormatter(formatter)
self.logger.addHandler(handler)
if {{ testing }}:
return
self.ws_url = "ws://127.0.1.2:9001"
self.ws = create_connection(self.ws_url)
def close(self):
if {{ testing }}:
return
self.ws.close()
def send(self, msg):
self.ws.send(json.dumps(msg))
def recv(self, message_type):
for i in range(1,20):
r = json.loads(self.ws.recv())
if r['message'] == message_type:
return r
def stats(self):
if {{ testing }}:
from random import randint
r = {
'message': 'stats',
'samples': {'rx': [
{'sat': 0, 'max': randint(-500,-100) / 10.0},
{'sat': 0, 'max': randint(-500,-100) / 10.0},
]}
}
else:
self.send({
"message": "stats",
"samples": True,
"rf": True
})
r = self.recv('stats')
self.logger.info('Samples stats', extra={'data': r})
if __name__ == '__main__':
ws = enbWebSocket()
try:
while True:
ws.stats()
time.sleep({{ stats_period }})
finally:
ws.close()
......@@ -16,27 +16,31 @@
[template]
filename = instance.cfg
md5sum = 6e5c63c35b13f8920ea13e24c27d7b50
md5sum = 8a6e6e065e3eeffc3d5d4d8bb68f4a43
[amarisoft-stats.jinja2.py]
_update_hash_filename_ = amarisoft-stats.jinja2.py
md5sum = 6e0a052bd0ca08cc0c7b4880d3deffcc
[template-lte-enb-epc]
_update_hash_filename_ = instance-enb-epc.jinja2.cfg
md5sum = 42959a0525d2e06e61310836656d5de6
md5sum = f15c81f0f4c2aa59bc794d855e7d01c0
[template-lte-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = 04dbc8396cb112e86d5d1564df033b82
md5sum = 68362f58fccc534757b6bb566d285fa6
[template-lte-gnb-epc]
_update_hash_filename_ = instance-gnb-epc.jinja2.cfg
md5sum = 2b589e23486661c52f379c4d9b35e7a9
md5sum = dd98a2d0cb4fadc869638166bde6d9c8
[template-lte-epc]
_update_hash_filename_ = instance-epc.jinja2.cfg
md5sum = 9ffc54bf10757403c4b1809d1102ea52
md5sum = 48755eb0b2eb87f80130d42026ea8f7b
[template-lte-gnb]
_update_hash_filename_ = instance-gnb.jinja2.cfg
md5sum = 01f4de736594a0810a66f847753fadf1
md5sum = 45ff1f5f4e98867449dcff7caae678f8
[template-lte-mme]
_update_hash_filename_ = instance-mme.jinja2.cfg
......@@ -44,11 +48,11 @@ md5sum = 728f4d3ae248710c23e4b73eea4d628e
[template-lte-ue-lte]
_update_hash_filename_ = instance-ue-lte.jinja2.cfg
md5sum = 4517baee6700afbf78de3b2d7dd4ba22
md5sum = 38ef57bc93f53338187bd9c39fe4f0c5
[template-lte-ue-nr]
_update_hash_filename_ = instance-ue-nr.jinja2.cfg
md5sum = 45e7ade19a579d6750d2733a0659dc1a
md5sum = eaaf8fb3806a941f188eecdb90d38bda
[ue_db.jinja2.cfg]
filename = config/ue_db.jinja2.cfg
......@@ -56,7 +60,7 @@ md5sum = dcaac06553a3222b14c0013a13f4a149
[enb.jinja2.cfg]
filename = config/enb.jinja2.cfg
md5sum = 9fd6abb1e69fe59af0dafbb336f24f8d
md5sum = 1c9909f691b5bb00d3fc30d41613e26a
[sib23.asn]
filename = config/sib23.asn
......@@ -64,7 +68,7 @@ md5sum = b377dac7f1fcf94fb9ce9ebed617f36a
[gnb.jinja2.cfg]
filename = config/gnb.jinja2.cfg
md5sum = 407c20d11c5417636b985fe4886bf135
md5sum = 16698f0b4ea3e6cf40e9f070af2439e5
[ltelogs.jinja2.sh]
filename = ltelogs.jinja2.sh
......@@ -88,8 +92,24 @@ md5sum = b3078deab008d7e81ddd88ac02b8b698
[sdr-busy-promise]
_update_hash_filename_ = promise/check_sdr_busy.py
md5sum = 2e25144d1d952ed5bebb194360b60afb
md5sum = b0c65aefa60a9d5b9f7e7b38383db48b
[cell-gain-saturated-promise]
_update_hash_filename_ = promise/check_cell_gain_saturated.py
md5sum = 764ca8913ea40964382848cf3233c1f7
[rx-saturated-promise]
_update_hash_filename_ = promise/check_rx_saturated.py
md5sum = 40cf5389fd91845f4426ef159fb20fc0
[amarisoft-stats-log-promise]
_update_hash_filename_ = promise/check_amarisoft_stats_log.py
md5sum = 5bf57a9074ea5b054d999789cbbe2c87
[cpu-temperature-promise]
_update_hash_filename_ = promise/check_cpu_temperature.py
md5sum = 8e8f836554d81e2979e39dfb50e05b88
[interface-up-promise]
_update_hash_filename_ = promise/check_interface_up.py
md5sum = 7797aeaf02e055226249f2c08209775a
md5sum = 44ae5693f62b7a4dbc98f700f68d8600
......@@ -14,6 +14,7 @@
},
tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_lte_tx_gain']) }},
rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_lte_rx_gain']) }},
com_addr: "127.0.1.2:9001",
mme_list: [
{% if slapparameter_dict.get('mme_list', '') %}
......
......@@ -38,6 +38,7 @@
tx_gain: {{ slapparameter_dict.get('tx_gain', slap_configuration['configuration.default_nr_tx_gain']) }},
rx_gain: {{ slapparameter_dict.get('rx_gain', slap_configuration['configuration.default_nr_rx_gain']) }},
{% endif %}
com_addr: "127.0.1.2:9001",
amf_list: [
{% if slapparameter_dict.get('amf_list', '') %}
......
......@@ -14,6 +14,7 @@ parts =
directory
lte-enb-request
lte-mme-request
cpu-temperature-promise
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }}
sla-computer_guid = {{ slap_connection['computer-id'] }}
config-monitor-password = ${monitor-htpasswd:passwd}
config-sub-instance = true
[lte-mme-request]
<= request-common-base
......@@ -85,6 +87,14 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
lte-enb-request = ${lte-enb-request:connection-monitor-base-url}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
<= monitor-publish
......
......@@ -119,6 +119,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -4,7 +4,14 @@ parts =
ltelogs
lte-enb-config
lte-enb-service
amarisoft-stats-service
sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
amarisoft-stats-log-promise
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
monitor-base
publish-connection-information
......@@ -97,6 +104,30 @@ environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft
[amarisoft-stats-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-stats.json.log
context =
section directory directory
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775
url = {{ amarisoft_stats_template }}
output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb)
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
wrapper-path = ${directory:service}/amarisoft-stats
mode = 0775
hash-files =
${amarisoft-stats-template:output}
[config-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
......@@ -130,7 +161,6 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
# Add custom promise to check if /dev/sdr0 is busy
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
......@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
[cell-gain-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cell_gain_saturated_promise }}
output = ${directory:plugins}/check-cell-gain-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[rx-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
[amarisoft-stats-log-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ amarisoft_stats_log_promise }}
output = ${directory:plugins}/check-amarisoft-stats-log.py
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-maxtemp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
......@@ -26,6 +26,12 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -13,6 +13,9 @@ info = Your SIM card has been attached to service ${slap-configuration:instance-
parts =
directory
lte-mme-request
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -73,6 +76,14 @@ config-slave-list = {{ dumps(slave_instance_list) }}
[monitor-base-url-dict]
lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
<= monitor-publish
......
......@@ -14,6 +14,7 @@ parts =
directory
lte-gnb-request
lte-mme-request
cpu-temperature-promise
publish-connection-information
{% for part in part_list -%}
{{ ' %s' % part }}
......@@ -59,6 +60,7 @@ cert-file = {{ slap_connection['cert-file'] }}
sla-computer_guid = {{ slap_connection['computer-id'] }}
config-monitor-password = ${monitor-htpasswd:passwd}
config-sub-instance = true
[lte-mme-request]
<= request-common-base
......@@ -85,6 +87,14 @@ return = monitor-base-url
lte-mme-request = ${lte-mme-request:connection-monitor-base-url}
lte-gnb-request = ${lte-gnb-request:connection-monitor-base-url}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
[publish-connection-information]
recipe = slapos.cookbook:publish.serialised
<= monitor-publish
......
......@@ -171,6 +171,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -4,7 +4,14 @@ parts =
ltelogs
lte-gnb-config
lte-enb-service
amarisoft-stats-service
sdr-busy-promise
cell-gain-saturated-promise
rx-saturated-promise
amarisoft-stats-log-promise
{% if not slapparameter_dict.get("sub-instance", False) %}
cpu-temperature-promise
{% endif %}
monitor-base
publish-connection-information
......@@ -98,6 +105,30 @@ environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft
[amarisoft-stats-template]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
log-output = ${directory:var}/log/amarisoft-stats.json.log
context =
section directory directory
key slapparameter_dict slap-configuration:configuration
key log_file :log-output
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
raw testing {{ slapparameter_dict.get("testing", False) }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775
url = {{ amarisoft_stats_template }}
output = ${directory:bin}/amarisoft-stats.py
### eNodeB (enb)
[amarisoft-stats-service]
recipe = slapos.cookbook:wrapper
command-line = ${amarisoft-stats-template:output}
wrapper-path = ${directory:service}/amarisoft-stats
mode = 0775
hash-files =
${amarisoft-stats-template:output}
[config-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
......@@ -130,7 +161,6 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
# Add custom promise to check if /dev/sdr0 is busy
[sdr-busy-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
......@@ -138,3 +168,44 @@ file = {{ sdr_busy_promise }}
output = ${directory:plugins}/check-sdr-busy.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
[cell-gain-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ cell_gain_saturated_promise }}
output = ${directory:plugins}/check-cell-gain-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[rx-saturated-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ rx_saturated_promise }}
output = ${directory:plugins}/check-rx-saturated.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-max-rx-sample-db = {{ slapparameter_dict.get("max_rx_sample_db", 0) }}
[amarisoft-stats-log-promise]
recipe = slapos.cookbook:promise.plugin
eggs =
slapos.core
python-dateutil
file = {{ amarisoft_stats_log_promise }}
output = ${directory:plugins}/check-amarisoft-stats-log.py
config-amarisoft-stats-log = ${amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
[cpu-temperature-promise]
recipe = slapos.cookbook:promise.plugin
eggs = slapos.core
file = {{ cpu_temperature_promise }}
output = ${directory:plugins}/check-cpu-temperature.py
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-max-temp = {{ slapparameter_dict.get("promise_cpu_temperature_threshold", 80) }}
......@@ -117,6 +117,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -99,6 +99,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -169,6 +169,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -151,6 +151,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -117,6 +117,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -99,6 +99,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}
}
......@@ -169,6 +169,24 @@
"title": "Use IPv4",
"description": "Set to true to use IPv4 for AMF / MME addresses",
"type": "boolean"
},
"enb_stats_fetch_period": {
"title": "eNB statistics fetch period (seconds)",
"description": "Describes how often a call to Amarisoft remote API is made to get eNB statistics",
"type": "number",
"default": 60
},
"max_rx_sample_db": {
"title": "Maximum RX sample value (dB)",
"description": "Maximum RX sample threshold above which RX saturated promise will fail",
"type": "number",
"default": 0
},
"promise_cpu_temperature_threshold": {
"title": "CPU temperature promise threshold",
"description": "Temperature threshold above which CPU temperature promise will fail",
"type": "number",
"default": 80
}
}