init
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*.env
|
||||||
|
*venv
|
||||||
|
__pycache__
|
||||||
38
config.py
Normal file
38
config.py
Normal 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
17
printer.py
Normal 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
3
requirements.txt
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
escpos
|
||||||
|
flask
|
||||||
|
pillow
|
||||||
104
server.py
Normal file
104
server.py
Normal 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
35
static/config.html
Normal 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
36
static/config.js
Normal 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
22
static/index.html
Normal 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
0
static/index.js
Normal file
0
static/style.css
Normal file
0
static/style.css
Normal file
Reference in New Issue
Block a user