Commit 6cc121d9c283170ebfe7e571bf306c4c35480c54

Commits
[COMMIT BEGIN]
commit 6cc121d9c283170ebfe7e571bf306c4c35480c54
Author: 0x4248 <[email protected]>
Date:   Tue Feb 3 09:20:17 2026 +0000

    escpos: add basic web server

diff --git a/toolkits/ESCPOS/Makefile b/toolkits/ESCPOS/Makefile
new file mode 100644
index 0000000..b0ecf58
--- /dev/null
+++ b/toolkits/ESCPOS/Makefile
@@ -0,0 +1,8 @@
+all: build run
+
+build:
+	mkdir -p build
+	gcc src/escpos.c src/escpos_commands.h -o build/escpos
+
+run: 
+	python3 src/server.py
\ No newline at end of file
diff --git a/toolkits/ESCPOS/src/server.py b/toolkits/ESCPOS/src/server.py
new file mode 100644
index 0000000..6586500
--- /dev/null
+++ b/toolkits/ESCPOS/src/server.py
@@ -0,0 +1,167 @@
+# python http server that lets you send escpos command via the escpos formatting language
+from flask import request, Response
+from flask import Flask
+from subprocess import Popen, PIPE
+import shlex
+import logging
+import os
+import datetime
+
+app = Flask(__name__)
+logging.basicConfig(level=logging.DEBUG)
+PRINTER = "/dev/usb/lp0" 
+
+STYLE = """
+* {
+    font-family: monospace;
+    background-color: #000;
+    color: #fff;
+}
+a {
+    color: #0f0;
+}
+
+input, textarea {
+    background-color: #222;
+    color: #fff;
+    border: 1px solid #555;
+}
+
+input[type="submit"] {
+    background-color: #444;
+    color: #fff;
+    border: 1px solid #888;
+    padding: 5px 10px;
+}
+
+"""
+
+def generate_escpos_cmdline(print_id):
+    return f"./escpos < ./data/jobs/{print_id}.epml > {PRINTER}"
+
+if not os.path.exists(PRINTER):
+    logging.error(f"Printer device {PRINTER} does not exist. Please check the printer connection.")
+    exit(1)
+
+if not os.path.exists("./data/jobs"):
+    os.makedirs("./data/jobs")
+else:
+    for filename in os.listdir("./data/jobs"):
+        file_path = os.path.join("./data/jobs", filename)
+        if os.path.isfile(file_path):
+            os.remove(file_path)
+
+class JobList:
+    def __init__(self):
+        self.jobs = []
+    
+    def add_job(self, job_id, title="New Job"):
+        timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+        self.jobs.append((job_id, title, timestamp))
+    
+    def get_jobs(self):
+        return self.jobs
+
+print_jobs = JobList()
+
[email protected]('/print/<print_id>', methods=['POST'])
+def print_escpos(print_id):
+    escpos_data = request.data.decode('utf-8')
+    job_file_path = f"./data/jobs/{print_id}.epml"
+    
+    with open(job_file_path, 'w') as job_file:
+        job_file.write(escpos_data)
+    
+    cmdline = generate_escpos_cmdline(print_id)
+    logging.debug(f"Executing command: {cmdline}")
+    
+    process = Popen(shlex.split(cmdline), stdout=PIPE, stderr=PIPE)
+    stdout, stderr = process.communicate()
+    
+    if process.returncode != 0:
+        logging.error(f"Error printing job {print_id}: {stderr.decode('utf-8')}")
+        return Response(f"Error printing job {print_id}: {stderr.decode('utf-8')}", status=500)
+    
+    logging.info(f"Successfully printed job {print_id}")
+    return Response(f"Successfully printed job {print_id}", status=200)
+
+
[email protected]('/print/submit_job', methods=['POST'])
+def submit_print_job():
+    escpos_data = request.form.get('escpos_data', '')
+    job_title = request.form.get('job_title', 'New Job')
+    print_now = request.form.get('print_now', 'no') == 'yes'
+    copies = int(request.form.get('copies', '1'))
+    
+    job_id = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
+    job_file_path = f"./data/jobs/{job_id}.epml"
+    
+    with open(job_file_path, 'w') as job_file:
+        job_file.write(escpos_data)
+    
+    print_jobs.add_job(job_id, job_title)
+    
+    if print_now:
+        for _ in range(copies):
+            cmdline = generate_escpos_cmdline(job_id)
+            logging.debug(f"Executing command: {cmdline}")
+            
+            process = Popen(shlex.split(cmdline), stdout=PIPE, stderr=PIPE)
+            stdout, stderr = process.communicate()
+            
+            if process.returncode != 0:
+                logging.error(f"Error printing job {job_id}: {stderr.decode('utf-8')}")
+                return Response(f"Error printing job {job_id}: {stderr.decode('utf-8')}", status=500)
+        
+        logging.info(f"Successfully printed job {job_id} ({copies} copies)")
+        return Response(f"Successfully printed job {job_id} ({copies} copies)", status=200)
+    
+    return Response(f"Job {job_id} submitted successfully", status=200)
+
[email protected]('/', methods=['GET'])
+def index():
+    job_list_html = "<h2>Print Jobs</h2><ul>"
+    for job in print_jobs.get_jobs():
+        job_id, title, timestamp = job
+        job_list_html += f"<li><a href='/print/{job_id}'>{title} - {timestamp}</a></li>"
+    job_list_html += "</ul>"
+
+    head_html = f"""
+    <head>
+    <style>
+    {STYLE}
+    </style>
+    </head>
+    """
+    form_html = """
+    <h1>ESC/POS Print Server</h1>
+    <p>Use the buttons below to insert ESC/POS commands into the textarea.</p>
+    <a onclick="appendText('[NORMAL]')">[NORMAL]</a>
+    <a onclick="appendText('[CENTER]')">[CENTER]</a>
+    <a onclick="appendText('[BOLD]')">[BOLD]</a>
+    <a onclick="appendText('[CUT]')">[CUT]</a>
+    <a onclick="appendText('[INVERT ON]')">[INVERT ON]</a>
+    <a onclick="appendText('[INVERT OFF]')">[INVERT OFF]</a>
+    <a onclick="appendText('[WIDE]')">[WIDE]</a>
+    <a onclick="appendText('[HR]')">[HORIZONTAL RULE]</a>
+    <a onclick="appendText('[NL]')">[NEWLINE]</a>
+    <br><br>
+    <form action="/print/submit_job" method="post">
+        <input type="text" name="job_title" placeholder="Job Title"><br>
+        <textarea id="escpos_data" name="escpos_data" rows="10" cols="50" placeholder="Enter ESC/POS commands here..."></textarea><br>
+        <input type="checkbox" name="print_now" value="yes" checked> Print Now<br>
+        <input type="number" name="copies" value="1" min="1" max="10"> Copies<br>
+        <input type="submit" value="Send Job to Server">
+    </form>
+    <script>
+    function appendText(text) {
+        var textarea = document.getElementById('escpos_data');
+        textarea.value += text;
+    }
+    </script>
+    """
+    
+    return head_html + form_html + job_list_html
+
+if __name__ == '__main__':
+    app.run(host='0.0.0.0', port=80, debug=True)
\ No newline at end of file
diff --git a/toolkits/ESCPOS/tools/fix-perms.sh b/toolkits/ESCPOS/tools/fix-perms.sh
new file mode 100644
index 0000000..651cb10
--- /dev/null
+++ b/toolkits/ESCPOS/tools/fix-perms.sh
@@ -0,0 +1 @@
+sudo chmod 666 /dev/usb/lp0
\ No newline at end of file
[COMMIT END]
(C) 2025 0x4248 (C) 2025 4248 Media and 4248 Systems, All part of 0x4248 See LICENCE files for more information. Not all files are by 0x4248 always check Licencing.