#!/usr/bin/env python3 """Packs out/app-Rion-MeetingRoom.sax for the Ontrol Rion simulator (ontrol_VM). python make_sim.py Writes out/sim/device/ (app.sab, kits.scode, images/, fonts/, system/) and out/app-Rion-MeetingRoom-sim.zip, the backup layout simulatorLauncher opens. kits.scode and the boot logo are taken from ontrol_VM's ExampleApp Rion backup, so the app's schema is rewritten to that scode's kits and checksums. """ import os, re, shutil, sys, zipfile from PIL import Image HERE = os.path.dirname(os.path.abspath(__file__)) SEDONA_HOME = r"C:\Users\aa\OneDrive - Ontrol\Documents\_is\NiagaraAXSedona\sedona" VM = r"C:\Users\aa\_aaSourceCodes\ontrol_VM" EXAMPLE = os.path.join(VM, "ExampleApp", "app-RION-VM_mini.zip") SAB2SAX = r"C:\Users\aa\_aaSourceCodes\Py_sab2sax" FONTS = ["16pt Tahoma.bin", "32pt Tahoma.bin", "72pt Tahoma.bin", "bold 18pt Tahoma.bin", "bold 32pt Tahoma.bin", "bold 48pt Tahoma.bin"] OUT = os.path.join(HERE, "out") SAX = os.path.join(OUT, "app-Rion-MeetingRoom.sax") SIM = os.path.join(OUT, "sim") DEV = os.path.join(SIM, "device") shutil.rmtree(SIM, ignore_errors=True) for d in ("images", "fonts", "system"): os.makedirs(os.path.join(DEV, d)) # app.sax with the example scode's schema (kit set and checksums must match kits.scode) with zipfile.ZipFile(EXAMPLE) as z: ex_sax = z.read("app.sax").decode("utf-8") open(os.path.join(DEV, "kits.scode"), "wb").write(z.read("device/kits.scode")) open(os.path.join(DEV, "system", "logo.bin"), "wb").write(z.read("device/system/logo.bin")) schema = re.search(r".*?", ex_sax, re.S).group(0) sim_sax = re.sub(r".*?", lambda m: schema, open(SAX, encoding="utf-8").read(), flags=re.S) open(os.path.join(SIM, "app.sax"), "w", encoding="utf-8", newline="\n").write(sim_sax) sys.path.insert(0, SAB2SAX) import sab # Py_sab2sax's SAX -> SAB encoder sab.encode(os.path.join(SIM, "app.sax"), SEDONA_HOME, os.path.join(DEV, "app.sab")) def native_image(path, name): """Rion image file: 32-byte name, flags, u16 LE width/height, 27 pad, RGB565 LE.""" img = Image.open(path).convert("RGB") w, h = img.size out = bytearray(name.encode("ascii")) + bytes(32 - len(name)) out += bytes([0, w & 0xFF, w >> 8, h & 0xFF, h >> 8]) + bytes(27) for r, g, b in img.getdata(): v = (r >> 3) << 11 | (g >> 2) << 5 | (b >> 3) out += bytes((v & 0xFF, v >> 8)) return bytes(out) bank = os.path.join(OUT, "imageBank") for f in sorted(os.listdir(bank)): name = os.path.splitext(f)[0] open(os.path.join(DEV, "images", name + ".bin"), "wb").write(native_image(os.path.join(bank, f), name)) for f in FONTS: shutil.copy2(os.path.join(SEDONA_HOME, "ontrol", "fontBank", f), os.path.join(DEV, "fonts", f)) zpath = os.path.join(OUT, "app-Rion-MeetingRoom-sim.zip") with zipfile.ZipFile(zpath, "w", zipfile.ZIP_DEFLATED) as z: for root, _, files in os.walk(SIM): for f in files: full = os.path.join(root, f) z.write(full, os.path.relpath(full, SIM).replace(os.sep, "/")) for f in os.listdir(bank): z.write(os.path.join(bank, f), "imageBank/" + f) for f in FONTS: z.write(os.path.join(DEV, "fonts", f), "fontBank/" + f) print("device folder:", DEV) print("backup zip: ", zpath)