Skip to content

Commit

Permalink
Flash RFID readers from admin panel (#42)
Browse files Browse the repository at this point in the history
* Automatic RFID reader code reworked and refined.

Also some bug fixes etc...

* Fix pylint
  • Loading branch information
leechwort committed Dec 18, 2023
1 parent 7dca0cb commit e737cb3
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 186 deletions.
6 changes: 0 additions & 6 deletions app/api/web_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,3 @@ def api_update_settings():
except Exception as e:
app.logger.error("Error updating settings: %s", e)
raise Exception("Error updating settings") from e

# websocket = Sock(app)
# @websocket.route('/updater_socket')
# def updater(websocket):
# # pylint: disable=redefined-outer-name
# update_firmware_full(websocket)
13 changes: 11 additions & 2 deletions app/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
login_required,
current_user,
)
from flask_sock import Sock
from pyee.base import EventEmitter

from api.device_api import device_api
from api.web_api import web_api
from models.admin_user import AdminUser
from plugins.slack_notifier import SlackNotifierPlugin
from utils.fimware_updater import firmware_updater_route

app = Flask(__name__)
app.ee = EventEmitter()
Expand All @@ -27,8 +28,11 @@
login_manager = LoginManager()
login_manager.init_app(app)

websocket = Sock(app)


# Plugins
slack_notifier = SlackNotifierPlugin(app.app_context())
# slack_notifier = SlackNotifierPlugin(app.app_context())

connection = sqlite3.connect(app.config["DATABASE_URI"])

Expand Down Expand Up @@ -128,3 +132,8 @@ def logs():
@login_required
def settings():
return render_template("prismo/settings.html")


@websocket.route('/reader_flasher')
def updater(socket):
firmware_updater_route(socket)
25 changes: 25 additions & 0 deletions app/config_debug.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"DEBUG": false,
"TESTING": false,
"SECRET_KEY": "secret_key",
"USE_X_SENDFILE": false,
"APPLICATION_ROOT": "/",
"SESSION_COOKIE_NAME": "session",
"SESSION_COOKIE_HTTPONLY": true,
"SESSION_COOKIE_SECURE": false,
"SESSION_REFRESH_EACH_REQUEST": true,
"TRAP_HTTP_EXCEPTIONS": false,
"EXPLAIN_TEMPLATE_LOADING": false,
"PREFERRED_URL_SCHEME": "http",
"MAX_COOKIE_SIZE": 4093,
"DATABASE_URI": "file:database.db",
"PRISMO": {
"READER_FIRMWARE_FLASHING_SCRIPT_PATH": "/path/to/reader/firmware/src/flasher.sh",
"CURRENT_CONFIG_FILE": "config_debug.json",
"NOTIFIER": {
"CURRENT_NOTIFIER": "SLACK",
"SLACK_CHANNEL": "#prismo-debug",
"SLACK_TOKEN": "xoxb-THIS-ISNOTAREAL-SLACKTOKEN"
}
}
}
2 changes: 1 addition & 1 deletion app/models/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_authorized_users(cls, device_id):

# Fetch authorized users for the given device
cursor.execute(
"SELECT users.key FROM users INNER JOIN permissions"
"SELECT users.key FROM users INNER JOIN permissions "
"ON users.key = permissions.user_key WHERE permissions.device_id = ?",
(device_id,),
)
Expand Down
11 changes: 0 additions & 11 deletions app/static/js/application.js

This file was deleted.

131 changes: 131 additions & 0 deletions app/static/js/devices.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// Global: Device ID, which is pending for update
let deviceIDForUpdate = null;

function flashFirmware() {
console.log("Flashing device: ", deviceIDForUpdate);
const socket = new WebSocket("ws://" + location.host + "/reader_flasher");
const logContainer = document.getElementById("log-container");

let progress = 0;

socket.addEventListener("open", () => {
console.log(
"WebSocket connection established, send device id for flashing",
);
socket.send(deviceIDForUpdate);
});
function log(data) {
const obj = JSON.parse(data);
logContainer.innerHTML += `<span>${obj.text}</span><br>`;

// Update progress bar
document.querySelector(".progress-bar").style.width = `${obj.progress}%`;
document.getElementById("statusText").innerText = `${obj.status}`;
}

function toggleLog() {
logContainer.style.display =
logContainer.style.display === "block" ? "none" : "block";
}

socket.addEventListener("message", (ev) => {
log(ev.data);
});
}

fetch("/api/devices")
.then((response) => response.json())
.then((data) => generateAccordionItems(data))
.catch((error) => console.error("Error fetching data:", error));

function generateAccordionItems(devices) {
const accordionItemsHTML = [];
for (const device of devices) {
const accordionItemHTML = `
<div class="accordion-item">
<h2 class="accordion-header">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapse-${device.id}" aria-expanded="false" aria-controls="flush-collapse-${device.id}">
<i class="bi bi-phone-vibrate-fill"></i> | ${device.name}
</button>
</h2>
<div id="flush-collapse-${device.id}" class="accordion-collapse collapse" data-bs-parent="#accordionFlushExample">
<div class="accordion-body">
<div class="d-flex justify-content-between align-items-center">
<div class="me-3">
Device id: ${device.id}, Device type: ${device.type}
</div>
<div>
<button type="button" class="btn btn-primary me-3" data-bs-toggle="modal" data-bs-target="#flashDeviceModal" onclick="deviceIDForUpdate='${device.id}'">Flash Connected Device</button>
<button type="button" class="btn btn-danger" onclick="removeDevice('${device.id}')">Remove Device</button>
</div>
</div>
</div>
</div>
</div>
`;
accordionItemsHTML.push(accordionItemHTML);
}
const devicesListElement = document.getElementById("devicesList");
devicesListElement.innerHTML = accordionItemsHTML.join("");
}

function addDevice(deviceName) {
// Generate random UUID for device ID
const deviceId = crypto.randomUUID();
// Prepare device data
const deviceData = {
device_name: deviceName,
device_id: deviceId,
device_type: "tool",
};
// Make API call to add device
fetch("/api/devices", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(deviceData),
})
.then((response) => {
// Check if response status code is 201 (Created)
if (response.status === 201) {
alert("Device added successfully!");
refreshDevicesList();
} else {
alert("Error adding device. Please try again later.");
}
})
.catch((error) => {
console.error("Error adding device:", error);
alert("Error adding device. Please try again later.");
});
}

function removeDevice(deviceId) {
fetch(`/api/devices/${deviceId}`, {
method: "DELETE",
})
.then((response) => {
if (response.status === 200) {
alert("Device removed successfully!");
refreshDevicesList();
} else {
alert("Error removing device. Please try again later.");
}
})
.catch((error) => {
console.error("Error removing device:", error);
alert("Error removing device. Please try again later.");
});
}

function refreshDevicesList() {
fetch("/api/devices")
.then((response) => response.json())
.then((data) => generateAccordionItems(data))
.catch((error) => console.error("Error fetching data:", error));
}
1 change: 0 additions & 1 deletion app/templates/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/intro.js"></script>
<script src="static/js/rfid.js"></script>
<script src="static/js/application.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/intro.js/2.7.0/introjs.css">
Expand Down
Loading

0 comments on commit e737cb3

Please sign in to comment.