mirror of
https://github.com/NaitLee/Cat-Printer.git
synced 2025-05-18 00:00:18 -07:00
Take IPP support back, update doc, few other thing
This commit is contained in:
parent
2f4e111419
commit
1768c5055e
25
README.md
25
README.md
@ -1,4 +1,4 @@
|
||||
English | [Deutsch](./README.de_DE.md) | [简体中文](./README.zh_CN.md)
|
||||
English | [Deutsch](./readme.i18n/README.de_DE.md) | [简体中文](./readme.i18n/README.zh_CN.md)
|
||||
|
||||
# Cat-Printer
|
||||
|
||||
@ -16,22 +16,37 @@ Currently:
|
||||
|
||||
## Features
|
||||
|
||||
*Currently it's in development. More will be here soon!*
|
||||
|
||||
| Available | Partial | Planned |
|
||||
|-----------------|-----------|---------------|
|
||||
| Web Interface | CUPS/IPP* | Visual Editor |
|
||||
| Print a Picture | | Help/Manual |
|
||||
| Command-line | | Text Printing |
|
||||
|
||||
<!-- May comment the line below if there are no * -->
|
||||
\* In development code. Will be released in a short period.
|
||||
|
||||
*Along with...*
|
||||
|
||||
- Simple!
|
||||
- Operate via a Web UI just in browser,
|
||||
- or get the Android release!
|
||||
- ~~Feature-rich~~
|
||||
- Currently it's in development. More will be there soon!
|
||||
|
||||
- Friendly!
|
||||
- Language support! You can participate in translation!
|
||||
- Good user interface, adaptive to PC/mobile and light/dark theme!
|
||||
|
||||
- Cross platform!
|
||||
- Newer Windows 10 and above
|
||||
- GNU/Linux
|
||||
- MacOS *(Needs testing)*
|
||||
- and a lot of extra efforts for Android!
|
||||
|
||||
- Free, as in [freedom](https://www.gnu.org/philosophy/free-sw.html)!
|
||||
- Unlike the "original" proprietary app,
|
||||
this project is for everyone that concerns *open-mind and freedom*!
|
||||
|
||||
- and Fun!
|
||||
- Do whatever you like!
|
||||
|
||||
@ -99,7 +114,7 @@ See file `COPYING`, `LICENSE`, and detail of used JavaScript in file `www/jslice
|
||||
|
||||
## Development
|
||||
|
||||
You may interested in language support, anyway. See the translation files in directory `www/lang`!
|
||||
You may interested in language support, anyway. See the translation files in directory `www/lang` and `readme.i18n`!
|
||||
Note: you can correct some mistakes in them, if there are any. Also feel free to make it (truly) better!
|
||||
|
||||
Also interested in code development? See [development.md](development.md)!
|
||||
@ -111,5 +126,5 @@ Also interested in code development? See [development.md](development.md)!
|
||||
- [roddeh-i18n](https://github.com/roddeh/i18njs), good work!
|
||||
- [python-for-android](https://python-for-android.readthedocs.io/en/latest/), though there are some painful troubles
|
||||
- [AdvancedWebView](https://github.com/delight-im/Android-AdvancedWebView) for saving my life from Java
|
||||
- Stack Overflow & the whole Internet, you let me know Android `Activity` all from empty
|
||||
- Stack Overflow & the whole Internet, you let me know Android `Activity` all from beginning
|
||||
- ... Everyone is Awesome!
|
||||
|
12
TODO
12
TODO
@ -1,8 +1,16 @@
|
||||
|
||||
Note: not ordered. do whatever I/you want
|
||||
|
||||
+ Check GB03, again
|
||||
+ Hacky text printing, typewriter-like, with PF2 font
|
||||
+ Better MTU/freq moderation
|
||||
ok I won't forget frontend, but it's different
|
||||
+ Better CLI, e.g. invoke imagemagick if input is not PBM
|
||||
+ (Re-)support CUPS & IPP
|
||||
+ Consider better MTU adaption
|
||||
+ Consider better BLE traffic regulation, with BLE notification
|
||||
+ Consider the printer 'text' mode, it can make things faster
|
||||
+ Consider more control to something like 'energy'
|
||||
+ Consider keeping server backend (more) secure to be used by IPP
|
||||
+ Clean up CUPS/IPP code
|
||||
+ Make a build guide for android:
|
||||
Summary the hacks to p4a, bleak p4a recipe, p4a webview bootstrap, and AdvancedWebView
|
||||
+ More frontend usability, more functions
|
||||
|
0
additional/__init__.py
Normal file
0
additional/__init__.py
Normal file
@ -26,10 +26,12 @@ class I18n():
|
||||
self.load_file(os.path.join(search_path, name))
|
||||
|
||||
def load_file(self, name):
|
||||
'Load an i18n json file'
|
||||
with open(name, 'r', encoding='utf-8') as file:
|
||||
self.load_data(file.read())
|
||||
|
||||
def load_data(self, raw_json):
|
||||
'Load i18n json data (from str)'
|
||||
data = json.loads(raw_json)
|
||||
for key in data['values']:
|
||||
self.data['values'][key] = data['values'][key]
|
||||
@ -60,5 +62,5 @@ class I18n():
|
||||
if string is None:
|
||||
string = data
|
||||
for j in i:
|
||||
string = string.replace('%%{%s}' % j, i[j])
|
||||
string = string.replace(f'%%{j}', i[j])
|
||||
return string
|
100
additional/ipp.py
Normal file
100
additional/ipp.py
Normal file
@ -0,0 +1,100 @@
|
||||
''' Provide *very* basic CUPS/IPP support
|
||||
Extracted from version 0.0.2, do more cleaning later...
|
||||
'''
|
||||
|
||||
import platform
|
||||
import subprocess
|
||||
|
||||
class IPP():
|
||||
'https://datatracker.ietf.org/doc/html/rfc8010'
|
||||
server = None
|
||||
printer = None
|
||||
def __init__(self, server, printer):
|
||||
self.server = server
|
||||
self.printer = printer
|
||||
async def handle_ipp(self, data):
|
||||
'Handle an IPP protocol request'
|
||||
server = self.server
|
||||
# len_data = len(data)
|
||||
# ipp_version_number = data[0:2]
|
||||
# ipp_operation_id = data[2:4]
|
||||
# ipp_request_id = data[4:8]
|
||||
ipp_operation_attributes_tag = data[8]
|
||||
attributes = {}
|
||||
data_to_print = b''
|
||||
# this is silly. i want to use io.BytesIO
|
||||
if ipp_operation_attributes_tag == 0x01:
|
||||
pointer = 9
|
||||
next_name_length_at = 10
|
||||
next_value_length_at = 10
|
||||
name = b''
|
||||
value = b''
|
||||
while data[pointer] != 0x03:
|
||||
tag = data[pointer:pointer + 1]
|
||||
pointer += 1
|
||||
if tag[0] < 0x10: # delimiter-tag
|
||||
continue
|
||||
next_name_length_at = pointer + data[pointer] * 0x0100 + data[pointer + 1] + 2
|
||||
pointer += 2
|
||||
while pointer < next_name_length_at:
|
||||
name = name + data[pointer:pointer + 1]
|
||||
pointer += 1
|
||||
next_value_length_at = pointer + data[pointer] * 0x0100 + data[pointer + 1] + 2
|
||||
pointer += 2
|
||||
while pointer < next_value_length_at:
|
||||
value = value + data[pointer:pointer + 1]
|
||||
pointer += 1
|
||||
attributes[name] = (tag, value)
|
||||
name = b''
|
||||
value = b''
|
||||
pointer += 1
|
||||
data_to_print = data[pointer:]
|
||||
# there are hard coded minimal response. this "just works" on cups
|
||||
if data_to_print == b'':
|
||||
try:
|
||||
server.send_response(200)
|
||||
server.send_header('Content-Type', 'application/ipp')
|
||||
server.end_headers()
|
||||
server.wfile.write(
|
||||
b'\x01\x01\x00\x00\x00\x00\x00\x01\x01\x03'
|
||||
)
|
||||
except BrokenPipeError:
|
||||
pass
|
||||
return
|
||||
platform_system = platform.system()
|
||||
# https://ghostscript.com/doc/9.54.0/Use.htm#Output_device
|
||||
if platform_system == 'Windows':
|
||||
gsexe = 'gswin32c.exe'
|
||||
elif platform_system == 'OS/2':
|
||||
gsexe = 'gsos2'
|
||||
else:
|
||||
gsexe = 'gs'
|
||||
gsproc = subprocess.Popen([
|
||||
gsexe,
|
||||
'-q', '-sDEVICE=pbmraw', '-dNOPAUSE', '-dBATCH', '-dSAFER',
|
||||
'-dFIXEDMEDIA', '-g384x543', '-r46.4441219158x46.4441219158',
|
||||
'-dFitPage', '-dFitPage',
|
||||
'-sOutputFile=-', '-'
|
||||
], executable=gsexe, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||
pbm_data, _ = gsproc.communicate(data_to_print)
|
||||
try:
|
||||
if gsproc.wait() == 0:
|
||||
info = server.path[1:]
|
||||
is_found = await server.printer.filter_device(info, server.settings.scan_time)
|
||||
if not is_found:
|
||||
... # TODO: Make IPP can report some errors
|
||||
raise Exception(f'No printer found with info: {info}')
|
||||
await server.printer.print_data(pbm_data)
|
||||
else:
|
||||
raise Exception('Error on invoking Ghostscript')
|
||||
server.send_response(200)
|
||||
server.send_header('Content-Type', 'application/ipp')
|
||||
server.end_headers()
|
||||
server.wfile.write(
|
||||
b'\x01\x01\x00\x00\x00\x00\x00\x01\x01\x03'
|
||||
)
|
||||
except Exception as _:
|
||||
server.send_response(500)
|
||||
server.send_header('Content-Type', 'application/ipp')
|
||||
server.end_headers()
|
||||
server.wfile.write(b'')
|
74
printer.py
74
printer.py
@ -9,11 +9,14 @@ from bleak import BleakClient, BleakScanner
|
||||
from bleak.exc import BleakError, BleakDBusError
|
||||
|
||||
try:
|
||||
from i18n import I18n
|
||||
from additional.i18n import I18n
|
||||
except ImportError:
|
||||
class I18n():
|
||||
'Dummy i18n in case "full" version is missing'
|
||||
|
||||
def __init__(self, _search_path=None, _lang=None, _fallback=None):
|
||||
pass
|
||||
|
||||
def __getitem__(self, keys):
|
||||
if not isinstance(keys, tuple):
|
||||
keys = (keys, )
|
||||
@ -21,9 +24,11 @@ except ImportError:
|
||||
|
||||
i18n = I18n('www/lang')
|
||||
|
||||
|
||||
class PrinterError(Exception):
|
||||
'Error of Printer driver'
|
||||
|
||||
|
||||
models = ('GT01', 'GB01', 'GB02', 'GB03')
|
||||
|
||||
crc8_table = [
|
||||
@ -75,7 +80,10 @@ def reverse_binary(value: int):
|
||||
return int(f"{bin(value)[2:]:0>8}"[::-1], 2)
|
||||
|
||||
|
||||
def make_command(command: int, payload: Union[bytes, bytearray], *, prefix: List[int]=None) -> bytearray:
|
||||
def make_command(
|
||||
command: int, payload: Union[bytes, bytearray], *,
|
||||
prefix: List[int] = None
|
||||
) -> bytearray:
|
||||
'Make a `bytearray` with command data, which can be sent to printer directly to operate'
|
||||
if len(payload) > 0x100:
|
||||
raise Exception('Too large payload')
|
||||
@ -164,40 +172,48 @@ class PrinterDriver():
|
||||
def _read_pbm(self, path: str = None, data: bytes = None):
|
||||
if path is not None and path != '-':
|
||||
file = open(path, 'rb')
|
||||
data = file.read()
|
||||
file.close()
|
||||
elif data is not None:
|
||||
file = io.BytesIO(data)
|
||||
pass
|
||||
else:
|
||||
file = sys.stdin.buffer
|
||||
signature = file.readline()
|
||||
if signature != b'P4\n':
|
||||
data = sys.stdin.buffer.read()
|
||||
if data[0:3] != b'P4\n':
|
||||
raise Exception('Specified file is not a PBM image')
|
||||
width, height = self.standard_width, 0
|
||||
# there can be several "chunks", by e.g. cat-ing several files, or ghostscript output
|
||||
chunks = data.split(b'P4\n')[1:]
|
||||
result = b''
|
||||
total_height = 0
|
||||
for chunk in chunks:
|
||||
page = io.BytesIO(chunk)
|
||||
while True:
|
||||
# There can be comments. Skip them
|
||||
line = file.readline()[0:-1]
|
||||
line = page.readline()[0:-1]
|
||||
if line[0:1] != b'#':
|
||||
break
|
||||
width, height = [int(x) for x in line.split(b' ')[0:2]]
|
||||
if width != self.standard_width:
|
||||
raise Exception('PBM image width is not 384px')
|
||||
total_height += height
|
||||
expected_data_size = self.pbm_data_per_line * height
|
||||
data = file.read()
|
||||
if path is not None and path != '-':
|
||||
file.close()
|
||||
data_size = len(data)
|
||||
raw_data = page.read()
|
||||
data_size = len(raw_data)
|
||||
if data_size != expected_data_size:
|
||||
raise Exception('Broken PBM file data')
|
||||
if self.dry_run:
|
||||
# Dry run: put blank data
|
||||
data = b'\x00' * expected_data_size
|
||||
return PBMData(width, height, data)
|
||||
result += b'\x00' * expected_data_size
|
||||
else:
|
||||
result += raw_data
|
||||
return PBMData(self.standard_width, total_height, result)
|
||||
|
||||
def _pbm_data_to_raw(self, data: PBMData):
|
||||
buffer = bytearray()
|
||||
# new/old print command
|
||||
if self.name == 'GB03':
|
||||
buffer.append(0x12)
|
||||
buffer += bytearray([0x51, 0x78, 0xa3, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff])
|
||||
buffer += bytearray([0x51, 0x78, 0xa3, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0xff])
|
||||
for key in data.args:
|
||||
buffer += make_command(key, data.args[key])
|
||||
buffer += make_command(
|
||||
@ -236,7 +252,7 @@ class PrinterDriver():
|
||||
)
|
||||
return buffer
|
||||
|
||||
async def send_buffer(self, buffer: bytearray, address: str=None):
|
||||
async def send_buffer(self, buffer: bytearray, address: str = None):
|
||||
'Send manipulation data (buffer) to the printer via bluetooth'
|
||||
address = address or self.address
|
||||
client = BleakClient(address, timeout=5.0)
|
||||
@ -267,6 +283,7 @@ class PrinterDriver():
|
||||
if device.name in models:
|
||||
result.append(device)
|
||||
return result
|
||||
|
||||
async def search_printer(self, timeout: int):
|
||||
'Search for a printer, returns `None` if not found'
|
||||
timeout = timeout or 3
|
||||
@ -275,20 +292,40 @@ class PrinterDriver():
|
||||
return devices[0]
|
||||
return None
|
||||
|
||||
async def print_file(self, path: str, address: str=None):
|
||||
async def print_file(self, path: str, address: str = None):
|
||||
'Method to print the specified PBM image at `path` with printer at specified MAC `address`'
|
||||
address = address or self.address
|
||||
pbm_data = self._read_pbm(path)
|
||||
buffer = self._pbm_data_to_raw(pbm_data)
|
||||
await self.send_buffer(buffer, address)
|
||||
|
||||
async def print_data(self, data: bytes, address: str=None):
|
||||
async def print_data(self, data: bytes, address: str = None):
|
||||
'Method to print the specified PBM image `data` with printer at specified MAC `address`'
|
||||
address = address or self.address
|
||||
pbm_data = self._read_pbm(None, data)
|
||||
buffer = self._pbm_data_to_raw(pbm_data)
|
||||
await self.send_buffer(buffer, address)
|
||||
|
||||
async def filter_device(self, info: str, timeout: float = 5.0) -> bool:
|
||||
'Find a suitable device with `info`: Bluetooth name or MAC address, or empty string'
|
||||
devices = await self.search_all_printers(timeout)
|
||||
if len(devices) == 0:
|
||||
return False
|
||||
if info in models:
|
||||
for device in devices:
|
||||
if device.name == info:
|
||||
self.name, self.address = device.name, device.address
|
||||
break
|
||||
elif info[2::3] == ':::::':
|
||||
for device in devices:
|
||||
if device.address.lower() == info.lower():
|
||||
self.name, self.address = device.name, device.address
|
||||
break
|
||||
else:
|
||||
device = devices[0]
|
||||
self.name, self.address = device.name, device.address
|
||||
return True
|
||||
|
||||
|
||||
async def _main():
|
||||
'Main routine for direct command line execution'
|
||||
@ -335,6 +372,7 @@ async def _main():
|
||||
await printer.print_file(cmdargs.file)
|
||||
print(i18n['finished'])
|
||||
|
||||
|
||||
async def main():
|
||||
'Run the `_main` routine while catching exceptions'
|
||||
try:
|
||||
|
@ -15,21 +15,36 @@ Gegenwärtig:
|
||||
|
||||
## Funktionen
|
||||
|
||||
*Derzeit befindet sich die Software im Alpha-Stadium. Mehr wird es bald geben!*
|
||||
|
||||
| Available | Partial | Planned |
|
||||
|-----------------|-----------|---------------|
|
||||
| Web Interface | CUPS/IPP* | Visual Editor |
|
||||
| Print a Picture | | Help/Manual |
|
||||
| Command-line | | Text Printing |
|
||||
|
||||
<!-- May comment the line below if there are none -->
|
||||
\* In development code. Will be released in a short period.
|
||||
|
||||
*Along with…*
|
||||
|
||||
- Simple!
|
||||
- Bedienung über eine Web-UI direkt im Browser,
|
||||
- oder besorgen Sie sich die Android-Version!
|
||||
- ~~Umfangreiche Funktionen~~
|
||||
- Derzeit befindet sich die Software im Alpha-Stadium. Mehr wird es bald geben!
|
||||
|
||||
- Friendly!
|
||||
- Sprachunterstützung! Sie können sich an der Übersetzung beteiligen!
|
||||
- Gute Benutzeroberfläche, mit PC-/Mobil-/Licht-/Dunkelmodus-Varianten! (Systemkonfiguration adaptiv)
|
||||
|
||||
- Plattformübergreifend!
|
||||
- Neuere Windows 10 und darüber
|
||||
- GNU/Linux
|
||||
- MacOS *(muss getestet werden*
|
||||
- und eine Menge zusätzlicher Anstrengungen für Android!
|
||||
|
||||
- Frei, wie in [freedom](https://www.gnu.org/philosophy/free-sw.html)!
|
||||
- Anders als die "offizielle" proprietäre App, ist dieses Projekt für alle, denen *offener Geist und Freiheit* wichtig sind!
|
||||
|
||||
- und Fun!
|
||||
- Mach, was du willst!
|
||||
|
||||
@ -92,7 +107,7 @@ Siehe Datei `COPYING`, `LICENSE` und Details zum verwendeten JavaScript in der D
|
||||
|
||||
## Development
|
||||
|
||||
Vielleicht sind Sie ohnehin an der Sprachunterstützung interessiert. Siehe die Übersetzungsdateien im Verzeichnis `www/lang`!
|
||||
Vielleicht sind Sie ohnehin an der Sprachunterstützung interessiert. Siehe die Übersetzungsdateien im Verzeichnis `www/lang` und `readme.i18n`!
|
||||
|
||||
Interessieren Sie sich auch für Code-Entwicklung? Siehe [development.md](development.md)!
|
||||
|
@ -15,21 +15,36 @@
|
||||
|
||||
## 特性
|
||||
|
||||
*当前仍在继续开发。以后会有更多!*
|
||||
|
||||
| 可用 | 部分 | 计划 |
|
||||
|-----------|-----------|---------------|
|
||||
| 网页界面 | CUPS/IPP* | 可视化编辑器 |
|
||||
| 打印图片 | | 帮助/文档 |
|
||||
| 命令行 | | 文本打印 |
|
||||
|
||||
<!-- 若没有 *,可注释下一句 -->
|
||||
\* 存在于开发代码中。将在短时间内发布。
|
||||
|
||||
*当然还有……*
|
||||
|
||||
- 简易!
|
||||
- 在网页界面进行操作,
|
||||
- 或者获取安卓应用!
|
||||
- ~~功能丰富~~
|
||||
- 当前仍在继续开发。以后会有更多!
|
||||
|
||||
- 友好!
|
||||
- 语言支持!您可参与翻译!
|
||||
- 良好的用户界面,可适应桌面/移动端/明暗主题!
|
||||
|
||||
- 跨平台!
|
||||
- 较新的 Windows 10 及以上
|
||||
- GNU/Linux
|
||||
- MacOS *(需要测试)*
|
||||
- 在安卓上也花了些功夫呢!
|
||||
|
||||
- 是[自由软件](https://www.gnu.org/philosophy/free-sw.html)!
|
||||
- 不像“原版”专有应用,此作品为在乎*开放思想与计算自由*的人而生!
|
||||
|
||||
- 有意思!
|
||||
- 做什么都可以!
|
||||
|
||||
@ -97,19 +112,20 @@ Copyright © 2022 NaitLee Soft. 保留一些权利。
|
||||
|
||||
## 开发
|
||||
|
||||
您可能对翻译工作感兴趣。可于目录 `www/lang` 中查看翻译文件!
|
||||
您可能对翻译工作感兴趣。可于目录 `www/lang` 和 `readme.i18n` 中查看翻译文件!
|
||||
|
||||
注:
|
||||
1. 通常英语与简体中文同时更新。请考虑其他,如繁体中文(需注意在繁体中与简体的用字、技术术语差别)。
|
||||
2. 如果您有(真的)能力,您也可以纠正/改善某些翻译!
|
||||
2. 如果(真的)有能力,您也可以纠正/改善某些翻译!
|
||||
|
||||
还想写代码?看看 [development.md](development.md)!(英文)
|
||||
|
||||
### 鸣谢
|
||||
|
||||
- 当然不能没有 Python 和 Web 技术!
|
||||
- [Bleak](https://bleak.readthedocs.io/en/latest/) 蓝牙低功耗库,牛!
|
||||
- [roddeh-i18n](https://github.com/roddeh/i18njs),好活!
|
||||
- [Bleak](https://bleak.readthedocs.io/en/latest/) 跨平台蓝牙低功耗库,牛!
|
||||
- [roddeh-i18n](https://github.com/roddeh/i18njs),很好!
|
||||
- [python-for-android](https://python-for-android.readthedocs.io/en/latest/),虽然有些麻烦的地方
|
||||
- [AdvancedWebView](https://github.com/delight-im/Android-AdvancedWebView) 从 Java 拯救了我的生命
|
||||
- Stack Overflow 和互联网,你们让我无中生有地了解了安卓“活动” `Activity`
|
||||
- Stack Overflow 和整个互联网,你们让我从零开始了解了安卓“活动” `Activity`
|
||||
- ……每个人都是好样的!
|
40
server.py
40
server.py
@ -34,9 +34,6 @@ class PrinterServerError(Exception):
|
||||
if len_args > 1:
|
||||
self.details = args[1]
|
||||
|
||||
Printer = PrinterDriver()
|
||||
server = None
|
||||
|
||||
def log(message):
|
||||
'For logging a message'
|
||||
print(message)
|
||||
@ -66,6 +63,8 @@ class PrinterServer(BaseHTTPRequestHandler):
|
||||
'frequency': 0.8,
|
||||
'dry_run': False
|
||||
})
|
||||
printer = PrinterDriver()
|
||||
ipp = None
|
||||
def log_request(self, _code=200, _size=0):
|
||||
pass
|
||||
def log_error(self, *_args):
|
||||
@ -126,22 +125,23 @@ class PrinterServer(BaseHTTPRequestHandler):
|
||||
'Save config file'
|
||||
with open(self.settings.config_path, 'w', encoding='utf-8') as file:
|
||||
json.dump(self.settings, file, indent=4)
|
||||
def update_printer(self):
|
||||
'Update `PrinterDriver` state/config'
|
||||
self.printer.dry_run = self.settings.dry_run
|
||||
self.printer.frequency = float(self.settings.frequency)
|
||||
if self.settings.printer is not None:
|
||||
self.printer.name, self.printer.address = self.settings.printer.split(',')
|
||||
def handle_api(self):
|
||||
'Handle API request from POST'
|
||||
content_length = int(self.headers.get('Content-Length'))
|
||||
body = self.rfile.read(content_length)
|
||||
api = self.path[1:]
|
||||
if api == 'print':
|
||||
if self.settings.printer is None:
|
||||
# usually can't encounter, though
|
||||
raise PrinterServerError('No printer address specified')
|
||||
Printer.dry_run = self.settings.dry_run
|
||||
Printer.frequency = float(self.settings.frequency)
|
||||
Printer.name, Printer.address = self.settings.printer.split(',')
|
||||
self.update_printer()
|
||||
loop = asyncio.new_event_loop()
|
||||
try:
|
||||
devices = loop.run_until_complete(
|
||||
Printer.print_data(body)
|
||||
self.printer.print_data(body)
|
||||
)
|
||||
self.api_success()
|
||||
finally:
|
||||
@ -152,7 +152,7 @@ class PrinterServer(BaseHTTPRequestHandler):
|
||||
loop = asyncio.new_event_loop()
|
||||
try:
|
||||
devices = loop.run_until_complete(
|
||||
Printer.search_all_printers(float(self.settings.scan_time))
|
||||
self.printer.search_all_printers(float(self.settings.scan_time))
|
||||
)
|
||||
finally:
|
||||
loop.close()
|
||||
@ -196,6 +196,23 @@ class PrinterServer(BaseHTTPRequestHandler):
|
||||
self.send_header('Content-Type', mime('txt'))
|
||||
self.end_headers()
|
||||
return
|
||||
if self.headers.get('Content-Type') == 'application/ipp':
|
||||
if self.ipp is None:
|
||||
try:
|
||||
from additional.ipp import IPP
|
||||
self.load_config()
|
||||
except ImportError:
|
||||
# TODO: Better response?
|
||||
return
|
||||
self.ipp = IPP(self, self.printer)
|
||||
self.update_printer()
|
||||
body = self.rfile.read(content_length)
|
||||
loop = asyncio.new_event_loop()
|
||||
try:
|
||||
loop.run_until_complete(self.ipp.handle_ipp(body))
|
||||
finally:
|
||||
loop.close()
|
||||
return
|
||||
try:
|
||||
self.handle_api()
|
||||
return
|
||||
@ -231,7 +248,6 @@ def serve():
|
||||
if '-a' in sys.argv:
|
||||
print('Will listen on ALL addresses')
|
||||
listen_all = True
|
||||
global server
|
||||
# Again, Don't use ThreadingHTTPServer if you're going to use pyjnius!
|
||||
server = HTTPServer(('' if listen_all else address, port), PrinterServer)
|
||||
service_url = f'http://{address}:{port}/'
|
||||
|
Loading…
x
Reference in New Issue
Block a user