Compare commits
5 Commits
0c9f1a8780
...
18c4eba49c
Author | SHA1 | Date | |
---|---|---|---|
18c4eba49c | |||
bb60ed7a0c | |||
64d211d9e8 | |||
de33aa514b | |||
c2d722c12e |
45
.gitea/workflows/sonar.yaml
Normal file
45
.gitea/workflows/sonar.yaml
Normal file
@ -0,0 +1,45 @@
|
||||
# Name of the workflow, visible in the Gitea Actions UI
|
||||
name: Sonar analyzer
|
||||
|
||||
# Defines the events that trigger this workflow
|
||||
on:
|
||||
# Trigger on pushes to the 'master' branch
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
# Definition of the jobs to be executed in the workflow
|
||||
jobs:
|
||||
# Define the 'build' job
|
||||
build:
|
||||
# Name displayed for the job in the Gitea Actions UI
|
||||
name: Sonar analyzer
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Definition of the steps within the 'build' job
|
||||
steps:
|
||||
# Step to checkout the repository code
|
||||
# fetch-depth: 0 is important for SonarQube to analyze the full history
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
# Step to run the SonarQube scan action
|
||||
# This action handles the SonarQube scanner execution within a container
|
||||
- name: Analyze with SonarQube
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
# Environment variables required by the SonarQube scan action
|
||||
env:
|
||||
# SONAR_TOKEN and SONAR_HOST_URL must be configured as secrets in your Gitea repository
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
|
||||
|
||||
# Optional step: Check the Quality Gate status
|
||||
# Uncomment these lines if you want the job to fail if the Quality Gate is red.
|
||||
# This is common practice to prevent merging/deploying code that doesn't meet quality standards.
|
||||
- name: Wait for Quality Gate status
|
||||
uses: SonarSource/sonarqube-quality-gate-action@v1
|
||||
timeout-minutes: 5 # Maximum time to wait for the Quality Gate status
|
||||
env:
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
12
.gitignore
vendored
12
.gitignore
vendored
@ -1,7 +1,7 @@
|
||||
/dist/
|
||||
*/dist/
|
||||
/.idea/
|
||||
/node_modules
|
||||
/public/images/
|
||||
/config.json
|
||||
/yarn-error.log
|
||||
/docs/
|
||||
*node_modules
|
||||
/server/public/images/
|
||||
*config.json
|
||||
*yarn-error.log
|
||||
/server/docs/
|
||||
|
2
DOCME.md
2
DOCME.md
@ -8,5 +8,5 @@ Hier befinden sich Methoden und Klassen vom iTender, von Web-Client, über die W
|
||||
|
||||
Die Bedienung dieser Dokumentation erscheint anfangs vielleicht holprig, allerdings ist sie leichter als gedacht.
|
||||
|
||||
Du willst vermutlich hier hin ->
|
||||
Du willst vermutlich hier hin →
|
||||
[iTender Klasse](classes/iTender.iTender.html)
|
@ -1,8 +0,0 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
]
|
||||
}
|
@ -1,103 +1,337 @@
|
||||
/**
|
||||
* Official proxy code for iTender GPIO Communication
|
||||
**/
|
||||
#include <ArduinoJson.h>
|
||||
#include "HX711.h"
|
||||
* @file itender.ino
|
||||
* @brief Official proxy code for iTender GPIO Communication via Serial.
|
||||
*
|
||||
* This code acts as a communication bridge between an Arduino and a Raspberry Pi
|
||||
* using JSON over a serial connection (USB). It allows the Raspberry Pi to
|
||||
* control Arduino GPIO pins (set digital/analog output, get digital/analog input)
|
||||
* and read sensor data (specifically from multiple HX711 load cells dynamically).
|
||||
*/
|
||||
|
||||
// Define the size of the JSON buffer
|
||||
#include <ArduinoJson.h> // Include the ArduinoJson library for JSON parsing and serialization.
|
||||
#include "HX711.h" // Include the HX711 library for interacting with the load cell amplifier.
|
||||
|
||||
// Define the size of the JSON buffer for incoming messages.
|
||||
// Adjust this size based on the maximum expected size of incoming JSON messages.
|
||||
#define JSON_BUFFER_SIZE 256
|
||||
|
||||
// Create a JSON object for incoming messages
|
||||
// Create a static JSON document for incoming messages.
|
||||
// Static allocation is efficient but has a fixed size.
|
||||
StaticJsonDocument<JSON_BUFFER_SIZE> incomingJson;
|
||||
|
||||
// Create a JSON object for outgoing messages
|
||||
// Create a dynamic JSON document for outgoing messages.
|
||||
// Dynamic allocation is more flexible but can lead to memory fragmentation on small microcontrollers.
|
||||
DynamicJsonDocument outgoingJson(JSON_BUFFER_SIZE);
|
||||
|
||||
void setup() {
|
||||
// Initialize serial communication
|
||||
Serial.begin(9600);
|
||||
}
|
||||
// --- Multiple HX711 Handling ---
|
||||
|
||||
void (*resetFunc)(void) = 0; //declare reset function @ address 0
|
||||
// Define the maximum number of HX711 sensors we can manage tare offsets for.
|
||||
// Adjust this based on available Arduino memory if needed.
|
||||
#define MAX_SENSORS 5
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
// Read the incoming JSON message
|
||||
DeserializationError error = deserializeJson(incomingJson, Serial);
|
||||
if (error) {
|
||||
// Handle error
|
||||
} else {
|
||||
// Extract the "type" and "data" fields from the JSON object
|
||||
String id = incomingJson["id"];
|
||||
int type = incomingJson["type"];
|
||||
JsonVariant data = incomingJson["data"];
|
||||
// Structure to hold the pins and tare offset for a single sensor.
|
||||
struct SensorTare {
|
||||
int dataPin = -1;
|
||||
int clockPin = -1;
|
||||
long tareOffset = 0;
|
||||
};
|
||||
|
||||
// Create a nested object in the root object
|
||||
JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
|
||||
// Array to store the tare offsets for multiple sensors.
|
||||
SensorTare sensorTareOffsets[MAX_SENSORS];
|
||||
|
||||
outgoingData["success"] = true;
|
||||
|
||||
// Handle the message based on the "type" field
|
||||
switch (type) {
|
||||
case 1:
|
||||
// Handle SET_PIN message
|
||||
pinMode((int)data["pin"], OUTPUT);
|
||||
if (data["mode"] == "DIGITAL") {
|
||||
digitalWrite((int)data["pin"], data["value"]);
|
||||
} else {
|
||||
analogWrite((int)data["pin"], (data["value"] == 255) ? HIGH : LOW);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// Handle GET_VAL message
|
||||
pinMode((int)data["pin"], INPUT);
|
||||
int val;
|
||||
if (data["mode"] == "DIGITAL") {
|
||||
val = digitalRead((int)data["pin"]);
|
||||
} else {
|
||||
val = analogRead((int)data["pin"]);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// Handle GET_SENSOR message
|
||||
|
||||
/*
|
||||
(WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
|
||||
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) ist die Formel zur Berechnung des Gewichts in Gramm nach der Kalibrierung mit einem 100 Gramm Gewicht.
|
||||
100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
|
||||
Durch die Division von 100g_val durch 100 wird der Sensitivitätsfaktor berechnet, und durch die Division von (WEIGHT_VAL - NO_WEIGHT_VAL) durch den Sensitivitätsfaktor wird das Gewicht in Gramm berechnet.
|
||||
|
||||
Beispiel:
|
||||
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
|
||||
(2400 - 2000) / (2450 /100) = 80 Gramm
|
||||
*/
|
||||
// HX711 circuit wiring
|
||||
const int LOADCELL_DATA_PIN = (int)data["pin_data"];
|
||||
const int LOADCELL_CLOCK_PIN = (int)data["pin_clock"];
|
||||
HX711 scale;
|
||||
scale.begin(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN);
|
||||
|
||||
// Get the weight value from the scale
|
||||
long weight_val = scale.get_units();
|
||||
outgoingData["value"] = weight_val;
|
||||
break;
|
||||
case 4:
|
||||
resetFunc(); //call reset
|
||||
break;
|
||||
default:
|
||||
// Handle unknown message type
|
||||
outgoingData[""] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Prepare the outgoing JSON message
|
||||
outgoingJson["id"] = id;
|
||||
outgoingJson["type"] = 0;
|
||||
outgoingJson["data"] = outgoingData;
|
||||
|
||||
// Send the outgoing JSON message
|
||||
serializeJson(outgoingJson, Serial);
|
||||
Serial.println();
|
||||
/**
|
||||
* @brief Finds the index of a sensor in the sensorTareOffsets array based on its pins.
|
||||
* @param dataPin The data pin of the sensor.
|
||||
* @param clockPin The clock pin of the sensor.
|
||||
* @return The index of the sensor, or -1 if not found.
|
||||
*/
|
||||
int findSensorTareIndex(int dataPin, int clockPin) {
|
||||
for (int i = 0; i < MAX_SENSORS; i++) {
|
||||
if (sensorTareOffsets[i].dataPin == dataPin && sensorTareOffsets[i].clockPin == clockPin) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // Sensor not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds or updates the tare offset for a sensor based on its pins.
|
||||
* @param dataPin The data pin of the sensor.
|
||||
* @param clockPin The clock pin of the sensor.
|
||||
* @param offset The tare offset to store.
|
||||
* @return The index where the offset was stored/updated, or -1 if the array is full.
|
||||
*/
|
||||
int addOrUpdateSensorTare(int dataPin, int clockPin, long offset) {
|
||||
int index = findSensorTareIndex(dataPin, clockPin);
|
||||
|
||||
if (index != -1) {
|
||||
// Sensor found, update the offset
|
||||
sensorTareOffsets[index].tareOffset = offset;
|
||||
return index;
|
||||
} else {
|
||||
// Sensor not found, find the first available slot
|
||||
for (int i = 0; i < MAX_SENSORS; i++) {
|
||||
if (sensorTareOffsets[i].dataPin == -1) { // Found an empty slot
|
||||
sensorTareOffsets[i].dataPin = dataPin;
|
||||
sensorTareOffsets[i].clockPin = clockPin;
|
||||
sensorTareOffsets[i].tareOffset = offset;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1; // Array is full
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the stored tare offset for a sensor based on its pins.
|
||||
* @param dataPin The data pin of the sensor.
|
||||
* @param clockPin The clock pin of the sensor.
|
||||
* @return The stored tare offset, or 0 if the sensor is not found.
|
||||
*/
|
||||
long getSensorTareOffset(int dataPin, int clockPin) {
|
||||
int index = findSensorTareIndex(dataPin, clockPin);
|
||||
if (index != -1) {
|
||||
return sensorTareOffsets[index].tareOffset;
|
||||
}
|
||||
return 0; // Return 0 offset if sensor not found (effectively untared)
|
||||
}
|
||||
|
||||
// --- End Multiple HX711 Handling ---
|
||||
|
||||
|
||||
void setup() {
|
||||
// Initialize serial communication at 9600 baud rate.
|
||||
// This speed should match the serial communication speed on the Raspberry Pi.
|
||||
Serial.begin(9600);
|
||||
|
||||
// Initialize the sensorTareOffsets array.
|
||||
for (int i = 0; i < MAX_SENSORS; i++) {
|
||||
sensorTareOffsets[i].dataPin = -1; // Mark as empty
|
||||
}
|
||||
|
||||
// Optional: Wait for the serial port to connect.
|
||||
while (!Serial);
|
||||
}
|
||||
|
||||
// Declare a function pointer to address 0.
|
||||
// Calling this function effectively resets the Arduino.
|
||||
void (*resetFunc)(void) = 0;
|
||||
|
||||
void loop() {
|
||||
// Check if there is data available to read from the serial port.
|
||||
if (Serial.available()) {
|
||||
// Read the incoming JSON message from the serial buffer.
|
||||
// deserializeJson reads from the Serial stream until it finds a complete JSON object.
|
||||
DeserializationError error = deserializeJson(incomingJson, Serial);
|
||||
|
||||
// Check if deserialization was successful.
|
||||
if (error) {
|
||||
// Handle deserialization error.
|
||||
// You might want to send an error message back to the Raspberry Pi.
|
||||
Serial.print(F("Deserialization failed: "));
|
||||
Serial.println(error.f_str());
|
||||
// Clear the serial buffer to prevent processing incomplete messages.
|
||||
while (Serial.available()) Serial.read();
|
||||
} else {
|
||||
// Deserialization was successful. Process the incoming message.
|
||||
|
||||
// Extract the "id", "type", and "data" fields from the JSON object.
|
||||
// The "id" is used to correlate requests and responses.
|
||||
String id = incomingJson["id"];
|
||||
// The "type" determines the action to perform.
|
||||
int type = incomingJson["type"];
|
||||
// The "data" field contains parameters for the action.
|
||||
JsonVariant data = incomingJson["data"];
|
||||
|
||||
// Create a nested object named "data" within the root outgoing JSON object.
|
||||
// This will hold the response data.
|
||||
JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
|
||||
|
||||
// Assume success by default, set to false in case of errors within cases.
|
||||
outgoingData["success"] = true;
|
||||
|
||||
// Check if the 'data' field exists and is not null before accessing its members.
|
||||
if (!data.isNull()) {
|
||||
// Handle the message based on the "type" field using a switch statement.
|
||||
switch (type) {
|
||||
case 1: // Handle SET_PIN message: Set the state of a GPIO pin.
|
||||
{ // Use a block to scope variables declared within the case.
|
||||
int pin = data["pin"];
|
||||
String mode = data["mode"];
|
||||
int value = data["value"];
|
||||
|
||||
// Set the pin mode to OUTPUT.
|
||||
pinMode(pin, OUTPUT);
|
||||
|
||||
// Check the mode (DIGITAL or ANALOG).
|
||||
if (mode == "DIGITAL") {
|
||||
// For digital mode, write HIGH or LOW.
|
||||
digitalWrite(pin, value); // Assuming value is 0 for LOW, 1 for HIGH.
|
||||
} else if (mode == "ANALOG") {
|
||||
// For analog mode (PWM), write a value between 0 and 255.
|
||||
// Ensure the pin supports PWM output.
|
||||
analogWrite(pin, value); // Use the value directly for PWM.
|
||||
} else {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "Invalid mode for SET_PIN";
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 2: // Handle GET_VAL message: Get the current value of a GPIO pin.
|
||||
{ // Use a block to scope variables declared within the case.
|
||||
int pin = data["pin"];
|
||||
String mode = data["mode"];
|
||||
int val;
|
||||
|
||||
// Set the pin mode to INPUT.
|
||||
pinMode(pin, INPUT);
|
||||
|
||||
// Check the mode (DIGITAL or ANALOG).
|
||||
if (mode == "DIGITAL") {
|
||||
// For digital mode, read HIGH or LOW.
|
||||
val = digitalRead(pin);
|
||||
} else if (mode == "ANALOG") {
|
||||
// For analog mode, read the analog value (0-1023 for most Arduinos).
|
||||
val = analogRead(pin);
|
||||
} else {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "Invalid mode for GET_VAL";
|
||||
break; // Exit the case after setting the error.
|
||||
}
|
||||
// Add the read value to the outgoing JSON data.
|
||||
outgoingData["value"] = val;
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // Handle GET_SENSOR message: Read data from a sensor (specifically HX711).
|
||||
{ // Use a block to scope variables declared within the case.
|
||||
// Get the data and clock pins for the HX711 from the incoming data.
|
||||
const int LOADCELL_DATA_PIN = (int)data["pin_data"];
|
||||
const int LOADCELL_CLOCK_PIN = (int)data["pin_clock"];
|
||||
|
||||
// Check if pins are valid.
|
||||
if (LOADCELL_DATA_PIN < 0 || LOADCELL_CLOCK_PIN < 0) {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "HX711 data and clock pins not provided or invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a temporary HX711 object for this specific sensor.
|
||||
HX711 currentScale;
|
||||
currentScale.begin(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN);
|
||||
|
||||
// Wait for the HX711 to be ready.
|
||||
if (currentScale.wait_ready_timeout(1000)) { // Wait up to 1000ms
|
||||
// Get the raw value from the scale.
|
||||
long raw_value = currentScale.get_value(); // Use get_value() for raw reading.
|
||||
|
||||
// Get the stored tare offset for these pins.
|
||||
long tare_offset = getSensorTareOffset(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN);
|
||||
|
||||
// Calculate the taried value.
|
||||
long taried_value = raw_value - tare_offset;
|
||||
|
||||
// Add the taried value to the outgoing JSON data.
|
||||
outgoingData["value"] = taried_value;
|
||||
|
||||
/*
|
||||
// Example calculation for weight in grams using a scale factor (requires calibration).
|
||||
// You would need to store and retrieve the scale factor per sensor as well.
|
||||
// currentScale.set_scale(calibration_factor);
|
||||
// long weight_grams = currentScale.get_units(10); // Get average of 10 readings with scale factor
|
||||
// outgoingData["grams"] = weight_grams;
|
||||
*/
|
||||
|
||||
} else {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "HX711 not ready or timeout";
|
||||
}
|
||||
} // Closing brace for case 3
|
||||
break;
|
||||
|
||||
case 4: // Handle TARE message: Tare a specific HX711 sensor.
|
||||
{ // Use a block to scope variables declared within the case.
|
||||
// Get the data and clock pins for the HX711 from the incoming data.
|
||||
const int LOADCELL_DATA_PIN = (int)data["pin_data"];
|
||||
const int LOADCELL_CLOCK_PIN = (int)data["pin_clock"];
|
||||
|
||||
// Check if pins are valid.
|
||||
if (LOADCELL_DATA_PIN < 0 || LOADCELL_CLOCK_PIN < 0) {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "HX711 data and clock pins not provided or invalid";
|
||||
break;
|
||||
}
|
||||
|
||||
// Create a temporary HX711 object for this specific sensor.
|
||||
HX711 currentScale;
|
||||
currentScale.begin(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN);
|
||||
|
||||
// Wait for the HX711 to be ready.
|
||||
if (currentScale.wait_ready_timeout(1000)) { // Wait up to 1000ms
|
||||
// Get the current raw value to use as the new tare offset.
|
||||
long current_raw_value = currentScale.get_value();
|
||||
|
||||
// Store this value as the tare offset for these pins.
|
||||
int index = addOrUpdateSensorTare(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN, current_raw_value);
|
||||
|
||||
if (index != -1) {
|
||||
outgoingData["message"] = "Sensor taried successfully";
|
||||
// Optionally return the new tare offset or taried value (which should be close to 0)
|
||||
// outgoingData["new_tare_offset"] = current_raw_value;
|
||||
// outgoingData["taried_value"] = current_raw_value - current_raw_value; // Should be 0
|
||||
} else {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "Could not store tare offset, sensor array full";
|
||||
}
|
||||
|
||||
} else {
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "HX711 not ready or timeout for tare";
|
||||
}
|
||||
} // Closing brace for case 4
|
||||
break;
|
||||
|
||||
|
||||
case 5: // Handle RESET message: Reset the Arduino.
|
||||
outgoingData["message"] = "Resetting Arduino";
|
||||
serializeJson(outgoingJson, Serial); // Send response before reset
|
||||
Serial.println(); // Send newline
|
||||
delay(100); // Small delay to ensure message is sent
|
||||
resetFunc(); // Call the reset function.
|
||||
break;
|
||||
|
||||
|
||||
default: // Handle unknown message type.
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "Unknown message type";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// Handle case where the 'data' field is missing or null.
|
||||
outgoingData["success"] = false;
|
||||
outgoingData["error"] = "Missing or null 'data' field in incoming JSON";
|
||||
}
|
||||
|
||||
|
||||
// Prepare the root of the outgoing JSON message.
|
||||
// Set the 'id' to match the incoming message for correlation.
|
||||
outgoingJson["id"] = id;
|
||||
// Set the 'type' for the response (e.g., 0 for acknowledgment/response).
|
||||
outgoingJson["type"] = 0;
|
||||
// The 'data' field was already created as a nested object.
|
||||
|
||||
// Send the outgoing JSON message to the serial port.
|
||||
serializeJson(outgoingJson, Serial);
|
||||
// Send a newline character to indicate the end of the JSON message.
|
||||
Serial.println();
|
||||
|
||||
// Clear the incoming JSON document to free up memory for the next message.
|
||||
incomingJson.clear();
|
||||
// Clear the outgoing JSON document.
|
||||
outgoingJson.clear();
|
||||
}
|
||||
}
|
||||
// Add a small delay to prevent the loop from running too fast when no data is available.
|
||||
delay(1);
|
||||
}
|
||||
|
10
doc/Notes.md
10
doc/Notes.md
@ -1,6 +1,6 @@
|
||||
# ### Achtung! \###
|
||||
Diese Datei ist nicht mehr aktuell.<br>
|
||||
Bitte nutze die neue Wiki unter [https://git.gaminggeneration.de/tobiash/itender/wiki](https://git.gaminggeneration.de/tobiash/itender/wiki) (Wiki des iTender Projekts)
|
||||
Bitte nutze die neue Wiki unter [https://git.dateien.org/tobiash/itender/wiki](https://git.gaminggeneration.de/tobiash/itender/wiki) (Wiki des iTender Projekts)
|
||||
|
||||
<br><br><br><br><br><br><hr><br><br><br><br><br>
|
||||
|
||||
@ -34,13 +34,13 @@ Was haben wir bereits am iTender Projekt gemacht?
|
||||
|
||||
#### Erstes 3D-Modell
|
||||
|
||||
<img src="./Screenshot_Model1.1_FrontTopRight.png" width="50%">
|
||||
<img src="./Screenshot_Model1.1_BackDownLeft.png" width="50%">
|
||||
<img src="Screenshot_Model1.1_FrontTopRight.png" width="50%">
|
||||
<img src="Screenshot_Model1.1_BackDownLeft.png" width="50%">
|
||||
|
||||
#### Neues 3D-Modell
|
||||
|
||||
<img src="./Screenshot_Model1.2_Front.png" width="50%">
|
||||
<img src="./Screenshot_Model1.2_Back.png" width="50%">
|
||||
<img src="Screenshot_Model1.2_Front.png" width="50%">
|
||||
<img src="Screenshot_Model1.2_Back.png" width="50%">
|
||||
|
||||
|
||||
<hr>
|
||||
|
@ -1,12 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
# shellcheck disable=SC2034
|
||||
DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root!"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "Creating user if not exists"
|
||||
useradd -p $(openssl passwd -1 iTender2022) itender || true
|
||||
useradd -p $(`openssl passwd -1 iTender2025`) itender || true
|
||||
mkdir /home/itender/
|
||||
usermod -d /home/itender/ itender || true
|
||||
chown itender:itender /home/itender
|
||||
@ -15,8 +18,8 @@ echo "Updating indexes"
|
||||
apt update
|
||||
|
||||
echo "Installing xserver xinit openbox ufw xserver-xorg x11 unclutter make chromium-browser crontab cmake g++ gcc and git..."
|
||||
apt install --no-install-recommends ufw xserver-xorg x11-xserver-utils xinit openbox -y || exit
|
||||
apt install git gcc g++ make cmake chromium-browser unclutter iptables cron pigpio -y || exit
|
||||
apt install --no-install-recommends xserver-xorg x11-xserver-utils xinit openbox -y || exit
|
||||
apt install git gcc g++ make cmake ufw chromium-browser unclutter iptables cron pigpio -y || exit
|
||||
echo "Try to uninstall node and npm... (Can fail)"
|
||||
apt purge node -y || true
|
||||
apt purge npm -y || true
|
||||
@ -29,11 +32,15 @@ echo "allowed_users=anybody" >/etc/X11/Xwrapper.config
|
||||
echo "Adding apt keys..."
|
||||
# Keys and stuff ---
|
||||
# Nodejs
|
||||
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash
|
||||
echo "Installing NodeJS"
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
||||
\. "$HOME/.nvm/nvm.sh"
|
||||
|
||||
# Yarn
|
||||
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor | sudo tee /usr/share/keyrings/yarnkey.gpg >/dev/null
|
||||
echo "deb [signed-by=/usr/share/keyrings/yarnkey.gpg] https://dl.yarnpkg.com/debian stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
|
||||
# Download and install Node.js:
|
||||
nvm install 22
|
||||
|
||||
# Download and install Yarn:
|
||||
corepack enable yarn
|
||||
|
||||
# MongoDB
|
||||
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
|
||||
@ -55,10 +62,6 @@ echo "Installing mongodb and yarn..."
|
||||
apt install nodejs yarn mongodb-org -y
|
||||
apt upgrade -y
|
||||
|
||||
adduser itender gpio
|
||||
adduser itender sudo
|
||||
chown itender:itender /home/itender/ -R
|
||||
|
||||
# V2: Arduino CLI
|
||||
echo "Installing arduino-cli..."
|
||||
sudo -u itender mkdir -p /home/itender/bin
|
||||
@ -69,6 +72,13 @@ sudo -u itender /home/itender/bin/arduino-cli core install arduino:avr || true
|
||||
sudo -u itender /home/itender/bin/arduino-cli lib install ArduinoJson || true
|
||||
sudo -u itender /home/itender/bin/arduino-cli lib install HX711 || true
|
||||
|
||||
|
||||
# User rights
|
||||
adduser itender gpio
|
||||
adduser itender sudo
|
||||
chown itender:itender /home/itender/ -R
|
||||
|
||||
|
||||
echo "Installing autostart..."
|
||||
# Autostart
|
||||
cat <<EOT >/etc/xdg/openbox/autostart
|
||||
@ -84,9 +94,11 @@ sed -i 's/"exited_cleanly":false/"exited_cleanly":true/; s/"exit_type":"[^"]\+"/
|
||||
/usr/bin/chromium-browser --disable-infobars --kiosk --incognito --disable-pinch --overscroll-history-navigation=0 "http://127.0.0.1:3000/" &
|
||||
EOT
|
||||
|
||||
|
||||
echo "Setting to console autologin..."
|
||||
raspi-config nonint do_boot_behaviour B2
|
||||
|
||||
|
||||
echo "Installing bashrc"
|
||||
echo "clear" >>/home/itender/.bashrc
|
||||
echo "[[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && startx -- -nocursor >/dev/null 2>&1" >>/home/itender/.bashrc
|
||||
@ -101,7 +113,7 @@ else
|
||||
echo "Cloning..."
|
||||
sudo -u itender git config --global credential.helper store
|
||||
git config --global credential.helper store
|
||||
git clone "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet
|
||||
git clone "https://itender:740e2cec4212ad058b09df3de5da73a372d73a1a@git.dateien.org.de/tobiash/itender.git" --quiet
|
||||
fi
|
||||
cd "$DIR" || exit
|
||||
yarn install
|
||||
@ -116,10 +128,11 @@ chown itender:itender /tmp/currentCron
|
||||
#install new cron file
|
||||
sudo -u itender crontab /tmp/currentCron
|
||||
|
||||
|
||||
echo "Installing systemd service..."
|
||||
cat <<EOT >/etc/systemd/system/itender.service
|
||||
[Unit]
|
||||
Description=iTender App
|
||||
Description=iTender Service
|
||||
After=network.target mongod.service
|
||||
StartLimitIntervalSec=1
|
||||
StartLimitBurst=1000
|
||||
@ -193,8 +206,8 @@ if ! grep -w "logo.nologo" /boot/cmdline.txt; then
|
||||
sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt
|
||||
fi
|
||||
|
||||
echo "iTender© 2022-2023 - Official licensed software
|
||||
Programmed by Tobias Hopp" >/etc/motd
|
||||
echo "iTender© 2022-2025 - Official licensed software
|
||||
Programmed by Tobias Hopp" > /etc/motd
|
||||
|
||||
echo "[Service]
|
||||
ExecStart=/usr/sbin/dhcpcd -q" >/etc/systemd/system/dhcpcd.service.d/wait.conf
|
64
package.json
64
package.json
@ -1,59 +1,19 @@
|
||||
{
|
||||
"name": "itender",
|
||||
"version": "2.2.8",
|
||||
"private": true,
|
||||
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
||||
"license": "UNLICENSED",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"repository": "https://git.dateien.org/TobiasH/itender.git",
|
||||
"author": "Tobias Hopp <thopp@conet.de>",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.15.14",
|
||||
"concurrently": "^9.1.2",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"scripts": {
|
||||
"boot": "yarn && yarn run compile && yarn run start",
|
||||
"start": "DEBUG=itender:* node --trace-warnings ./dist/main.js",
|
||||
"compile": "tsc && webpack",
|
||||
"compileStart": "yarn run compile && yarn start",
|
||||
"watchTS": "tsc --watch",
|
||||
"watchWP": "webpack --watch",
|
||||
"doc": "typedoc"
|
||||
"dev": "concurrently \"npm run --prefix web dev\" \"npm run --prefix server watchTS\""
|
||||
},
|
||||
"dependencies": {
|
||||
"@serialport/parser-readline": "^10.5.0",
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^4.17.14",
|
||||
"@types/express-ws": "^3.0.1",
|
||||
"@types/mongoose": "^5.11.97",
|
||||
"@types/morgan": "^1.9.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/rpi-gpio": "^2.1.1",
|
||||
"@types/rpi-ws281x-native": "^1.0.0",
|
||||
"@types/serialport": "^8.0.2",
|
||||
"@types/sharp": "^0.31.1",
|
||||
"axios": "^1.3.2",
|
||||
"buffer": "^6.0.3",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"debug": "^4.3.4",
|
||||
"detect-rpi": "^1.4.0",
|
||||
"express": "~4.16.1",
|
||||
"express-ws": "^5.0.2",
|
||||
"hc-sr04": "^0.0.1",
|
||||
"http-errors": "~1.6.3",
|
||||
"mongoose": "^6.7.2",
|
||||
"morgan": "^1.10.0",
|
||||
"net-ping": "^1.2.3",
|
||||
"onoff": "^6.0.3",
|
||||
"pi-hx711": "^1.2.0",
|
||||
"pug": "^3.0.2",
|
||||
"rpi-gpio": "^2.1.7",
|
||||
"rpi-ws281x-native": "^1.0.4",
|
||||
"serialport": "^10.5.0",
|
||||
"sharp": "^0.31.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"nodemon": "^2.0.20",
|
||||
"ts-loader": "^9.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typedoc": "^0.23.24",
|
||||
"typedoc-plugin-missing-exports": "^1.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
"nodemon": "^3.1.10"
|
||||
}
|
||||
}
|
||||
|
1
server/.env
Normal file
1
server/.env
Normal file
@ -0,0 +1 @@
|
||||
DEBUG=itender:*
|
5263
server/package-lock.json
generated
Normal file
5263
server/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
55
server/package.json
Normal file
55
server/package.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"name": "itender-server",
|
||||
"version": "2.2.8",
|
||||
"private": true,
|
||||
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
||||
"license": "UNLICENSED",
|
||||
"main": "dist/main.js",
|
||||
"scripts": {
|
||||
"start": "node --trace-warnings ./dist/main.js",
|
||||
"compile": "tsc && webpack",
|
||||
"compileStart": "yarn run compile && yarn start",
|
||||
"watchTS": "tsc --watch",
|
||||
"watch": "nodemon -w src/ -e ts src/main.ts",
|
||||
"doc": "typedoc"
|
||||
},
|
||||
"dependencies": {
|
||||
"@serialport/parser-readline": "^10.5.0",
|
||||
"axios": "1.8.2",
|
||||
"buffer": "^6.0.3",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"debug": "^4.3.4",
|
||||
"detect-rpi": "^1.4.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "5.0.0",
|
||||
"express-ws": "^5.0.2",
|
||||
"hc-sr04": "^0.0.1",
|
||||
"http-errors": "~1.6.3",
|
||||
"mongoose": "8.9.5",
|
||||
"morgan": "^1.10.0",
|
||||
"onoff": "^6.0.3",
|
||||
"pi-hx711": "^1.2.0",
|
||||
"pug": "^3.0.2",
|
||||
"rpi-gpio": "^2.1.7",
|
||||
"serialport": "^10.5.0",
|
||||
"sharp": "^0.31.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cookie-parser": "^1.4.3",
|
||||
"@types/debug": "^4.1.7",
|
||||
"@types/express": "^5.0.1",
|
||||
"@types/morgan": "^1.9.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/rpi-gpio": "^2.1.1",
|
||||
"@types/serialport": "^8.0.2",
|
||||
"@types/sharp": "^0.31.1",
|
||||
"nodemon": "^2.0.20",
|
||||
"ts-loader": "^9.4.1",
|
||||
"ts-node": "^10.9.1",
|
||||
"typedoc": "^0.23.24",
|
||||
"typedoc-plugin-missing-exports": "^1.0.0",
|
||||
"typescript": "^4.8.4",
|
||||
"webpack": "5.94.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user