Compare commits
No commits in common. "react-rewrite" and "master" have entirely different histories.
react-rewr
...
master
@ -1,45 +0,0 @@
|
|||||||
# 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/
|
/.idea/
|
||||||
*node_modules
|
/node_modules
|
||||||
/server/public/images/
|
/public/images/
|
||||||
*config.json
|
/config.json
|
||||||
*yarn-error.log
|
/yarn-error.log
|
||||||
/server/docs/
|
/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.
|
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)
|
[iTender Klasse](classes/iTender.iTender.html)
|
8
arduino/itender/.theia/launch.json
Normal file
8
arduino/itender/.theia/launch.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
@ -1,337 +1,103 @@
|
|||||||
/**
|
/**
|
||||||
* @file itender.ino
|
* Official proxy code for iTender GPIO Communication
|
||||||
* @brief Official proxy code for iTender GPIO Communication via Serial.
|
**/
|
||||||
*
|
#include <ArduinoJson.h>
|
||||||
* This code acts as a communication bridge between an Arduino and a Raspberry Pi
|
#include "HX711.h"
|
||||||
* 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).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ArduinoJson.h> // Include the ArduinoJson library for JSON parsing and serialization.
|
// Define the size of the JSON buffer
|
||||||
#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
|
#define JSON_BUFFER_SIZE 256
|
||||||
|
|
||||||
// Create a static JSON document for incoming messages.
|
// Create a JSON object for incoming messages
|
||||||
// Static allocation is efficient but has a fixed size.
|
|
||||||
StaticJsonDocument<JSON_BUFFER_SIZE> incomingJson;
|
StaticJsonDocument<JSON_BUFFER_SIZE> incomingJson;
|
||||||
|
|
||||||
// Create a dynamic JSON document for outgoing messages.
|
// Create a JSON object for outgoing messages
|
||||||
// Dynamic allocation is more flexible but can lead to memory fragmentation on small microcontrollers.
|
|
||||||
DynamicJsonDocument outgoingJson(JSON_BUFFER_SIZE);
|
DynamicJsonDocument outgoingJson(JSON_BUFFER_SIZE);
|
||||||
|
|
||||||
// --- Multiple HX711 Handling ---
|
|
||||||
|
|
||||||
// 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
|
|
||||||
|
|
||||||
// Structure to hold the pins and tare offset for a single sensor.
|
|
||||||
struct SensorTare {
|
|
||||||
int dataPin = -1;
|
|
||||||
int clockPin = -1;
|
|
||||||
long tareOffset = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Array to store the tare offsets for multiple sensors.
|
|
||||||
SensorTare sensorTareOffsets[MAX_SENSORS];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @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() {
|
void setup() {
|
||||||
// Initialize serial communication at 9600 baud rate.
|
// Initialize serial communication
|
||||||
// This speed should match the serial communication speed on the Raspberry Pi.
|
|
||||||
Serial.begin(9600);
|
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.
|
void (*resetFunc)(void) = 0; //declare reset function @ address 0
|
||||||
// Calling this function effectively resets the Arduino.
|
|
||||||
void (*resetFunc)(void) = 0;
|
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
// Check if there is data available to read from the serial port.
|
|
||||||
if (Serial.available()) {
|
if (Serial.available()) {
|
||||||
// Read the incoming JSON message from the serial buffer.
|
// Read the incoming JSON message
|
||||||
// deserializeJson reads from the Serial stream until it finds a complete JSON object.
|
|
||||||
DeserializationError error = deserializeJson(incomingJson, Serial);
|
DeserializationError error = deserializeJson(incomingJson, Serial);
|
||||||
|
|
||||||
// Check if deserialization was successful.
|
|
||||||
if (error) {
|
if (error) {
|
||||||
// Handle deserialization error.
|
// Handle 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 {
|
} else {
|
||||||
// Deserialization was successful. Process the incoming message.
|
// Extract the "type" and "data" fields from the JSON object
|
||||||
|
|
||||||
// Extract the "id", "type", and "data" fields from the JSON object.
|
|
||||||
// The "id" is used to correlate requests and responses.
|
|
||||||
String id = incomingJson["id"];
|
String id = incomingJson["id"];
|
||||||
// The "type" determines the action to perform.
|
|
||||||
int type = incomingJson["type"];
|
int type = incomingJson["type"];
|
||||||
// The "data" field contains parameters for the action.
|
|
||||||
JsonVariant data = incomingJson["data"];
|
JsonVariant data = incomingJson["data"];
|
||||||
|
|
||||||
// Create a nested object named "data" within the root outgoing JSON object.
|
// Create a nested object in the root object
|
||||||
// This will hold the response data.
|
|
||||||
JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
|
JsonObject outgoingData = outgoingJson.to<JsonObject>().createNestedObject("data");
|
||||||
|
|
||||||
// Assume success by default, set to false in case of errors within cases.
|
|
||||||
outgoingData["success"] = true;
|
outgoingData["success"] = true;
|
||||||
|
|
||||||
// Check if the 'data' field exists and is not null before accessing its members.
|
// Handle the message based on the "type" field
|
||||||
if (!data.isNull()) {
|
|
||||||
// Handle the message based on the "type" field using a switch statement.
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 1: // Handle SET_PIN message: Set the state of a GPIO pin.
|
case 1:
|
||||||
{ // Use a block to scope variables declared within the case.
|
// Handle SET_PIN message
|
||||||
int pin = data["pin"];
|
pinMode((int)data["pin"], OUTPUT);
|
||||||
String mode = data["mode"];
|
if (data["mode"] == "DIGITAL") {
|
||||||
int value = data["value"];
|
digitalWrite((int)data["pin"], 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 {
|
} else {
|
||||||
outgoingData["success"] = false;
|
analogWrite((int)data["pin"], (data["value"] == 255) ? HIGH : LOW);
|
||||||
outgoingData["error"] = "Invalid mode for SET_PIN";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 2:
|
||||||
case 2: // Handle GET_VAL message: Get the current value of a GPIO pin.
|
// Handle GET_VAL message
|
||||||
{ // Use a block to scope variables declared within the case.
|
pinMode((int)data["pin"], INPUT);
|
||||||
int pin = data["pin"];
|
|
||||||
String mode = data["mode"];
|
|
||||||
int val;
|
int val;
|
||||||
|
if (data["mode"] == "DIGITAL") {
|
||||||
// Set the pin mode to INPUT.
|
val = digitalRead((int)data["pin"]);
|
||||||
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 {
|
} else {
|
||||||
outgoingData["success"] = false;
|
val = analogRead((int)data["pin"]);
|
||||||
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;
|
break;
|
||||||
|
case 3:
|
||||||
case 3: // Handle GET_SENSOR message: Read data from a sensor (specifically HX711).
|
// Handle GET_SENSOR message
|
||||||
{ // 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).
|
(WEIGHT_VAL - NO_WEIGHT_VAL) / Sensitivitätsfaktor = Gewicht in Gramm
|
||||||
// You would need to store and retrieve the scale factor per sensor as well.
|
(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.
|
||||||
// currentScale.set_scale(calibration_factor);
|
100g_val /100 gibt den Sensitivitätsfaktor an, der angibt, wie viel sich der Sensorwert ändert, wenn sich das Gewicht um ein Gramm ändert.
|
||||||
// long weight_grams = currentScale.get_units(10); // Get average of 10 readings with scale factor
|
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.
|
||||||
// outgoingData["grams"] = weight_grams;
|
|
||||||
|
Beispiel:
|
||||||
|
(WEIGHT_VAL - NO_WEIGHT_VAL) / (100g_val /100) = Gewicht in Gramm
|
||||||
|
(2400 - 2000) / (2450 /100) = 80 Gramm
|
||||||
*/
|
*/
|
||||||
|
// HX711 circuit wiring
|
||||||
} 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_DATA_PIN = (int)data["pin_data"];
|
||||||
const int LOADCELL_CLOCK_PIN = (int)data["pin_clock"];
|
const int LOADCELL_CLOCK_PIN = (int)data["pin_clock"];
|
||||||
|
HX711 scale;
|
||||||
|
scale.begin(LOADCELL_DATA_PIN, LOADCELL_CLOCK_PIN);
|
||||||
|
|
||||||
// Check if pins are valid.
|
// Get the weight value from the scale
|
||||||
if (LOADCELL_DATA_PIN < 0 || LOADCELL_CLOCK_PIN < 0) {
|
long weight_val = scale.get_units();
|
||||||
outgoingData["success"] = false;
|
outgoingData["value"] = weight_val;
|
||||||
outgoingData["error"] = "HX711 data and clock pins not provided or invalid";
|
break;
|
||||||
|
case 4:
|
||||||
|
resetFunc(); //call reset
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handle unknown message type
|
||||||
|
outgoingData[""] = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a temporary HX711 object for this specific sensor.
|
// Prepare the outgoing JSON message
|
||||||
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;
|
outgoingJson["id"] = id;
|
||||||
// Set the 'type' for the response (e.g., 0 for acknowledgment/response).
|
|
||||||
outgoingJson["type"] = 0;
|
outgoingJson["type"] = 0;
|
||||||
// The 'data' field was already created as a nested object.
|
outgoingJson["data"] = outgoingData;
|
||||||
|
|
||||||
// Send the outgoing JSON message to the serial port.
|
// Send the outgoing JSON message
|
||||||
serializeJson(outgoingJson, Serial);
|
serializeJson(outgoingJson, Serial);
|
||||||
// Send a newline character to indicate the end of the JSON message.
|
|
||||||
Serial.println();
|
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! \###
|
# ### Achtung! \###
|
||||||
Diese Datei ist nicht mehr aktuell.<br>
|
Diese Datei ist nicht mehr aktuell.<br>
|
||||||
Bitte nutze die neue Wiki unter [https://git.dateien.org/tobiash/itender/wiki](https://git.gaminggeneration.de/tobiash/itender/wiki) (Wiki des iTender Projekts)
|
Bitte nutze die neue Wiki unter [https://git.gaminggeneration.de/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>
|
<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
|
#### Erstes 3D-Modell
|
||||||
|
|
||||||
<img src="Screenshot_Model1.1_FrontTopRight.png" width="50%">
|
<img src="./Screenshot_Model1.1_FrontTopRight.png" width="50%">
|
||||||
<img src="Screenshot_Model1.1_BackDownLeft.png" width="50%">
|
<img src="./Screenshot_Model1.1_BackDownLeft.png" width="50%">
|
||||||
|
|
||||||
#### Neues 3D-Modell
|
#### Neues 3D-Modell
|
||||||
|
|
||||||
<img src="Screenshot_Model1.2_Front.png" width="50%">
|
<img src="./Screenshot_Model1.2_Front.png" width="50%">
|
||||||
<img src="Screenshot_Model1.2_Back.png" width="50%">
|
<img src="./Screenshot_Model1.2_Back.png" width="50%">
|
||||||
|
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# shellcheck disable=SC2034
|
|
||||||
DEBIAN_FRONTEND=noninteractive
|
|
||||||
|
|
||||||
if [ "$EUID" -ne 0 ]; then
|
if [ "$EUID" -ne 0 ]; then
|
||||||
echo "Please run as root!"
|
echo "Please run as root!"
|
||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Creating user if not exists"
|
echo "Creating user if not exists"
|
||||||
useradd -p $(`openssl passwd -1 iTender2025`) itender || true
|
useradd -p $(openssl passwd -1 iTender2022) itender || true
|
||||||
mkdir /home/itender/
|
mkdir /home/itender/
|
||||||
usermod -d /home/itender/ itender || true
|
usermod -d /home/itender/ itender || true
|
||||||
chown itender:itender /home/itender
|
chown itender:itender /home/itender
|
||||||
@ -18,8 +15,8 @@ echo "Updating indexes"
|
|||||||
apt update
|
apt update
|
||||||
|
|
||||||
echo "Installing xserver xinit openbox ufw xserver-xorg x11 unclutter make chromium-browser crontab cmake g++ gcc and git..."
|
echo "Installing xserver xinit openbox ufw xserver-xorg x11 unclutter make chromium-browser crontab cmake g++ gcc and git..."
|
||||||
apt install --no-install-recommends xserver-xorg x11-xserver-utils xinit openbox -y || exit
|
apt install --no-install-recommends ufw 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
|
apt install git gcc g++ make cmake chromium-browser unclutter iptables cron pigpio -y || exit
|
||||||
echo "Try to uninstall node and npm... (Can fail)"
|
echo "Try to uninstall node and npm... (Can fail)"
|
||||||
apt purge node -y || true
|
apt purge node -y || true
|
||||||
apt purge npm -y || true
|
apt purge npm -y || true
|
||||||
@ -32,15 +29,11 @@ echo "allowed_users=anybody" >/etc/X11/Xwrapper.config
|
|||||||
echo "Adding apt keys..."
|
echo "Adding apt keys..."
|
||||||
# Keys and stuff ---
|
# Keys and stuff ---
|
||||||
# Nodejs
|
# Nodejs
|
||||||
echo "Installing NodeJS"
|
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash
|
||||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.3/install.sh | bash
|
|
||||||
\. "$HOME/.nvm/nvm.sh"
|
|
||||||
|
|
||||||
# Download and install Node.js:
|
# Yarn
|
||||||
nvm install 22
|
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 Yarn:
|
|
||||||
corepack enable yarn
|
|
||||||
|
|
||||||
# MongoDB
|
# MongoDB
|
||||||
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
|
wget -qO - https://www.mongodb.org/static/pgp/server-4.4.asc | sudo apt-key add -
|
||||||
@ -62,6 +55,10 @@ echo "Installing mongodb and yarn..."
|
|||||||
apt install nodejs yarn mongodb-org -y
|
apt install nodejs yarn mongodb-org -y
|
||||||
apt upgrade -y
|
apt upgrade -y
|
||||||
|
|
||||||
|
adduser itender gpio
|
||||||
|
adduser itender sudo
|
||||||
|
chown itender:itender /home/itender/ -R
|
||||||
|
|
||||||
# V2: Arduino CLI
|
# V2: Arduino CLI
|
||||||
echo "Installing arduino-cli..."
|
echo "Installing arduino-cli..."
|
||||||
sudo -u itender mkdir -p /home/itender/bin
|
sudo -u itender mkdir -p /home/itender/bin
|
||||||
@ -72,13 +69,6 @@ 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 ArduinoJson || true
|
||||||
sudo -u itender /home/itender/bin/arduino-cli lib install HX711 || 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..."
|
echo "Installing autostart..."
|
||||||
# Autostart
|
# Autostart
|
||||||
cat <<EOT >/etc/xdg/openbox/autostart
|
cat <<EOT >/etc/xdg/openbox/autostart
|
||||||
@ -94,11 +84,9 @@ 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/" &
|
/usr/bin/chromium-browser --disable-infobars --kiosk --incognito --disable-pinch --overscroll-history-navigation=0 "http://127.0.0.1:3000/" &
|
||||||
EOT
|
EOT
|
||||||
|
|
||||||
|
|
||||||
echo "Setting to console autologin..."
|
echo "Setting to console autologin..."
|
||||||
raspi-config nonint do_boot_behaviour B2
|
raspi-config nonint do_boot_behaviour B2
|
||||||
|
|
||||||
|
|
||||||
echo "Installing bashrc"
|
echo "Installing bashrc"
|
||||||
echo "clear" >>/home/itender/.bashrc
|
echo "clear" >>/home/itender/.bashrc
|
||||||
echo "[[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && startx -- -nocursor >/dev/null 2>&1" >>/home/itender/.bashrc
|
echo "[[ -z \$DISPLAY && \$XDG_VTNR -eq 1 ]] && startx -- -nocursor >/dev/null 2>&1" >>/home/itender/.bashrc
|
||||||
@ -113,7 +101,7 @@ else
|
|||||||
echo "Cloning..."
|
echo "Cloning..."
|
||||||
sudo -u itender git config --global credential.helper store
|
sudo -u itender git config --global credential.helper store
|
||||||
git config --global credential.helper store
|
git config --global credential.helper store
|
||||||
git clone "https://itender:740e2cec4212ad058b09df3de5da73a372d73a1a@git.dateien.org.de/tobiash/itender.git" --quiet
|
git clone "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet
|
||||||
fi
|
fi
|
||||||
cd "$DIR" || exit
|
cd "$DIR" || exit
|
||||||
yarn install
|
yarn install
|
||||||
@ -128,11 +116,10 @@ chown itender:itender /tmp/currentCron
|
|||||||
#install new cron file
|
#install new cron file
|
||||||
sudo -u itender crontab /tmp/currentCron
|
sudo -u itender crontab /tmp/currentCron
|
||||||
|
|
||||||
|
|
||||||
echo "Installing systemd service..."
|
echo "Installing systemd service..."
|
||||||
cat <<EOT >/etc/systemd/system/itender.service
|
cat <<EOT >/etc/systemd/system/itender.service
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=iTender Service
|
Description=iTender App
|
||||||
After=network.target mongod.service
|
After=network.target mongod.service
|
||||||
StartLimitIntervalSec=1
|
StartLimitIntervalSec=1
|
||||||
StartLimitBurst=1000
|
StartLimitBurst=1000
|
||||||
@ -206,8 +193,8 @@ if ! grep -w "logo.nologo" /boot/cmdline.txt; then
|
|||||||
sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt
|
sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "iTender© 2022-2025 - Official licensed software
|
echo "iTender© 2022-2023 - Official licensed software
|
||||||
Programmed by Tobias Hopp" > /etc/motd
|
Programmed by Tobias Hopp" >/etc/motd
|
||||||
|
|
||||||
echo "[Service]
|
echo "[Service]
|
||||||
ExecStart=/usr/sbin/dhcpcd -q" >/etc/systemd/system/dhcpcd.service.d/wait.conf
|
ExecStart=/usr/sbin/dhcpcd -q" >/etc/systemd/system/dhcpcd.service.d/wait.conf
|
64
package.json
64
package.json
@ -1,19 +1,59 @@
|
|||||||
{
|
{
|
||||||
"name": "itender",
|
"name": "itender",
|
||||||
"version": "1.0.0",
|
"version": "2.2.8",
|
||||||
"main": "index.js",
|
"private": true,
|
||||||
"repository": "https://git.dateien.org/TobiasH/itender.git",
|
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
||||||
"author": "Tobias Hopp <thopp@conet.de>",
|
"license": "UNLICENSED",
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^22.15.14",
|
|
||||||
"concurrently": "^9.1.2",
|
|
||||||
"typescript": "^5.8.3"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "concurrently \"npm run --prefix web dev\" \"npm run --prefix server watchTS\""
|
"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"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nodemon": "^3.1.10"
|
"@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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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