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

Switch config file format to toml and move it to $HOME/.config/nfc2klipper #18

Merged
merged 2 commits into from
Jan 26, 2025
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8", "3.9", "3.10"]
python-version: ["3.8", "3.9", "3.10", "3.11"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ virtualenv venv
venv/bin/pip3 install -r requirements.txt
```

Update the config in `nfc2klipper-config.json5`.
Copy and update the `nfc2klipper.cfg` to `~/.config/nfc2klipper/nfc2klipper.cfg`.

## Preparing an NFC reader

Expand Down Expand Up @@ -115,7 +115,7 @@ where `mainsailos.local` should be replaced with the computer's name (or IP addr
The program uses a development web server with **no security** at all so it
shouldn't be run if the computer is running on an untrusted network.

The program has a configuration file (nfc2klipper-config.json5) for
The program has a configuration file (`~/.config/nfc2klipper/nfc2klipper.cfg`) for
enabling the web server, setting the port number, addresses to moonraker
and mainsail, the webserver's address and NFC device to use.

Expand Down
2 changes: 1 addition & 1 deletion REUSE.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ SPDX-PackageSupplier = "Sebastian Andersson <[email protected]>"
SPDX-PackageDownloadLocation = "https://github.com/bofh69/nfc2klipper"

[[annotations]]
path = [".github/**", "requirements.txt", ".gitignore", "nfc2klipper.service", "nfc2klipper-config.json5"]
path = [".github/**", "requirements.txt", ".gitignore", "nfc2klipper.service", "nfc2klipper.cfg"]
precedence = "aggregate"
SPDX-FileCopyrightText = "$YEAR $NAME <$CONTACT>"
SPDX-License-Identifier = "CC0-1.0"
23 changes: 0 additions & 23 deletions nfc2klipper-config.json5

This file was deleted.

27 changes: 27 additions & 0 deletions nfc2klipper.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
[webserver]
# The web server is a experimental feature.
# If turned on, don't let it be accessed from internet or untrusted
# networks.
disable_web_server = true

# The address the web server listens to,
# use 0.0.0.0 for all IPv4
web_address = "0.0.0.0"
# The port the web server listens to
web_port = 5001

[nfc]
# Which NFC reader to use, see
# https://nfcpy.readthedocs.io/en/latest/topics/get-started.html#open-a-local-device
nfc-device = "ttyAMA0"

[spoolman]
# URL for the spoolman installation
spoolman-url = "http://mainsailos.local:7912"

[moonraker]
# URL for the moonraker installation
moonraker-url = "http://mainsailos.local"

# If true, clears the spool & filament info if no tag can be read.
clear-spool = false
63 changes: 48 additions & 15 deletions nfc2klipper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
"""Program to set current filament & spool in klipper, and write to tags. """

import logging
import threading
import os
import sys
import shutil
import threading
from pathlib import Path

from flask import Flask, render_template
import json5
import toml

from lib.moonraker_web_client import MoonrakerWebClient
from lib.nfc_handler import NfcHandler
Expand All @@ -20,18 +23,39 @@
FILAMENT = "FILAMENT"
NDEF_TEXT_TYPE = "urn:nfc:wkt:T"

script_dir = os.path.dirname(__file__)
cfg_filename = os.path.join(script_dir, "nfc2klipper-config.json5")
with open(cfg_filename, "r", encoding="utf-8") as fp:
args = json5.load(fp)
CFG_DIR = "~/.config/nfc2klipper"

logging.basicConfig(
level=logging.DEBUG, format="%(asctime)s %(levelname)s - %(name)s: %(message)s"
)

spoolman = SpoolmanClient(args["spoolman-url"])
moonraker = MoonrakerWebClient(args["moonraker-url"])
nfc_handler = NfcHandler(args["nfc-device"])
args = None # pylint: disable=C0103
for path in ["~/nfc2klipper.cfg", CFG_DIR + "/nfc2klipper.cfg"]:
cfg_filename = os.path.expanduser(path)
if os.path.exists(cfg_filename):
with open(cfg_filename, "r", encoding="utf-8") as fp:
args = toml.load(fp)
break

if not args:
print(
"WARNING: The config file is missing, installing a default version.",
file=sys.stderr,
)
if not os.path.exists(CFG_DIR):
cfg_dir = os.path.expanduser(CFG_DIR)
print(f"Creating dir {cfg_dir}", file=sys.stderr)
Path(cfg_dir).mkdir(parents=True, exist_ok=True)
script_dir = os.path.dirname(__file__)
from_filename = os.path.join(script_dir, "nfc2klipper.cfg")
to_filename = os.path.join(cfg_dir, "nfc2klipper.cfg")
shutil.copyfile(from_filename, to_filename)
print(f"Created {to_filename}, please update it", file=sys.stderr)
sys.exit(1)

spoolman = SpoolmanClient(args["spoolman"]["spoolman-url"])
moonraker = MoonrakerWebClient(args["moonraker"]["moonraker-url"])
nfc_handler = NfcHandler(args["nfc"]["nfc-device"])


app = Flask(__name__)
Expand Down Expand Up @@ -89,13 +113,20 @@ def index():
return render_template("index.html", spools=spools)


def should_clear_spool() -> bool:
"""Returns True if the config says the spool should be cleared"""
if args["moonraker"].get("clear_spool"):
return True
return False


def on_nfc_tag_present(spool, filament):
"""Handles a read tag"""

if not args.get("clear_spool"):
if not should_clear_spool():
if not (spool and filament):
app.logger.info("Did not find spool and filament records in tag")
if args.get("clear_spool") or (spool and filament):
if should_clear_spool() or (spool and filament):
if not spool:
spool = 0
if not filament:
Expand All @@ -105,28 +136,30 @@ def on_nfc_tag_present(spool, filament):

def on_nfc_no_tag_present():
"""Called when no tag is present (or tag without data)"""
if args.get("clear_spool"):
if should_clear_spool():
set_spool_and_filament(0, 0)


if __name__ == "__main__":

if args.get("clear_spool"):
if should_clear_spool():
# Start by unsetting current spool & filament:
set_spool_and_filament(0, 0)

nfc_handler.set_no_tag_present_callback(on_nfc_no_tag_present)
nfc_handler.set_tag_present_callback(on_nfc_tag_present)

if not args.get("disable_web_server"):
if not args["webserver"].get("disable_web_server"):
app.logger.info("Starting nfc-handler")
thread = threading.Thread(target=nfc_handler.run)
thread.daemon = True
thread.start()

app.logger.info("Starting web server")
try:
app.run(args["web_address"], port=args["web_port"])
app.run(
args["webserver"]["web_address"], port=args["webserver"]["web_port"]
)
except Exception:
nfc_handler.stop()
thread.join()
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
flask==3.0.3
json5==0.9.25
toml==0.10.2
nfcpy==1.0.4
npyscreen==4.10.5
requests==2.32.3
Loading