Automate gen_set.py with page detection and command line parameters

This commit is contained in:
Thomas Hooge 2025-08-01 11:01:23 +02:00
parent fb3af0bf83
commit 28a7e58e27
1 changed files with 168 additions and 121 deletions

View File

@ -1,132 +1,179 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# A tool to generate that part of config.json that deals with pages and fields.
#
#Usage: 1. modify this script (e.g.add a page, change number of fields, etc.)
# 2. Delete all lines from config.json from the curly backet before "name": "page1type" to o the end of the file (as of today, delete from line 917 to the end of the File)
# 3. run ./gen_set.py >> config.json
"""
A tool to generate that part of config.json that deals with pages and fields.
Usage example:
1. Delete all lines from config.json from the curly backet before
"name": "page1type" to the end of the file
2. run ./gen_set.py -d obp60 -p 10 >> config.json
TODO Better handling of default pages
"""
import os
import sys
import getopt
import re
import json import json
# List of all pages and the number of parameters they expect. __version__ = "0.2"
no_of_fields_per_page = {
"Wind": 0,
"XTETrack": 0,
"Battery2": 0,
"Battery": 0,
"BME280": 0,
"Clock": 0,
"Compass" : 0,
"DST810": 0,
"Fluid": 1,
"FourValues2": 4,
"FourValues": 4,
"Generator": 0,
"KeelPosition": 0,
"OneValue": 1,
"RollPitch": 2,
"RudderPosition": 0,
"SixValues" : 6,
"Solar": 0,
"ThreeValues": 3,
"TwoValues": 2,
"Voltage": 0,
"WhitePage": 0,
"WindPlot": 0,
"WindRose": 0,
"WindRoseFlex": 6,
}
# No changes needed beyond this point def detect_pages(filename):
# max number of pages supported by OBP60 # returns a dictionary with page name and the number of gui fields
no_of_pages = 10 pagefiles = []
# Default selection for each page with open(filename, 'r') as fh:
default_pages = [ pattern = r'extern PageDescription\s*register(Page[^;\s]*)'
"Voltage", for line in fh:
"WindRose", if "extern PageDescription" in line:
"OneValue", match = re.search(pattern, line)
"TwoValues", if match:
"ThreeValues", pagefiles.append(match.group(1))
"FourValues", try:
"FourValues2", pagefiles.remove('PageSystem')
"Clock", except ValueError:
"RollPitch", pass
"Battery2", pagedata = {}
] for pf in pagefiles:
numbers = [ filename = pf + ".cpp"
"one", with open(filename, 'r') as fh:
"two", content = fh.read()
"three", pattern = r'PageDescription\s*?register' + pf + r'\s*\(\s*"([^"]+)".*?\n\s*(\d+)'
"four", match = re.search(pattern, content, re.DOTALL)
"five", if match:
"six", pagedata[match.group(1)] = int(match.group(2))
"seven", return pagedata
"eight",
"nine",
"ten",
]
pages = sorted(no_of_fields_per_page.keys())
max_no_of_fields_per_page = max(no_of_fields_per_page.values())
output = [] def get_default_page(pageno):
# Default selection for each page
default_pages = (
"Voltage",
"WindRose",
"OneValue",
"TwoValues",
"ThreeValues",
"FourValues",
"FourValues2",
"Clock",
"RollPitch",
"Battery2"
)
if pageno > len(default_pages):
return "OneValue"
return default_pages[pageno - 1]
for page_no in range(1, no_of_pages + 1): def number_to_text(number):
page_data = { if number < 0 or number > 99:
"name": f"page{page_no}type", raise ValueError("Only numbers from 0 to 99 are allowed.")
"label": "Type", numbers = ("zero", "one", "two", "three", "four", "five", "six", "seven",
"type": "list", "eight", "nine", "ten", "eleven", "twelve", "thirteen", "fourteen",
"default": default_pages[page_no - 1], "fifteen", "sixteen", "seventeen", "eighteen", "nineteen")
"description": f"Type of page for page {page_no}", tens = ("", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy",
"list": pages, "eighty", "ninety")
"category": f"OBP60 Page {page_no}", if number < 20:
"capabilities": {"obp60": "true"}, return numbers[number]
"condition": [{"visiblePages": vp} for vp in range(page_no, no_of_pages + 1)], else:
#"fields": [], q, r = divmod(number, 10)
} return tens[q] + numbers[r]
output.append(page_data)
for field_no in range(1, max_no_of_fields_per_page + 1): def create_json(device, no_of_pages, pagedata):
field_data = {
"name": f"page{page_no}value{field_no}", pages = sorted(pagedata.keys())
"label": f"Field {field_no}", max_no_of_fields_per_page = max(pagedata.values())
"type": "boatData",
"default": "", output = []
"description": f"The display for field {numbers[field_no - 1]}",
"category": f"OBP60 Page {page_no}", for page_no in range(1, no_of_pages + 1):
"capabilities": {"obp60": "true"}, page_data = {
"condition": [ "name": f"page{page_no}type",
{f"page{page_no}type": page} "label": "Type",
for page in pages "type": "list",
if no_of_fields_per_page[page] >= field_no "default": get_default_page(page_no),
"description": f"Type of page for page {page_no}",
"list": pages,
"category": f"{device.upper()} Page {page_no}",
"capabilities": {device.lower(): "true"},
"condition": [{"visiblePages": vp} for vp in range(page_no, no_of_pages + 1)],
#"fields": [],
}
output.append(page_data)
for field_no in range(1, max_no_of_fields_per_page + 1):
field_data = {
"name": f"page{page_no}value{field_no}",
"label": f"Field {field_no}",
"type": "boatData",
"default": "",
"description": "The display for field {}".format(number_to_text(field_no)),
"category": f"{device.upper()} Page {page_no}",
"capabilities": {device.lower(): "true"},
"condition": [
{f"page{page_no}type": page}
for page in pages
if pagedata[page] >= field_no
],
}
output.append(field_data)
fluid_data ={
"name": f"page{page_no}fluid",
"label": "Fluid type",
"type": "list",
"default": "0",
"list": [
{"l":"Fuel (0)","v":"0"},
{"l":"Water (1)","v":"1"},
{"l":"Gray Water (2)","v":"2"},
{"l":"Live Well (3)","v":"3"},
{"l":"Oil (4)","v":"4"},
{"l":"Black Water (5)","v":"5"},
{"l":"Fuel Gasoline (6)","v":"6"}
], ],
} "description": "Fluid type in tank",
output.append(field_data) "category": f"{device.upper()} Page {page_no}",
"capabilities": {
device.lower(): "true"
},
"condition":[{f"page{page_no}type":"Fluid"}]
}
output.append(fluid_data)
fluid_data ={ return json.dumps(output, indent=4)
"name": f"page{page_no}fluid",
"label": "Fluid type",
"type": "list",
"default": "0",
"list": [
{"l":"Fuel (0)","v":"0"},
{"l":"Water (1)","v":"1"},
{"l":"Gray Water (2)","v":"2"},
{"l":"Live Well (3)","v":"3"},
{"l":"Oil (4)","v":"4"},
{"l":"Black Water (5)","v":"5"},
{"l":"Fuel Gasoline (6)","v":"6"}
],
"description": "Fluid type in tank",
"category": f"OBP60 Page {page_no}",
"capabilities": {
"obp60":"true"
},
"condition":[{f"page{page_no}type":"Fluid"}]
}
output.append(fluid_data)
json_output = json.dumps(output, indent=4) def usage():
# print omitting first and last line containing [ ] of JSON array print("{} v{}".format(os.path.basename(__file__), __version__))
#print(json_output[1:-1]) print()
# print omitting first line containing [ of JSON array print("Command line options")
print(json_output[1:]) print(" -d --device device name to use e.g. obp60")
# print(",") print(" -p --pages number of pages to create")
print(" -h show this help")
print()
if __name__ == '__main__':
try:
options, remainder = getopt.getopt(sys.argv[1:], 'd:p:', ['device=','--pages='])
except getopt.GetoptError as err:
print(err)
usage()
sys.exit(2)
device = "obp60"
no_of_pages = 10
for opt, arg in options:
if opt in ('-d', '--device'):
device = arg
elif opt in ('-p', '--pages'):
no_of_pages = int(arg)
elif opt == '-h':
usage()
sys.exit(0)
# automatic detect pages and number of fields from sourcecode
pagedata = detect_pages("obp60task.cpp")
json_output = create_json(device, no_of_pages, pagedata)
# print omitting first line containing [ of JSON array
print(json_output[1:])