Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build static site from documentation #11

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Build documentation
on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install python
uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Setup cache
uses: actions/cache@v2
with:
key: ${{ github.ref }}
path: .cache
- name: Setup dependencies
run: pip install -r docs/requirements.txt
- name: Build docs
run: mkdocs build --strict
- name: Upload artifact
uses: actions/upload-pages-artifact@v1
with:
path: ./site
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# niimprint
An open-source library and client for Niimbot printers

### Fork changelog & differences from original version

- Tested on Niimbot B1, B18, B21, D11, D110 and Python 3.11
- Added transport abstraction: switch between bluetooth and USB (serial)
- Disabled checksum calculation for image encoding (works fine without it so far)
- Switched to [click](https://click.palletsprojects.com/) CLI library instead of argparse
- Integrated [pyproject.toml](https://pip.pypa.io/en/stable/reference/build-system/pyproject-toml/) and [poetry](https://python-poetry.org)
- Integrated [pre-commit](https://pre-commit.com/) and [ruff](https://docs.astral.sh/ruff/), re-formatted all files
- Miscellaneous refactoring / file renaming / etc.

## Installation and usage

Check out [**documentation**](https://andbondstyle.github.io/niimprint/).

## Licence

[MIT](https://choosealicense.com/licenses/mit/). Originally developed by [kjy00302](https://github.com/kjy00302), forked & enhanced by [AndBondStyle](https://github.com/AndBondStyle)
22 changes: 22 additions & 0 deletions docs/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
hide:
- navigation
---

## Image orientation

Generally, the image comes out of the printer with the same orientation you see it on your screen.
You can have your input image rotated as you like, but adjust its orientation by passing `-r <...>` flag.

See the image below for clarification.

[![](./img/image_orientation.png)]()

<!-- Excalidraw link: https://excalidraw.com/#json=vYHMBohMn5GeB-5M6SNch,TsxRmh_WKUfzYjL183FGfg -->

## Image resolution

As far as we've tested, Niimbot printers have **8 pixels per mm** (~203 dpi) resolution. The CLI prints the image you provided as-is, without any checks of the actual label size, so be careful. However the script will check if the image width is too big for selected printer. The maximum width in pixels is usually slightly less than specified maximum width in mm:

- **B21, B1, B18**: max 384 pixels (almost equal to 50 mm * 8 px/mm = 400)
- **D11**: max 96 pixels (almost equal to 15 mm * 8 px/mm = 120)
24 changes: 24 additions & 0 deletions docs/hardware.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
hide:
- navigation
---

# Supported printers

- D11
- D110
- B21
- B1
- B18

# Tapes

=== "D11 / D110"

| Tape type | Printable dimensions (mm) | Pixels | Notes |
|-----------|---------------------------|--------|-------------|
| T14*22 | 13.5×21.5 | 96*172 | |
| T12*22 | 11.5×21.5 | 94*168 | |
| T12*30 | 11.7×29.8 | 94*228 | |
| TT14*50 | 13.9×49.9 | 96*380 | Transparent |
| T14*40 | 12x32 | 96*228 | «Bubble B» |
File renamed without changes
File renamed without changes
File renamed without changes
66 changes: 66 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
hide:
- navigation
- toc
---

# Niimbot Printer Client

## Installation

Recommended method is to use [poetry](https://python-poetry.org) and install with `poetry install`.
However `requirements.txt` is also provided for convenience.

Project is tested on Python 3.11, but should work on other versions.

## Usage

Just run `niimprint --help`

### Print and tape notes

* `TT14*50` is prone to overfeeding. Roll it for 1.5mm back after each printed label.
* «Bubble B» stickers have variable dimensions and colors (green, blue, teal, pink, yellow — in that order).
Be careful with layouts.
* Almost all stickers have rounded corners, count it when designing layouts.
* Note that different print densities will vary the pixel size, so count at least 2-5 pixels from the edges
to avoid clipping.
* **Always** use good dithering (Floyd-Steinberg, Sierra, Burkes) for grayscale images.

## Examples

### B21, USB connection, 30x15 mm (240x120 px) label

```
python niimprint -c usb -a /dev/ttyACM0 -r 90 -i examples/B21_30x15mm_240x120px.png
```

![](./img/B21_30x15_result.png)

### B21, Bluetooth connection, 80x50 mm (640x384 px) label

```
python niimprint -c bluetooth -a "E2:E1:08:03:09:87" -r 90 -i examples/B21_80x50mm_640x384px.png
```

![](./img/B21_80x50_result.png)


## USB connection

For USB connection, you can omit the `--addr` argument and let the script auto-detect the serial port.
However, it will fail if there're multiple available ports.

On linux, serial ports can be found at `/dev/ttyUSB*`, `/dev/ttyACM*` or `/dev/serial/*`.
On windows, they will be named like `COM1`, `COM2` etc. Check the device manager to choose the correct one.

## Bluetooth connection

It seems like B21 (and maybe other models?) has two bluetooth addresses.
For me, they start with `C2:E1` and `E2:E1` respectively.

!!! warning "Double-check bluetooth address"

Connection works only if you disconnect from `C2:E1` and connect to `E2:E1`.

Also after connecting to `E2:E1` via bluetoothctl I always get `org.bluez.Error.NotAvailable br-connection-profile-unavailable` error, but printing works fine regardless.
68 changes: 68 additions & 0 deletions docs/protocol.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
hide:
- navigation
---

## Packet structure

Niimbot uses simple TLV packet with preamble, postamble and checksum.

Every field of packet uses big endian.

|5555|c2|01|02|c1|aaaa|
│ │ │ │ │ └ Postamble (constant)
│ │ │ │ └─── Checksum (xor sum of type, length and value)
│ │ │ └────── Value
│ │ └───────── Length (of data)
│ └──────────── Type
└───────────────── Preamble (constant)

## Line encoding packets
Niimbot uses three types of packet to print image.

All three packet type has repeat count. So, repetition of same data can be reduced to one packet.

Currently niimprint's encoder only uses line packet without optimization.

_(Common packet fields are omitted for clarity.)_

### Blank packet
Blank packet (packet type 0x84) encodes blank line.

|5555|84|03|0000|0a|8d|aaaa|
│ └ Repeat count
└───── Line count

This packet will print 10 blank lines.

### Line packet
line packet (packet type 0x85) encodes line as bitmap.

|5555|85|12|000a|00|01|0f|02|0000000000000001fffe0000|91|aaaa
│ │ │ │ │ └ Bitmap data
│ │ │ │ └─── Repeat count
│ │ │ └────── Pixel count (right) (bit count of 0x00000000)
│ │ └───────── Pixel count (middle) (bit count of 0x00000001)
│ └──────────── Pixel count (left) (bit count of 0xfffe0000)
└───────────────── Line count

This packet will print 2 bitmap lines.

### Points packet
points packet (packet type 0x83) encodes line as array of 1D points.

5555|83|0e|000c|00|01|03|07|003f0040004d004e|f8|aaaa|
│ │ │ │ │ └ Point data (0x003f, 0x0040, 0x004d, 0x004e)
│ │ │ │ └─── Repeat count
│ │ │ └────── Pixel count (right)
│ │ └───────── Pixel count (middle)
│ └──────────── Pixel count (left)
└───────────────── Line count

This packet will print 7 lines with points.

### Todo

!!! question

How does B21 encodes more then 96 pixels?
5 changes: 5 additions & 0 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
cairosvg~=2.7.1
mkdocs-material~=9.4.14
mkdocs-minify-plugin~=0.7.1
pillow~=10.1.0

120 changes: 120 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
site_name: niimprint
site_url: https://orhideous.github.io/niimprint
edit_uri: blob/main/docs/ # Change the master branch to main as we are using main as a main branch
site_author: niimprint authors
site_description: >-
Python app for Niimbot label printers.

# Repository
repo_name: orhideous/niimprint
repo_url: https://github.com/orhideous/niimprint

# Copyright
copyright: Copyright &copy; 2024 niimprint authors

# Configuration
theme:
name: material
features:
- announce.dismiss
- content.action.edit
- content.action.view
- content.code.annotate
- content.code.copy
# - content.tabs.link
- content.tooltips
# - header.autohide
# - navigation.expand
- navigation.footer
- navigation.indexes
# - navigation.instant
# - navigation.prune
- navigation.sections
- navigation.tabs
# - navigation.tabs.sticky
- navigation.top
- navigation.tracking
- search.highlight
- search.share
- search.suggest
- toc.follow
# - toc.integrate
palette:
- scheme: default
primary: white
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
toggle:
icon: material/brightness-4
name: Switch to light mode
font:
text: Roboto
code: Roboto Mono
favicon: assets/favicon.png

# Plugins
plugins:
- search:
separator: '[\s\-,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])'
- minify:
minify_html: true
- social: {}

# Customization
extra:
annotate:
json: [.s2]
social:
- icon: fontawesome/brands/github
link: https://github.com/orhideous/niimprint

# Extensions
markdown_extensions:
- abbr
- admonition
- attr_list
- def_list
- footnotes
- md_in_html
- toc:
permalink: true
- pymdownx.arithmatex:
generic: true
- pymdownx.betterem:
smart_enable: all
- pymdownx.caret
- pymdownx.details
- pymdownx.emoji:
emoji_generator: !!python/name:material.extensions.emoji.to_svg
emoji_index: !!python/name:material.extensions.emoji.twemoji
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.keys
- pymdownx.magiclink:
repo_url_shorthand: true
user: squidfunk
repo: mkdocs-material
- pymdownx.mark
- pymdownx.smartsymbols
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.tilde

# Page tree
nav:
- Home: index.md
- FAQ: faq.md
- Printers & Tapes: hardware.md
- Protocol: protocol.md
Loading