This commit is contained in:
2025-09-15 00:15:49 +03:00
commit 8c1647eb13
10 changed files with 258 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
*.env
*venv
__pycache__

38
config.py Normal file
View File

@@ -0,0 +1,38 @@
import json
import printer
class PrinterConfig:
editables = {"printer_address", "printer_port"}
required_params = {"printer_address"}
def __init__(self):
self.printer_address = None
self.printer_port = 9100
self.printer_profile = "RP-F10-80mm"
self.__printer = None
def save(self):
with open("config.json", "w", encoding="utf-8") as ofd:
json.dump(self.__dict__, ofd, ensure_ascii=False)
def load(self):
with open("config.json", "r", encoding="utf-8") as ifd:
self.__dict__ = json.load(ifd)
@property
def complete(self):
for param in self.required_params:
if getattr(self, param) is None:
return False
return True
@property
def printer(self):
if self.__printer is None:
self.__printer = printer.Printer(
address=self.printer_address,
port=self.printer_port,
profile=self.printer_profile,
)
return self.printer

17
printer.py Normal file
View File

@@ -0,0 +1,17 @@
from escpos.printer import Network
class Printer:
def __init__(self, address: str, port: int = 9070, profile="RP-F10-80mm"):
self.address = address
self.port = port
self.profile = profile
self.printer = Network(host = self.address, port=self.port, profile=profile)
def test_connection(self):
return self.printer.is_online()
def print_text(self, text: str):
# todo text properties via printer.set()
self.printer.text(text)
self.printer.ln(2)
self.printer.cut()

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
escpos
flask
pillow

104
server.py Normal file
View File

@@ -0,0 +1,104 @@
from os import environ
import argparse
from flask import Flask, request, make_response, send_from_directory, jsonify
from config import PrinterConfig
argument_parser = argparse.ArgumentParser()
argument_parser.add_argument("--address", type=str, required=False, default="0.0.0.0")
argument_parser.add_argument("--port", type=int, required=False, default=8005)
args = argument_parser.parse_args()
printer_config = PrinterConfig()
app = Flask(__name__)
@app.route("/")
def index_route():
return send_from_directory("static", "index.html")
@app.route("/config", methods=["GET", "POST"])
def config_route():
request_type = None
if "Accept" in request.headers:
if "text/html" in request.headers["Accept"]:
request_type = "html"
elif "application/json" in request.headers["Accept"]:
request_type = "json"
print(request_type)
if request.method == "GET" and request_type == "html":
# return config html page
return send_from_directory("static", "config.html")
elif request.method == "GET" and request_type == "json":
# render config as JSON
print(get_config())
return jsonify(get_config())
elif request.method == "POST" and request.is_json:
# accept JSON form with new parameters
errors = {"critical": False, "errors": {}}
try:
request_data = request.json
print(request_data)
except Exception:
errors["errors"]["json"] = "Could not decode message as json"
errors["critical"] = True
request_params = {}
if "address" in request_data:
request_params["address"] = request_data["address"]
if "port" in request_data:
port = request_data["port"]
if isinstance(port, int) and 0 < port <= 65535:
request_params["port"] = port
else:
errors["errors"]["parseint"] = "Could not parse port number as an integer"
errors["critical"] = True
response = jsonify(errors)
if errors["critical"]:
response.status_code = 422
else:
response.status_code = 200
set_config(**request_params)
return response
def get_config():
return {
"address": printer_config.printer_address,
"port": printer_config.printer_port,
"profile": printer_config.printer_profile,
"can_print": can_print(),
}
def set_config(address: str = None, port: int = None):
if address is None:
printer_config.printer_address = None
else:
printer_config.printer_address = address
if port is None:
printer_config.printer_port = 9100
else:
printer_config.printer_port = port
def can_print():
return printer_config.complete
if __name__ == "__main__":
try:
printer_config.load()
except FileNotFoundError:
pass
try:
app.run(host=args.address, port=args.port)
except KeyboardInterrupt:
pass
printer_config.save()
exit(0)

35
static/config.html Normal file
View File

@@ -0,0 +1,35 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>P80 printer webpage configuration</title>
<script src="static/config.js"></script>
</head>
<body onload="render_config();">
<div class="navbar">
<ul>
<a href="/">Print</a>
<a href="/config">Configuration</a>
</ul>
</div>
<div class="container" display="block">
<form>
<label for="address">Address:</label><br>
<input type="text" id="address" name="address" title="Printer network address (ip/hostname)"
maxlength="30"><br>
<label for="port">Port:</label><br>
<input type="text" id="port" name="port" pattern="\d{1,5}" title="Port number (9100 by default)"><br>
<label for="profile">Profile:</label><br>
<input type="text" id="profile" name="profile" title="Printer profile, fixed value for now" readonly><br>
</form>
<button type="submit" onclick="send_config()">Update config</button>
</div>
</body>
</html>

36
static/config.js Normal file
View File

@@ -0,0 +1,36 @@
async function get_config() {
response = await fetch("/config", {method: "GET", headers: {"Accept": "application/json"}})
if (! response.ok){
throw Error("config data request error: " + await response.text())
}
return response.json()
}
async function render_config(){
params = await get_config()
for (par of Object.keys(params)) {
if (params.par == null) {
params.par = ""
}
}
const {address, port, profile} = params
document.getElementById("address").value = address
document.getElementById("port").value = port
document.getElementById("profile").value = profile
}
async function send_config() {
address_value = document.getElementById("address").value
port_value = document.getElementById("port").value
if (port_value == ""){
port_value = null
}
else{
port_value = parseInt(port_value)
}
response = await fetch("/config", {method: "POST", headers: {"Accept": "application/json", "Content-Type": "application/json"},
body: JSON.stringify({"address": address_value, "port": port_value, })})
document.location.reload()
}

22
static/index.html Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>P80 printer webpage</title>
</head>
<body>
<div class="navbar">
<ul>
<a href="/">Print</a>
<a href="/config">Configuration</a>
</ul>
</div>
<div class="container" display="block">
</div>
</body>
</html>

0
static/index.js Normal file
View File

0
static/style.css Normal file
View File