Compare commits
27 Commits
ab53eb2ee6
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d564b2670 | |||
| 5a67e90143 | |||
| 224fae39f7 | |||
| 45459ee231 | |||
| 978dd0dc5d | |||
| 1f96e10f76 | |||
| c5782018b8 | |||
| 67874de37a | |||
| 582925b8a1 | |||
| b6c91e4ac4 | |||
| 627cc9bc24 | |||
| 2ee9a26abd | |||
| 7ce3f5efc2 | |||
| b45180d50d | |||
| f0c90c831f | |||
| 69cce7be3e | |||
|
|
18427298bc | ||
|
|
247848285f | ||
|
|
641b5d2f68 | ||
|
|
fa4153d68d | ||
|
|
964236b6b5 | ||
|
|
5dc92e9ca4 | ||
|
|
6741f77615 | ||
|
|
a98acc9060 | ||
|
|
c619488738 | ||
|
|
a17eb70ce0 | ||
|
|
8525da4004 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
STM32_CONTROL/.vscode
|
||||
STM32_CONTROL/.pio
|
||||
18
.vscode/c_cpp_properties.json
vendored
Normal file
18
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "linux-gcc-x64",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "${default}",
|
||||
"cppStandard": "${default}",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"compilerArgs": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
24
.vscode/launch.json
vendored
Normal file
24
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C/C++ Runner: Debug Session",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"cwd": "/hdd/GiTea-REPO/MD1200/PC_CONTROL_CODE/CPP/noInflux",
|
||||
"program": "/hdd/GiTea-REPO/MD1200/PC_CONTROL_CODE/CPP/noInflux/build/Debug/outDebug",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
59
.vscode/settings.json
vendored
Normal file
59
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||
"C_Cpp_Runner.cStandard": "",
|
||||
"C_Cpp_Runner.cppStandard": "",
|
||||
"C_Cpp_Runner.msvcBatchPath": "",
|
||||
"C_Cpp_Runner.useMsvc": false,
|
||||
"C_Cpp_Runner.warnings": [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wpedantic",
|
||||
"-Wshadow",
|
||||
"-Wformat=2",
|
||||
"-Wcast-align",
|
||||
"-Wconversion",
|
||||
"-Wsign-conversion",
|
||||
"-Wnull-dereference"
|
||||
],
|
||||
"C_Cpp_Runner.msvcWarnings": [
|
||||
"/W4",
|
||||
"/permissive-",
|
||||
"/w14242",
|
||||
"/w14287",
|
||||
"/w14296",
|
||||
"/w14311",
|
||||
"/w14826",
|
||||
"/w44062",
|
||||
"/w44242",
|
||||
"/w14905",
|
||||
"/w14906",
|
||||
"/w14263",
|
||||
"/w44265",
|
||||
"/w14928"
|
||||
],
|
||||
"C_Cpp_Runner.enableWarnings": true,
|
||||
"C_Cpp_Runner.warningsAsError": false,
|
||||
"C_Cpp_Runner.compilerArgs": [],
|
||||
"C_Cpp_Runner.linkerArgs": [],
|
||||
"C_Cpp_Runner.includePaths": [],
|
||||
"C_Cpp_Runner.includeSearch": [
|
||||
"*",
|
||||
"**/*"
|
||||
],
|
||||
"C_Cpp_Runner.excludeSearch": [
|
||||
"**/build",
|
||||
"**/build/**",
|
||||
"**/.*",
|
||||
"**/.*/**",
|
||||
"**/.vscode",
|
||||
"**/.vscode/**"
|
||||
],
|
||||
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||
"C_Cpp_Runner.showCompilationTime": false,
|
||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||
}
|
||||
BIN
58FO8iY.jpg
Normal file
BIN
58FO8iY.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
6
ARDUINO_NANO_CONTROLL/.gitignore
vendored
Normal file
6
ARDUINO_NANO_CONTROLL/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.vscode
|
||||
37
ARDUINO_NANO_CONTROLL/include/README
Normal file
37
ARDUINO_NANO_CONTROLL/include/README
Normal file
@@ -0,0 +1,37 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the convention is to give header files names that end with `.h'.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
46
ARDUINO_NANO_CONTROLL/lib/README
Normal file
46
ARDUINO_NANO_CONTROLL/lib/README
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into the executable file.
|
||||
|
||||
The source code of each library should be placed in a separate directory
|
||||
("lib/your_library_name/[Code]").
|
||||
|
||||
For example, see the structure of the following example libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Example contents of `src/main.c` using Foo and Bar:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries by scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
18
ARDUINO_NANO_CONTROLL/platformio.ini
Normal file
18
ARDUINO_NANO_CONTROLL/platformio.ini
Normal file
@@ -0,0 +1,18 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:nanoatmega328]
|
||||
platform = atmelavr
|
||||
board = nanoatmega328
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
adafruit/DHT sensor library@^1.4.6
|
||||
featherfly/SoftwareSerial@^1.0
|
||||
board_build.mcu = atmega328p
|
||||
285
ARDUINO_NANO_CONTROLL/src/main.cpp
Normal file
285
ARDUINO_NANO_CONTROLL/src/main.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
#include <Arduino.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <DHT.h>
|
||||
#include <DHT_U.h>
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// DHT PreConfiguration
|
||||
#define DHTPIN 4 // Digital pin connected to the DHT sensor
|
||||
//#define DHTPIN PB0
|
||||
// Pin 15 can work but DHT must be disconnected during program upload.
|
||||
#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321
|
||||
// -------------------------------------------------------------
|
||||
// Initialize DHT sensor.
|
||||
// Note that older versions of this library took an optional third parameter to
|
||||
// tweak the timings for faster processors. This parameter is no longer needed
|
||||
// as the current DHT reading algorithm adjusts itself to work on faster procs.
|
||||
DHT dht(DHTPIN, DHTTYPE);
|
||||
|
||||
|
||||
// VARS
|
||||
const int MD1200BAUDS = 38400; // From what I've read it is always 38400
|
||||
//const int EPYSLEEPY = 600000; / 10 minutes
|
||||
const long EPYSLEEPY = 300000; // 5 minutes
|
||||
//const int EPYSLEEPY = 150000; // 2,5 minutes
|
||||
|
||||
#define RX_PIN 3
|
||||
#define TX_PIN 2
|
||||
SoftwareSerial MDSerial(RX_PIN, TX_PIN); // Goes up to 115200 bauds
|
||||
|
||||
// declarations
|
||||
int getTemp();
|
||||
int setFanTrsh(int);
|
||||
float dhtRead();
|
||||
|
||||
void setup() {
|
||||
// Setup connection to MD1200
|
||||
// Serial because we're using RX/TX pins
|
||||
MDSerial.begin(MD1200BAUDS);
|
||||
|
||||
// Just debug
|
||||
Serial.begin(9600);
|
||||
|
||||
dht.begin();
|
||||
|
||||
Serial.println("setup end");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
Serial.println("Loop start");
|
||||
|
||||
int fanPercnt = getTemp();
|
||||
|
||||
if (fanPercnt < 10) {
|
||||
setFanTrsh(fanPercnt);
|
||||
}
|
||||
|
||||
/*
|
||||
check temperature and
|
||||
set fan speed every X minutes
|
||||
*/
|
||||
delay(EPYSLEEPY);
|
||||
|
||||
}
|
||||
|
||||
// Get current temperature
|
||||
int getTemp() {
|
||||
Serial.println("getTemp start");
|
||||
|
||||
int bp1 = 0;
|
||||
int bp2 = 0;
|
||||
// int exp0 = 0;
|
||||
// int exp1 = 0;
|
||||
// int simm0 = 0;
|
||||
// int simm1 = 0;
|
||||
String MD1200output;
|
||||
|
||||
MDSerial.println("_temp_rd");
|
||||
|
||||
// wait for MD1200 to answer
|
||||
delay(30);
|
||||
Serial.println("start parsing temperature start");
|
||||
|
||||
while (MDSerial.available()) {
|
||||
MD1200output = MDSerial.readStringUntil('\n');
|
||||
|
||||
// Check backplane 1
|
||||
if (MD1200output.startsWith("BP_1")) {
|
||||
// check index number of =
|
||||
int eq = MD1200output.indexOf('=');
|
||||
// check index number of c
|
||||
int c = MD1200output.indexOf('c');
|
||||
// check if both exists
|
||||
if (eq != -1 && c != -1) {
|
||||
/*
|
||||
take value between "= " and "c".
|
||||
NOTICE that eq + 1 is there because in
|
||||
"BP_1[2] = 25c" there is a space between = and 25.
|
||||
*/
|
||||
bp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
Serial.println("Backplane 1 " + String(bp1));
|
||||
}
|
||||
}
|
||||
|
||||
// Check backplane 2
|
||||
if (MD1200output.startsWith("BP_2")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
bp2 = MD1200output.substring(eq + 1, c).toInt();
|
||||
Serial.println("Backplane 2 " + String(bp2));
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment if you want to also get temperature for expanders
|
||||
/*
|
||||
|
||||
// Check expander 0
|
||||
if (MD1200output.startsWith("EXP0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check expander 1
|
||||
if (MD1200output.startsWith("EXP1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 0
|
||||
if (MD1200output.startsWith("SIM0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 1
|
||||
if (MD1200output.startsWith("SIM1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Stop when prompt returns
|
||||
if (MD1200output.endsWith(">")) {
|
||||
Serial.println("stopping temp reading");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do (BP_1 + BP_2) / 2 to get the average of backplane
|
||||
if (bp1 != -1 && bp2 != -1) {
|
||||
int bpAvg = (bp1 + bp2) / 2;
|
||||
|
||||
Serial.println("Average temp is " + String(bpAvg));
|
||||
|
||||
// define default
|
||||
int outPrcntg = 21;
|
||||
|
||||
// check external sensor temp
|
||||
int ownReadTemp = int(dhtRead());
|
||||
|
||||
|
||||
Serial.println("Checking DHT temp");
|
||||
if (ownReadTemp <= 35) {
|
||||
return 40;
|
||||
}
|
||||
|
||||
// a
|
||||
switch (bpAvg) {
|
||||
case 23:
|
||||
outPrcntg = 21;
|
||||
break;
|
||||
/*
|
||||
Minimum is 21 (akhsually 20)
|
||||
BUT
|
||||
https://forums.servethehome.com/index.php?threads/fun-with-an-md1200-md1220-sc200-sc220.27487/
|
||||
*/
|
||||
case 25:
|
||||
outPrcntg = 23;
|
||||
break;
|
||||
case 27:
|
||||
outPrcntg = 24;
|
||||
break;
|
||||
case 29:
|
||||
outPrcntg = 26;
|
||||
break;
|
||||
case 31:
|
||||
outPrcntg = 27;
|
||||
break;
|
||||
case 33:
|
||||
outPrcntg = 30;
|
||||
break;
|
||||
case 35:
|
||||
outPrcntg = 34;
|
||||
break;
|
||||
case 37:
|
||||
outPrcntg = 38;
|
||||
break;
|
||||
/*
|
||||
I don't wan't to become deaf so max is 40.
|
||||
*/
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
Serial.println("Returnning " + String(outPrcntg) + " %");
|
||||
return outPrcntg;
|
||||
|
||||
} else {
|
||||
return -1; // failed to read temp
|
||||
}
|
||||
|
||||
/*
|
||||
BP_1[2] - Back plane, maybe left
|
||||
BP_2[3] - Back plane, maybe right
|
||||
SIM0[0] - Controller A
|
||||
SIM1[1] - Controller B
|
||||
EXP0[4] - Expander 0
|
||||
EXP1[5] - Expander 1
|
||||
|
||||
AVG - average of all sensors
|
||||
*/
|
||||
}
|
||||
|
||||
// take percentage as int and set it.
|
||||
int setFanTrsh(int fanTrshInp) {
|
||||
|
||||
Serial.println("Setting fan speed");
|
||||
String outputStatement = "set_speed " + String(fanTrshInp);
|
||||
|
||||
// MDSerial.println("Sending " + outputStatement + " to MD1200");
|
||||
|
||||
if (MDSerial.println(outputStatement)) {
|
||||
Serial.println("Setting fan speed success");
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
Serial.println("Setting fan speed unsuccess");
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
float dhtRead() {
|
||||
// Reading temperature or humidity takes about 250 milliseconds!
|
||||
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
|
||||
// float humidt = dht.readHumidity();
|
||||
// Read temperature as Celsius (the default)
|
||||
float tempr = dht.readTemperature();
|
||||
// Read temperature as Fahrenheit (isFahrenheit = true)
|
||||
// f = dht.readTemperature(true);
|
||||
|
||||
// Check if any reads failed and exit early (to try again).
|
||||
// if (isnan(humidt) || isnan(tempr))
|
||||
if (isnan(tempr))
|
||||
{
|
||||
// MDSerial.println("Failed to read from DHT sensor!");
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return tempr;
|
||||
}
|
||||
|
||||
// Compute heat index in Fahrenheit (the default)
|
||||
// hif = dht.computeHeatIndex(f, h);
|
||||
// Compute heat index in Celsius (isFahreheit = false)
|
||||
// hicc = dht.computeHeatIndex(tempr, humidt, false);
|
||||
|
||||
}
|
||||
11
ARDUINO_NANO_CONTROLL/test/README
Normal file
11
ARDUINO_NANO_CONTROLL/test/README
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
2
PC_CONTROL_CODE/.gitignore
vendored
Normal file
2
PC_CONTROL_CODE/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
testing
|
||||
cpp
|
||||
2
PC_CONTROL_CODE/VerySimpleCode/crontab
Normal file
2
PC_CONTROL_CODE/VerySimpleCode/crontab
Normal file
@@ -0,0 +1,2 @@
|
||||
# Run every minute
|
||||
* * * * /location/to/bash/simple.sh
|
||||
9
PC_CONTROL_CODE/VerySimpleCode/simple.sh
Normal file
9
PC_CONTROL_CODE/VerySimpleCode/simple.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
for i in {1..59}
|
||||
do
|
||||
stty -F /dev/ttyUSB0 speed 38400 cs8 -ixon raw
|
||||
echo -ne "_shutup 24\n\r" > /dev/ttyUSB0
|
||||
sleep 1
|
||||
done
|
||||
|
||||
exit
|
||||
BIN
PC_CONTROL_CODE/docker/.Dockerfile.kate-swp
Normal file
BIN
PC_CONTROL_CODE/docker/.Dockerfile.kate-swp
Normal file
Binary file not shown.
1
PC_CONTROL_CODE/docker/.gitignore
vendored
Normal file
1
PC_CONTROL_CODE/docker/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.mypy_cache
|
||||
28
PC_CONTROL_CODE/docker/Dockerfile
Normal file
28
PC_CONTROL_CODE/docker/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM alpine:latest
|
||||
|
||||
# https://docs.docker.com/reference/dockerfile/#environment-replacement
|
||||
# ENV MD1200BAUD=38400
|
||||
# ENV SERIALADAPTER=/dev/ttyUSB0
|
||||
# ENV EPPYSLEEPY=300
|
||||
|
||||
# VOLUME [""]
|
||||
|
||||
RUN apk update && \
|
||||
apk add python3 py3-pip
|
||||
|
||||
RUN mkdir /etc/MD1200FAN/
|
||||
WORKDIR /etc/MD1200FAN/
|
||||
|
||||
COPY ./mainDocker.py /etc/MD1200FAN/
|
||||
# COPY ./requirements.txt /etc/MD1200FAN/
|
||||
|
||||
RUN python3 -m venv venv && \
|
||||
venv/bin/python3 -m pip install --upgrade pip && \
|
||||
venv/bin/pip3 install PySerial
|
||||
# venv/bin/pip3 install -r requirements.txt
|
||||
|
||||
# VOLUME ["/etc/MD1200FAN/"]
|
||||
|
||||
CMD ["venv/bin/python3", "mainDocker.py"]
|
||||
|
||||
# CMD ["/etc/MD1200FAN/venv/bin/python3", "/etc/MD1200FAN/mainDocker.py"]
|
||||
18
PC_CONTROL_CODE/docker/docker-compose.yml
Normal file
18
PC_CONTROL_CODE/docker/docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
|
||||
services:
|
||||
mdfanchanger:
|
||||
container_name: MD_Fan_Changer
|
||||
image: yuruc3/md1200_fan_controll:v1.2.1
|
||||
environment:
|
||||
# - MD1200BAUD=
|
||||
- SERIALADAPTER=/dev/ttyUSB0
|
||||
- TEMP_FACTOR=17
|
||||
- EPPYSLEEPY=0.25
|
||||
- MDSERIALTIMEOUT=0.75
|
||||
# - LOW_FAN_TRSHD=
|
||||
# - HIGH_FAN_TRSHD=
|
||||
devices:
|
||||
- /dev/ttyUSB0:/dev/ttyUSB0
|
||||
restart: unless-stopped
|
||||
privileged: false
|
||||
194
PC_CONTROL_CODE/docker/mainDocker.py
Normal file
194
PC_CONTROL_CODE/docker/mainDocker.py
Normal file
@@ -0,0 +1,194 @@
|
||||
import serial, time, os
|
||||
from typing import Final
|
||||
|
||||
# setting consts that can be customized
|
||||
|
||||
# baud rate. Prob not needed as 38400 is standard
|
||||
MD1200BAUD: Final[int] = int(os.getenv("MD1200BAUD", 38400))
|
||||
# used if you want to run it on multiple JBODs
|
||||
SERIALADAPTER: Final[str] = os.getenv("SERIALADAPTER", "/dev/ttyUSB0")
|
||||
# Factor that defines how aggressive the temperature curve is
|
||||
TEMP_FACTOR: Final[int] = int(os.getenv("TEMP_FACTOR", 16))
|
||||
# time between sending command to get temp and storing it. It's there to allow JBOD to answer
|
||||
EPPYSLEEPY: Final[float] = float(os.getenv("EPPYSLEEPY", 1))
|
||||
|
||||
LOW_FAN_TRSHD: Final[int] = int(os.getenv("LOW_FAN_TRSHD", 21))
|
||||
HIGH_FAN_TRSHD: Final[int] = int(os.getenv("HIGH_FAN_TRSHD", 40))
|
||||
|
||||
GETTMPCMND: Final[str] = os.getenv("GETTMPCMND", "_temp_rd")
|
||||
SETFANCMND: Final[str] = os.getenv("SETFANCMND", "set_speed")
|
||||
|
||||
DEFOUTPRCNTG: Final[int] = int(os.getenv("DEFOUTPRCNTG", 24))
|
||||
|
||||
MDSERIALTIMEOUT: Final[float] = float(os.getenv("MDSERIALTIMEOUT", 1))
|
||||
|
||||
TEMPREADINTERVAL: Final[int] = int(os.getenv("TEMPREADINTERVAL", 15))
|
||||
|
||||
GETTEMPTIMESLEEP: Final[int] = int(os.getenv("GETTEMPTIMESLEEP", 1))
|
||||
|
||||
# init
|
||||
MDserial = serial.Serial(
|
||||
port=SERIALADAPTER,\
|
||||
baudrate=MD1200BAUD,\
|
||||
parity=serial.PARITY_NONE,\
|
||||
stopbits=serial.STOPBITS_ONE,\
|
||||
bytesize=serial.EIGHTBITS,\
|
||||
timeout=MDSERIALTIMEOUT)
|
||||
|
||||
lastTempReading = time.time()
|
||||
MDtempDict = {}
|
||||
|
||||
|
||||
def getTemp() -> dict:
|
||||
|
||||
MDserial.write(f"{GETTMPCMND}\n\r".encode())
|
||||
time.sleep(GETTEMPTIMESLEEP)
|
||||
MDreturning = MDserial.read_until(" >").decode(errors="ignore")
|
||||
|
||||
MDict = {}
|
||||
|
||||
# Sanitise output
|
||||
MDsanit = MDreturning.splitlines()
|
||||
|
||||
#if there is smth do smth
|
||||
if MDreturning:
|
||||
|
||||
for line in MDsanit:
|
||||
|
||||
if ">" in line or "b'" in line:
|
||||
continue
|
||||
|
||||
matchstm = line[2:6]
|
||||
|
||||
match matchstm:
|
||||
case "BP_1":
|
||||
MDict["bp1"] = int(line[12:14])
|
||||
case "BP_2":
|
||||
MDict["bp2"] = int(line[12:14])
|
||||
case "SIM0":
|
||||
MDict["sim0"] = int(line[12:14])
|
||||
case "SIM1":
|
||||
MDict["sim1"] = int(line[12:14])
|
||||
case "EXP0":
|
||||
MDict["exp0"] = int(line[12:14])
|
||||
case "EXP1":
|
||||
MDict["exp1"] = int(line[12:14])
|
||||
# case "AVG":
|
||||
# MDict["avg"] = int(line[12:14])
|
||||
# MDict["avg"] = int(line.strip().split("=")[1].strip().replace("c", ""))
|
||||
# try:
|
||||
# # Extract number from e.g. ' AVG = 40c'
|
||||
# temp = int(line.strip().split("=")[1].strip().replace("c", ""))
|
||||
# MDict["avg"] = temp
|
||||
# except Exception as e:
|
||||
# # print(f"[WARN] Failed to parse AVG line: {line} ({e})", flush=True)
|
||||
# pass
|
||||
case _:
|
||||
# try to catch the AVG line like: " AVG = 40c"
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("AVG"):
|
||||
try:
|
||||
temp = int(stripped.split("=")[1].strip().replace("c", ""))
|
||||
MDict["avg"] = temp
|
||||
except Exception as e:
|
||||
print(f"Could not parse AVG line: {line} ({e})", flush=True)
|
||||
continue
|
||||
# continue
|
||||
return MDict
|
||||
else:
|
||||
return {"error": "unidentified"}
|
||||
|
||||
|
||||
def setSpeed(inSpeeDict: dict) -> int:
|
||||
|
||||
bpavrg = 0
|
||||
# default
|
||||
outfanprcntg = 0
|
||||
|
||||
# get backplanbe average
|
||||
if "bp1" in inSpeeDict and "bp2" in inSpeeDict:
|
||||
bpavrg = (inSpeeDict["bp1"] + inSpeeDict["bp2"]) /2
|
||||
outfanprcntg = int((bpavrg / (HIGH_FAN_TRSHD - LOW_FAN_TRSHD)) * TEMP_FACTOR)
|
||||
# os.system(f"echo setting {outfanprcntg}%")
|
||||
|
||||
return outfanprcntg
|
||||
|
||||
# Set fan speed
|
||||
if outfanprcntg >= 20:
|
||||
MDserial.write((f"{SETFANCMND} {str(outfanprcntg)} \n\r").encode())
|
||||
print(f"setting {outfanprcntg}%", flush=True)
|
||||
return outfanprcntg
|
||||
else:
|
||||
# Set default value
|
||||
MDserial.write((f"{SETFANCMND} {str(DEFOUTPRCNTG)} \n\r").encode())
|
||||
return DEFOUTPRCNTG
|
||||
|
||||
# If something goes super wrong
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
# Check if UART is used
|
||||
# Not neede because when defining MDserial it gets automatically opened
|
||||
# Will leave it here anyway
|
||||
# try:
|
||||
# MDserial.open()
|
||||
# except serial.serialutil.SerialException:
|
||||
# # MDserial.close()
|
||||
# # MDserial.open()
|
||||
# print("Port allready opened.\nTry closing it first")
|
||||
|
||||
# Init
|
||||
MDtempDict = getTemp()
|
||||
lastTempReading = time.time()
|
||||
try:
|
||||
|
||||
while True:
|
||||
# https://stackoverflow.com/questions/52578122/not-able-to-send-the-enter-command-on-pyserial
|
||||
|
||||
# get temperature data, wait for MD1200 to answer and store
|
||||
|
||||
currentTime = time.time()
|
||||
|
||||
if currentTime - lastTempReading >= TEMPREADINTERVAL:
|
||||
MDtempDict = getTemp()
|
||||
lastTempReading = currentTime
|
||||
|
||||
if MDtempDict:
|
||||
setSpeedrcode = setSpeed(MDtempDict)
|
||||
|
||||
# good
|
||||
if setSpeedrcode == 0:
|
||||
pass
|
||||
# print("Were mint", flush=True)
|
||||
# time.sleep(EPPYSLEEPY)
|
||||
# not good
|
||||
elif setSpeedrcode == 1:
|
||||
print("Ambigous temperature readings.\nFalling back to safe values.", flush=True)
|
||||
# time.sleep(EPPYSLEEPY)
|
||||
# very not good
|
||||
elif setSpeedrcode == -1:
|
||||
print("o nyo", flush=True)
|
||||
exit()
|
||||
# very very very not good
|
||||
else:
|
||||
print("idk", flush=True)
|
||||
exit()
|
||||
else:
|
||||
print(f"temperature not yet pulled.\nFalling back do default fan speed", flush=True)
|
||||
# os.system(f"echo temperature not yet pulled.\nFalling back do default fan speed")
|
||||
MDserial.write((f"{SETFANCMND} {str(DEFOUTPRCNTG)} \n\r").encode())
|
||||
|
||||
time.sleep(EPPYSLEEPY)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("\n[INFO] KeyboardInterrupt detected. Exiting gracefully...")
|
||||
MDserial.close()
|
||||
exit()
|
||||
|
||||
finally:
|
||||
print("closing port")
|
||||
MDserial.close()
|
||||
|
||||
print("closing port")
|
||||
MDserial.close()
|
||||
6
PC_CONTROL_CODE/docker/md1200.env
Normal file
6
PC_CONTROL_CODE/docker/md1200.env
Normal file
@@ -0,0 +1,6 @@
|
||||
baud_rate=
|
||||
serial_adapter=
|
||||
wait_time=
|
||||
temp_factor=
|
||||
lower_treshold=
|
||||
upper_treshold=
|
||||
1
PC_CONTROL_CODE/dockerInflux/.gitignore
vendored
Normal file
1
PC_CONTROL_CODE/dockerInflux/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
.mypy_cache
|
||||
28
PC_CONTROL_CODE/dockerInflux/Dockerfile
Normal file
28
PC_CONTROL_CODE/dockerInflux/Dockerfile
Normal file
@@ -0,0 +1,28 @@
|
||||
FROM alpine:latest
|
||||
|
||||
# https://docs.docker.com/reference/dockerfile/#environment-replacement
|
||||
# ENV MD1200BAUD=38400
|
||||
# ENV SERIALADAPTER=/dev/ttyUSB0
|
||||
# ENV EPPYSLEEPY=300
|
||||
|
||||
# VOLUME [""]
|
||||
|
||||
RUN apk update && \
|
||||
apk add python3 py3-pip
|
||||
|
||||
RUN mkdir /etc/MD1200FAN/
|
||||
WORKDIR /etc/MD1200FAN/
|
||||
|
||||
COPY ./mainDocker.py /etc/MD1200FAN/
|
||||
# COPY ./requirements.txt /etc/MD1200FAN/
|
||||
|
||||
RUN python3 -m venv venv && \
|
||||
venv/bin/python3 -m pip install --upgrade pip && \
|
||||
venv/bin/pip3 install PySerial influxdb_client
|
||||
# venv/bin/pip3 install -r requirements.txt
|
||||
|
||||
# VOLUME ["/etc/MD1200FAN/"]
|
||||
|
||||
CMD ["venv/bin/python3", "mainDocker.py"]
|
||||
|
||||
# CMD ["/etc/MD1200FAN/venv/bin/python3", "/etc/MD1200FAN/mainDocker.py"]
|
||||
11
PC_CONTROL_CODE/dockerInflux/docker-compose.yml
Normal file
11
PC_CONTROL_CODE/dockerInflux/docker-compose.yml
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
services:
|
||||
mdfanchanger:
|
||||
container_name: MD_Fan_Changer
|
||||
image: yuruc3/md1200_fan_controll:v2-flux
|
||||
env_file: md1200.env
|
||||
devices:
|
||||
- /dev/ttyUSB0:/dev/ttyUSB0
|
||||
restart: unless-stopped
|
||||
privileged: false
|
||||
55
PC_CONTROL_CODE/dockerInflux/influxSend.py
Normal file
55
PC_CONTROL_CODE/dockerInflux/influxSend.py
Normal file
@@ -0,0 +1,55 @@
|
||||
import time, os, influxdb_client
|
||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS, WriteOptions
|
||||
from datetime import timedelta
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Final
|
||||
|
||||
|
||||
# INFLUXDB config
|
||||
# token = "apg1gysUeCcxdcRTMmosJTenbEppmUNi9rXlANDB2oNadBdWAu2GVTDc_q_dyo0iyYsckKaOvPRm6ba2NK0y_A=="
|
||||
INFLUXTOKEN: Final[str] = os.getenv("INFLUX_TOKEN")
|
||||
# bucket = "JBOD"
|
||||
# INFLUXBUCKET: Final[str] = os.getenv("INFLUX_BUCKET")
|
||||
# org = "staging"
|
||||
INFLUXORG: Final[str] = os.getenv("INFLUX_ORG")
|
||||
# url = "http://localhost:8086"
|
||||
INFLUXURL: Final[str] = os.getenv("INFLUX_URL")
|
||||
# measurement = "MD1200"
|
||||
measurement = os.getenv("INFLUX_MEASUREMENT")
|
||||
# MACHINE_TAG = "CHONGUS1200"
|
||||
MACHINE_TAG = os.getenv("INFLUX_MACHINE_TAG")
|
||||
# LOCATION = "HQ"
|
||||
LOCATION = os.getenv("INFLUX_LOCATION")
|
||||
# INFLX_SEPARATE_POINTS = 0.1
|
||||
INFLUX_SEPARATE_POINTS = int(os.getenv("INFLUX_SEPARATE_POINTS"))
|
||||
|
||||
# Initialize InfluxDB client and influxdb API
|
||||
inflxdb_client = influxdb_client.InfluxDBClient(url=INFLUXURL, token=INFLUXTOKEN, org=INFLUXORG)
|
||||
#write_api = inflxdb_client.write_api(write_options=SYNCHRONOUS)
|
||||
write_api = inflxdb_client.write_api(write_options=WriteOptions(batch_size=500, flush_interval=1000))
|
||||
|
||||
# Threaded flow processor
|
||||
def process_temps(inEntry):
|
||||
global MDict
|
||||
|
||||
# ---LeData---
|
||||
# {'bp1': 35, 'bp2': 29, 'sim0': 35, 'sim1': 34, 'exp0': 56, 'exp1': 54}
|
||||
# ---LeData---
|
||||
|
||||
# Prep InfluxDB data
|
||||
inflxdb_Data_To_Send = (
|
||||
influxdb_client.Point(f"{measurement}-script")
|
||||
.tag("MACHINE", MACHINE_TAG)
|
||||
.tag("LOCATION", LOCATION)
|
||||
.field("Backplane1", inEntry["bp1"])
|
||||
.field("Backplane2", inEntry["bp2"])
|
||||
.field("SASIntModule0", inEntry["sim0"])
|
||||
.field("SASIntModule1", inEntry["sim1"])
|
||||
.field("Expander0", inEntry["exp0"])
|
||||
.field("Expander1", inEntry["exp1"])
|
||||
.field("Average", inEntry["avg"])
|
||||
)
|
||||
|
||||
print("----------------")
|
||||
return ()
|
||||
350
PC_CONTROL_CODE/dockerInflux/mainDocker.py
Normal file
350
PC_CONTROL_CODE/dockerInflux/mainDocker.py
Normal file
@@ -0,0 +1,350 @@
|
||||
import time, os, influxdb_client, serial, threading
|
||||
from influxdb_client import InfluxDBClient, Point, WritePrecision
|
||||
from influxdb_client.client.write_api import SYNCHRONOUS, ASYNCHRONOUS, WriteOptions
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from typing import Final
|
||||
|
||||
# setting consts that can be customized
|
||||
|
||||
# baud rate. Prob not needed as 38400 is standard
|
||||
MD1200BAUD: Final[int] = int(os.getenv("MD1200BAUD", "38400"))
|
||||
# used if you want to run it on multiple JBODs
|
||||
SERIALADAPTER: Final[str] = os.getenv("SERIALADAPTER", "/dev/ttyUSB0")
|
||||
# Factor that defines how aggressive the temperature curve is
|
||||
TEMP_FACTOR: Final[float] = float(os.getenv("TEMP_FACTOR", "19"))
|
||||
# time between sending command to get temp and storing it. It's there to allow JBOD to answer
|
||||
EPPYSLEEPY: Final[float] = float(os.getenv("EPPYSLEEPY", "1"))
|
||||
|
||||
LOW_FAN_TRSHD: Final[float] = float(os.getenv("LOW_FAN_TRSHD", "21"))
|
||||
HIGH_FAN_TRSHD: Final[float] = float(os.getenv("HIGH_FAN_TRSHD", "40"))
|
||||
|
||||
GETTMPCMND: Final[str] = os.getenv("GETTMPCMND", "_temp_rd")
|
||||
SETFANCMND: Final[str] = os.getenv("SETFANCMND", "set_speed")
|
||||
|
||||
DEFOUTPRCNTG: Final[float] = float(os.getenv("DEFOUTPRCNTG", "24"))
|
||||
|
||||
MDSERIALTIMEOUT: Final[float] = float(os.getenv("MDSERIALTIMEOUT", "1"))
|
||||
|
||||
TEMPREADINTERVAL: Final[float] = float(os.getenv("TEMPREADINTERVAL", "15"))
|
||||
|
||||
# If True or yes then we good
|
||||
TEMPSETING = os.getenv("TEMPSETING", "1").strip().lower() in ("1", "true", "yes", "on")
|
||||
|
||||
PROCESSTEMPWAITTIME: Final[float] = float(os.getenv("PROCESSTEMPWAITTIME", "0.75"))
|
||||
|
||||
BACKOFFTIME: Final[float] = float(os.getenv("BACKOFFTIME", "5"))
|
||||
|
||||
INFLUX_MAX_RETRIES: Final[int] = int(os.getenv("INFLUX_MAX_RETRIES", "3"))
|
||||
|
||||
# INFLUXDB config
|
||||
# should Influx be used?
|
||||
USEINFLUX: Final[bool] = os.getenv("USEINFLUX", "True").strip().lower() in ("1", "true", "yes", "on")
|
||||
# token = "apg1gysUeCcxdcRTMmosJTenbEppmUNi9rXlANDB2oNadBdWAu2GVTDc_q_dyo0iyYsckKaOvPRm6ba2NK0y_A=="
|
||||
INFLUXTOKEN: Final[str] = str(os.getenv("INFLUX_TOKEN", "0"))
|
||||
# bucket = "JBOD"
|
||||
INFLUXBUCKET: Final[str] = str(os.getenv("INFLUX_BUCKET", "0"))
|
||||
# org = "staging"
|
||||
INFLUXORG: Final[str] = str(os.getenv("INFLUX_ORG", "0"))
|
||||
# url = "http://localhost:8086"
|
||||
INFLUXURL: Final[str] = str(os.getenv("INFLUX_URL", "0"))
|
||||
# measurement = "MD1200"
|
||||
INFLUXMEASUREMENT: Final[str] = str(os.getenv("INFLUX_MEASUREMENT", "0"))
|
||||
# MACHINE_TAG = "CHONGUS1200"
|
||||
MACHINE_TAG: Final[str] = str(os.getenv("INFLUX_MACHINE_TAG", "0"))
|
||||
# LOCATION = "HQ"
|
||||
LOCATION: Final[str] = str(os.getenv("INFLUX_LOCATION", "0"))
|
||||
# INFLX_SEPARATE_POINTS = 0.1
|
||||
# INFLUX_SEPARATE_POINTS = float(os.getenv("INFLUX_SEPARATE_POINTS"), 0.1)
|
||||
|
||||
# init
|
||||
MDserial = serial.Serial(
|
||||
port=SERIALADAPTER,\
|
||||
baudrate=MD1200BAUD,\
|
||||
parity=serial.PARITY_NONE,\
|
||||
stopbits=serial.STOPBITS_ONE,\
|
||||
bytesize=serial.EIGHTBITS,\
|
||||
timeout=MDSERIALTIMEOUT)
|
||||
|
||||
# lastTempReading: float = time.time()
|
||||
setSpeedrcode = 21
|
||||
MDtempDict: dict = {}
|
||||
MDict: dict = {}
|
||||
currentSerialUsage = threading.Lock()
|
||||
fluxSending: bool = False
|
||||
currentTime: float = 0
|
||||
lastTempReading: float = 0
|
||||
# Initialize InfluxDB client and influxdb API
|
||||
# ---------------------UNCOMMENT-----------------------
|
||||
if USEINFLUX:
|
||||
inflxdb_client = influxdb_client.InfluxDBClient(url=INFLUXURL, token=INFLUXTOKEN, org=INFLUXORG)
|
||||
write_api = inflxdb_client.write_api(write_options=SYNCHRONOUS)
|
||||
inflxdb_LeData: list = []
|
||||
# ---------------------UNCOMMENT-----------------------
|
||||
|
||||
|
||||
# Just a helper function for process_temps to avoid db errors on flapping network
|
||||
def process_temps_dbsend(inpdatatosend) -> bool:
|
||||
if not USEINFLUX:
|
||||
return True
|
||||
try:
|
||||
write_api.write(bucket=INFLUXBUCKET, org=INFLUXORG, record=inpdatatosend)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Influx write error {e}", flush=True)
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def getTemp() -> dict:
|
||||
global MDict, fluxSending
|
||||
|
||||
|
||||
with currentSerialUsage:
|
||||
MDserial.write(f"{GETTMPCMND}\n\r".encode())
|
||||
time.sleep(1)
|
||||
MDreturning = MDserial.read_until(" >").decode()
|
||||
|
||||
|
||||
|
||||
# MDict = {}
|
||||
|
||||
# Sanitise output
|
||||
MDsanit = MDreturning.splitlines()
|
||||
|
||||
#if there is smth do smth
|
||||
if MDreturning:
|
||||
|
||||
for line in MDsanit:
|
||||
|
||||
if ">" in line or "b'" in line:
|
||||
continue
|
||||
|
||||
matchstm = line[2:6]
|
||||
|
||||
match matchstm:
|
||||
case "BP_1":
|
||||
MDict["bp1"] = int(line[12:14])
|
||||
case "BP_2":
|
||||
MDict["bp2"] = int(line[12:14])
|
||||
case "SIM0":
|
||||
MDict["sim0"] = int(line[12:14])
|
||||
case "SIM1":
|
||||
MDict["sim1"] = int(line[12:14])
|
||||
case "EXP0":
|
||||
MDict["exp0"] = int(line[12:14])
|
||||
case "EXP1":
|
||||
MDict["exp1"] = int(line[12:14])
|
||||
# case "AVG":
|
||||
# MDict["avg"] = int(line[12:14])
|
||||
# MDict["avg"] = int(line.strip().split("=")[1].strip().replace("c", ""))
|
||||
# try:
|
||||
# # Extract number from e.g. ' AVG = 40c'
|
||||
# temp = int(line.strip().split("=")[1].strip().replace("c", ""))
|
||||
# MDict["avg"] = temp
|
||||
# except Exception as e:
|
||||
# # print(f"[WARN] Failed to parse AVG line: {line} ({e})", flush=True)
|
||||
# pass
|
||||
case _:
|
||||
# try to catch the AVG line like: " AVG = 40c"
|
||||
stripped = line.strip()
|
||||
if stripped.startswith("AVG"):
|
||||
try:
|
||||
temp = int(stripped.split("=")[1].strip().replace("c", ""))
|
||||
MDict["avg"] = temp
|
||||
except Exception as e:
|
||||
print(f"[WARN] Could not parse AVG line: {line} ({e})", flush=True)
|
||||
continue
|
||||
# continue
|
||||
|
||||
|
||||
# {'bp1': 35, 'bp2': 29, 'sim0': 35, 'sim1': 33, 'exp0': 56, 'exp1': 54, 'avg': 40}
|
||||
# process_temps(MDict)
|
||||
fluxSending = True
|
||||
|
||||
return MDict
|
||||
else:
|
||||
return {"error": "unidentified"}
|
||||
|
||||
|
||||
def setSpeed(inSpeeDict: dict) -> int:
|
||||
|
||||
bpavrg = 0
|
||||
# default
|
||||
outfanprcntg = 0
|
||||
|
||||
# get backplanbe average
|
||||
if "bp1" in inSpeeDict and "bp2" in inSpeeDict:
|
||||
bpavrg = (inSpeeDict["bp1"] + inSpeeDict["bp2"]) /2
|
||||
#outfanprcntg = int((bpavrg / (HIGH_FAN_TRSHD - LOW_FAN_TRSHD)) * TEMP_FACTOR)
|
||||
outfanprcntg = int((bpavrg / (HIGH_FAN_TRSHD - LOW_FAN_TRSHD)) * TEMP_FACTOR)
|
||||
# os.system(f"echo setting {outfanprcntg}%")
|
||||
|
||||
with currentSerialUsage:
|
||||
|
||||
# Set fan speed
|
||||
if outfanprcntg >= 20:
|
||||
MDserial.write((f"{SETFANCMND} {str(outfanprcntg)} \n\r").encode())
|
||||
print(f"setting {outfanprcntg}%", flush=True)
|
||||
|
||||
return outfanprcntg
|
||||
else:
|
||||
# Set default value
|
||||
MDserial.write((f"{SETFANCMND} {str(DEFOUTPRCNTG)} \n\r").encode())
|
||||
|
||||
return outfanprcntg
|
||||
|
||||
|
||||
# If something goes super wrong
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
# Check if UART is used
|
||||
# Not neede because when defining MDserial it gets automatically opened
|
||||
# Will leave it here anyway
|
||||
# try:
|
||||
# MDserial.open()
|
||||
# except serial.serialutil.SerialException:
|
||||
# # MDserial.close()
|
||||
# # MDserial.open()
|
||||
# print("Port allready opened.\nTry closing it first")
|
||||
|
||||
# Threaded flow processor
|
||||
def process_temps() -> None:
|
||||
global MDict, fluxSending, setSpeedrcode
|
||||
|
||||
while True:
|
||||
# ---LeData---
|
||||
# {'bp1': 35, 'bp2': 29, 'sim0': 35, 'sim1': 34, 'exp0': 56, 'exp1': 54}
|
||||
# ---LeData---
|
||||
|
||||
if fluxSending:
|
||||
# Prep InfluxDB data
|
||||
|
||||
# build local copy in case MDict changes while executing
|
||||
MDictLocalCopy = MDict.copy()
|
||||
try:
|
||||
inflxdb_Data_To_Send = (
|
||||
influxdb_client.Point(f"{INFLUXMEASUREMENT}-script")
|
||||
.tag("MACHINE", MACHINE_TAG)
|
||||
.tag("LOCATION", LOCATION)
|
||||
.field("Backplane1", MDictLocalCopy["bp1"])
|
||||
.field("Backplane2", MDictLocalCopy["bp2"])
|
||||
.field("SASIntModule0", MDictLocalCopy["sim0"])
|
||||
.field("SASIntModule1", MDictLocalCopy["sim1"])
|
||||
.field("Expander0", MDictLocalCopy["exp0"])
|
||||
.field("Expander1", MDictLocalCopy["exp1"])
|
||||
.field("Average", MDictLocalCopy["avg"])
|
||||
.field("FanSpeed", setSpeedrcode)
|
||||
)
|
||||
except KeyError:
|
||||
time.sleep(BACKOFFTIME)
|
||||
continue
|
||||
|
||||
# Prep/append data
|
||||
inflxdb_LeData.append(inflxdb_Data_To_Send)
|
||||
|
||||
# Issue YuruC3/MD1200#7 fix
|
||||
if not process_temps_dbsend(inflxdb_Data_To_Send):
|
||||
i = 0
|
||||
while i < INFLUX_MAX_RETRIES:
|
||||
if process_temps_dbsend(inflxdb_Data_To_Send):
|
||||
print("Sending data to InfluxDB", flush=True)
|
||||
break
|
||||
else:
|
||||
time.sleep(1)
|
||||
i += 1
|
||||
else:
|
||||
print(f"Failed to send data to InfluxDB after {INFLUX_MAX_RETRIES} retires", flush=True)
|
||||
|
||||
else:
|
||||
print("Sending data to InfluxDB", flush=True)
|
||||
|
||||
|
||||
|
||||
# Clean up before another lo#op, 0.75
|
||||
inflxdb_LeData.clear()
|
||||
|
||||
fluxSending = False
|
||||
|
||||
else:
|
||||
time.sleep(PROCESSTEMPWAITTIME)
|
||||
|
||||
|
||||
|
||||
|
||||
# Init
|
||||
MDict = getTemp()
|
||||
lastTempReading = time.time()
|
||||
|
||||
def mainCodeHere() -> None:
|
||||
global setSpeedrcode
|
||||
while True:
|
||||
global MDict, fluxSending, currentTime, lastTempReading
|
||||
# https://stackoverflow.com/questions/52578122/not-able-to-send-the-enter-command-on-pyserial
|
||||
|
||||
# get temperature data, wait for MD1200 to answer and store
|
||||
|
||||
currentTime = time.time()
|
||||
|
||||
if currentTime - lastTempReading >= TEMPREADINTERVAL:
|
||||
|
||||
getTemp()
|
||||
lastTempReading = currentTime
|
||||
|
||||
if MDict and TEMPSETING:
|
||||
setSpeedrcode = setSpeed(MDict)
|
||||
|
||||
# good
|
||||
if setSpeedrcode == 0:
|
||||
pass
|
||||
# print("Were mint", flush=True)
|
||||
# time.sleep(EPPYSLEEPY)
|
||||
# not good
|
||||
elif setSpeedrcode == 1:
|
||||
print("Ambigous temperature readings.\nFalling back to safe values.", flush=True)
|
||||
# time.sleep(EPPYSLEEPY)
|
||||
# very not good
|
||||
elif setSpeedrcode == -1:
|
||||
print("o nyo", flush=True)
|
||||
exit()
|
||||
# very very very not good
|
||||
else:
|
||||
print("idk", flush=True)
|
||||
exit()
|
||||
elif TEMPSETING == False:
|
||||
print(f"Waiting to get temp", flush=True)
|
||||
pass
|
||||
else:
|
||||
print(f"temperature not yet pulled.\nFalling back do default fan speed", flush=True)
|
||||
# os.system(f"echo temperature not yet pulled.\nFalling back do default fan speed")
|
||||
|
||||
with currentSerialUsage:
|
||||
MDserial.write((f"{SETFANCMND} {str(DEFOUTPRCNTG)} \n\r").encode())
|
||||
|
||||
|
||||
|
||||
time.sleep(EPPYSLEEPY)
|
||||
|
||||
|
||||
# Prepare threads and launch them
|
||||
|
||||
|
||||
# daemon to make docker exit smoother
|
||||
thread_main = threading.Thread(target=mainCodeHere, daemon=True)
|
||||
threads = [thread_main]
|
||||
|
||||
if USEINFLUX:
|
||||
thread_flux = threading.Thread(target=process_temps, daemon=True)
|
||||
threads.append(thread_flux)
|
||||
|
||||
for thr in threads:
|
||||
thr.start()
|
||||
|
||||
# Join both (this will block forever, which is fine for a daemon)
|
||||
for thr in threads:
|
||||
thr.join()
|
||||
|
||||
|
||||
|
||||
|
||||
21
PC_CONTROL_CODE/dockerInflux/md1200.env
Normal file
21
PC_CONTROL_CODE/dockerInflux/md1200.env
Normal file
@@ -0,0 +1,21 @@
|
||||
# MD1200BAUD=
|
||||
SERIALADAPTER=/dev/ttyUSB0
|
||||
|
||||
# These are (for me) working values
|
||||
EPPYSLEEPY=1.5
|
||||
MDSERIALTIMEOUT=2
|
||||
TEMPREADINTERVAL=30
|
||||
|
||||
|
||||
TEMP_FACTOR=16
|
||||
# LOW_FAN_TRSHD=21
|
||||
# HIGH_FAN_TRSHD=40
|
||||
|
||||
# Influxdb config
|
||||
INFLUX_TOKEN=-3rZgq6EprG9i-gKqBDSFCC3hTS3U49fxGkg==
|
||||
INFLUX_BUCKET=JBOD
|
||||
INFLUX_ORG=FUBUKUS
|
||||
INFLUX_URL=http://192.168.1.101:8086
|
||||
INFLUX_MEASUREMENT=MD1200
|
||||
INFLUX_MACHINE_TAG=CHONGUS1200
|
||||
INFLUX_LOCATION=HQ
|
||||
19
PC_CONTROL_CODE/dockerInflux/md1200.env.defaults
Normal file
19
PC_CONTROL_CODE/dockerInflux/md1200.env.defaults
Normal file
@@ -0,0 +1,19 @@
|
||||
MD1200BAUD=38400
|
||||
SERIALADAPTER=/dev/ttyUSB0
|
||||
|
||||
EPPYSLEEPY=1
|
||||
MDSERIALTIMEOUT=1
|
||||
TEMPREADINTERVAL=15
|
||||
|
||||
TEMP_FACTOR=19
|
||||
LOW_FAN_TRSHD=21
|
||||
HIGH_FAN_TRSHD=40
|
||||
|
||||
# Influxdb config
|
||||
INFLUX_TOKEN===
|
||||
INFLUX_BUCKET=JBOD
|
||||
INFLUX_ORG=staging
|
||||
INFLUX_URL=http://localhost:8086
|
||||
INFLUX_MEASUREMENT=MD1200
|
||||
INFLUX_MACHINE_TAG=CHONGUS1200
|
||||
INFLUX_LOCATION=HQ
|
||||
131
PC_CONTROL_CODE/main.py
Normal file
131
PC_CONTROL_CODE/main.py
Normal file
@@ -0,0 +1,131 @@
|
||||
import serial, time
|
||||
|
||||
# CONST
|
||||
MD1200BAUD = 38400
|
||||
SERIALADAPTER = "/dev/ttyUSB0"
|
||||
GETTEMP = "_temp_rd"
|
||||
SETFANPRCNT = "set_speed"
|
||||
EPPYSLEEPY = 1 # 1 second
|
||||
#EPPYSLEEPY = 150 # 2,5 minutes
|
||||
|
||||
# init
|
||||
MDserial = serial.Serial(
|
||||
port=SERIALADAPTER,\
|
||||
baudrate=MD1200BAUD,\
|
||||
parity=serial.PARITY_NONE,\
|
||||
stopbits=serial.STOPBITS_ONE,\
|
||||
bytesize=serial.EIGHTBITS,\
|
||||
timeout=1)
|
||||
|
||||
|
||||
|
||||
def getTemp(inpMDreturning):
|
||||
MDict = {}
|
||||
|
||||
# Sanitise output
|
||||
MDsanit = inpMDreturning.splitlines()
|
||||
|
||||
#if there is smth do smth
|
||||
if inpMDreturning:
|
||||
|
||||
for line in MDsanit:
|
||||
|
||||
if ">" in line or "b'" in line:
|
||||
continue
|
||||
|
||||
matchstm = line[2:6]
|
||||
|
||||
match matchstm:
|
||||
case "BP_1":
|
||||
MDict["bp1"] = int(line[12:14])
|
||||
case "BP_2":
|
||||
MDict["bp2"] = int(line[12:14])
|
||||
case "SIM0":
|
||||
MDict["sim0"] = int(line[12:14])
|
||||
case "SIM1":
|
||||
MDict["sim1"] = int(line[12:14])
|
||||
case "EXP0":
|
||||
MDict["exp0"] = int(line[12:14])
|
||||
case "EXP1":
|
||||
MDict["exp1"] = int(line[12:14])
|
||||
case "AVG":
|
||||
MDict["avg"] = int(line[12:14])
|
||||
case _:
|
||||
continue
|
||||
|
||||
return MDict
|
||||
|
||||
|
||||
def setSpeed(inSpeeDict: dict):
|
||||
|
||||
bpavrg = 0
|
||||
# Some safe fan speedvalue
|
||||
defoutprntg = 27
|
||||
# default
|
||||
outfanprcntg = 0
|
||||
|
||||
# Decide on fan speeds
|
||||
LOW_FAN_TRSHD = 21
|
||||
HIGH_FAN_TRSHD = 40
|
||||
TEMP_FACTOR = 21
|
||||
|
||||
# get backplanbe average
|
||||
if inSpeeDict["bp1"] and inSpeeDict["bp2"]:
|
||||
bpavrg = (inSpeeDict["bp1"] + inSpeeDict["bp2"]) /2
|
||||
|
||||
outfanprcntg = int((bpavrg / (HIGH_FAN_TRSHD - LOW_FAN_TRSHD)) * TEMP_FACTOR)
|
||||
|
||||
# Set fan speed
|
||||
if outfanprcntg >= 20:
|
||||
MDserial.write(("set_speed " + str(outfanprcntg) + " \n\r").encode())
|
||||
print(f"setting {outfanprcntg}%")
|
||||
return 0
|
||||
else:
|
||||
# Set default value
|
||||
MDserial.write(("set_speed " + str(defoutprntg) + " \n\r").encode())
|
||||
return 1
|
||||
|
||||
# If something goes super wrong
|
||||
return -1
|
||||
|
||||
|
||||
|
||||
# Check if UART is used
|
||||
# Not neede because when defining MDserial it gets automatically opened
|
||||
# Will leave it here anyway
|
||||
# try:
|
||||
# MDserial.open()
|
||||
# except serial.serialutil.SerialException:
|
||||
# # MDserial.close()
|
||||
# # MDserial.open()
|
||||
# print("Port allready opened.\nTry closing it first")
|
||||
|
||||
while True:
|
||||
# https://stackoverflow.com/questions/52578122/not-able-to-send-the-enter-command-on-pyserial
|
||||
MDserial.write("_temp_rd\n\r".encode())
|
||||
time.sleep(1)
|
||||
MDreturning = MDserial.read_until(" >").decode()
|
||||
|
||||
MDtempDict = getTemp(MDreturning)
|
||||
setSpeedrcode = setSpeed(MDtempDict)
|
||||
|
||||
# good
|
||||
if setSpeedrcode == 0:
|
||||
# print("Were mint")
|
||||
time.sleep(EPPYSLEEPY)
|
||||
# not good
|
||||
elif setSpeedrcode == 1:
|
||||
print("Ambigous temperature readings.\nFalling back to safe values.")
|
||||
time.sleep(EPPYSLEEPY)
|
||||
# very not good
|
||||
elif setSpeedrcode == -1:
|
||||
print("o nyo")
|
||||
exit()
|
||||
# very very very not good
|
||||
else:
|
||||
print("idk")
|
||||
exit()
|
||||
|
||||
|
||||
print("closing port")
|
||||
MDserial.close()
|
||||
1
PC_CONTROL_CODE/requirements.txt
Normal file
1
PC_CONTROL_CODE/requirements.txt
Normal file
@@ -0,0 +1 @@
|
||||
pySerial == 3.5
|
||||
26
PC_CONTROL_CODE/systemd/MD1200Fans.example.service
Normal file
26
PC_CONTROL_CODE/systemd/MD1200Fans.example.service
Normal file
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=Adjust MD1200/MD1220 fan speeds
|
||||
After=multi-user.target
|
||||
# Place in /etc/systemd/system/
|
||||
|
||||
[Service]
|
||||
User=yuru
|
||||
Group=yuru
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
# EnvironmentFile=/etc/NetFlux/netflow.env
|
||||
# User=myuser
|
||||
WorkingDirectory=/etc/MD1200FAN/
|
||||
ExecStart=/etc/MD1200FAN/venv/bin/python3 /etc/MD1200FAN/main.py --serve-in-foreground
|
||||
#StandardInput=tty-force
|
||||
|
||||
# Log file will be create if it doesn't exist
|
||||
StandardOutput=append:/var/log/MD1200FAN.py.log
|
||||
StandardError=append:/var/log/MD1200FAN.py.errlog
|
||||
|
||||
# StandardOutput=syslog
|
||||
# StandardError=syslog
|
||||
# SyslogIdentifier=NetFlowInflux
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
26
PC_CONTROL_CODE/systemd/MD1200Fans.service
Normal file
26
PC_CONTROL_CODE/systemd/MD1200Fans.service
Normal file
@@ -0,0 +1,26 @@
|
||||
[Unit]
|
||||
Description=Adjust MD1200/MD1220 fan speeds
|
||||
After=multi-user.target
|
||||
# Place in /etc/systemd/system/
|
||||
|
||||
[Service]
|
||||
User=<CHANGE>
|
||||
Group=<CHANGE>
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
# EnvironmentFile=/etc/NetFlux/netflow.env
|
||||
# User=myuser
|
||||
WorkingDirectory=/dir/to/script/
|
||||
ExecStart=/dir/to/script'sVENV/venv/bin/python3 /dir/to/script/main.py --serve-in-foreground
|
||||
#StandardInput=tty-force
|
||||
|
||||
# Log file will be create if it doesn't exist
|
||||
StandardOutput=append:/var/log/MD1200FAN.py.log
|
||||
StandardError=append:/var/log/MD1200FAN.py.errlog
|
||||
|
||||
# StandardOutput=syslog
|
||||
# StandardError=syslog
|
||||
# SyslogIdentifier=NetFlowInflux
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
8
PC_CONTROL_CODE/systemd/README.md
Normal file
8
PC_CONTROL_CODE/systemd/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# What you need to prepare
|
||||
|
||||
virtual enviroment in python with installed packages
|
||||
|
||||
python script and InfluxDB
|
||||
|
||||
## Change stuff
|
||||
In .service file change everything that has <SOMETHIN_LIKE_THIS> and /path/to/dir
|
||||
226
PC_CONTROL_CODE/test.py
Normal file
226
PC_CONTROL_CODE/test.py
Normal file
@@ -0,0 +1,226 @@
|
||||
import serial, time
|
||||
|
||||
# CONST
|
||||
MD1200BAUD = 38400
|
||||
SERIALADAPTER = "/dev/ttyUSB0"
|
||||
GETTEMP = "_temp_rd"
|
||||
SETFANPRCNT = "set_speed"
|
||||
EPYSLEEPY = 300 # 5 minutes
|
||||
#EPYSLEEPY = 150 # 2,5 minutes
|
||||
|
||||
# init
|
||||
# MDserial = serial.Serial(
|
||||
# port=SERIALADAPTER,\
|
||||
# baudrate=MD1200BAUD,\
|
||||
# parity=serial.PARITY_NONE,\
|
||||
# stopbits=serial.STOPBITS_ONE,\
|
||||
# bytesize=serial.EIGHTBITS,\
|
||||
# timeout=1)
|
||||
|
||||
# After running .encode() on output
|
||||
MDreturn = "b'\r\nBlueDress.105.001 >_temp_rd\r\n\r\n BP_1[2] = 24c\r\n BP_2[3] = 24c\r\n SIM0[0] = 26c\r\n SIM1[1] = 29c\r\n EXP0[4] = 43c\r\n EXP1[5] = 47c\r\n\r\n AVG = 32c\r\n\r\nBlueDress.105.001 >'"
|
||||
# before running .encode() on output
|
||||
TrueMDeturn = MDreturn.encode()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def getTemp(inpMDreturning):
|
||||
# bp1 = 0
|
||||
# bp2 = 0
|
||||
# exp0 = 0
|
||||
# exp1 = 0
|
||||
# simm0 = 0
|
||||
# simm1 = 0
|
||||
# averr = 0
|
||||
MDict = {}
|
||||
|
||||
# print("1")
|
||||
|
||||
# Sanitise output
|
||||
MDsanit = inpMDreturning.splitlines()
|
||||
|
||||
#if there is smth do smth
|
||||
if inpMDreturning:
|
||||
# print("2")
|
||||
|
||||
# print(MDsanit)
|
||||
for line in MDsanit:
|
||||
# print(line)
|
||||
|
||||
if ">" in line or "b'" in line:
|
||||
continue
|
||||
|
||||
# print(line[2:])
|
||||
# if "BP_1" in line[2:]:
|
||||
# print("yeeee")
|
||||
|
||||
matchstm = line[2:6]
|
||||
|
||||
# print(matchstm)
|
||||
|
||||
match matchstm:
|
||||
case "BP_1":
|
||||
# print("BP_1 " + line[12:14])
|
||||
# bp1 = line[12:14]
|
||||
MDict["bp1"] = int(line[12:14])
|
||||
case "BP_2":
|
||||
# print("BP_2 " + line[12:14])
|
||||
# bp2 = line[12:14]
|
||||
MDict["bp2"] = int(line[12:14])
|
||||
case "SIM0":
|
||||
# print("SIM0 " + line[12:14])
|
||||
# simm0 = line[12:14]
|
||||
MDict["sim0"] = int(line[12:14])
|
||||
case "SIM1":
|
||||
# print("SIM1 " + line[12:14])
|
||||
# simm1 = line[12:14]
|
||||
MDict["sim1"] = int(line[12:14])
|
||||
case "EXP0":
|
||||
# print("EXP0 " + line[12:14])
|
||||
# exp0 = line[12:14]
|
||||
MDict["exp0"] = int(line[12:14])
|
||||
case "EXP1":
|
||||
# print("EXP1 " + line[12:14])
|
||||
# exp1 = line[12:14]
|
||||
MDict["exp1"] = int(line[12:14])
|
||||
case "AVG":
|
||||
# print("AVG " + line[12:14])
|
||||
# averr = line[12:14]
|
||||
MDict["avg"] = int(line[12:14])
|
||||
case _:
|
||||
print("ay men")
|
||||
# continue
|
||||
|
||||
# for thing in line.split(" ")[2:]:
|
||||
# print(thing)
|
||||
# print(line[12:14])
|
||||
# print(MDsanit.split("\n"))
|
||||
|
||||
return MDict
|
||||
# print(MDict)
|
||||
|
||||
|
||||
# for key, thing in getTemp(MDreturn).items():
|
||||
# print(key, thing)
|
||||
|
||||
def setSpeed(inSpeeDict: dict):
|
||||
print("skibidi")
|
||||
|
||||
bpavrg = 0
|
||||
# Some safe fan speedvalue
|
||||
defoutprntg = 27
|
||||
# default
|
||||
outfanprcntg = 0
|
||||
|
||||
# Decide on fan speeds
|
||||
LOW_FAN_TRSHD = 21
|
||||
HIGH_FAN_TRSHD = 40
|
||||
TEMP_FACTOR = 21
|
||||
|
||||
# DEBUG
|
||||
# for key, thing in inSpeeDict.items():
|
||||
# print(key, thing)
|
||||
|
||||
# get backplanbe average
|
||||
if inSpeeDict["bp1"] and inSpeeDict["bp2"]:
|
||||
bpavrg = (inSpeeDict["bp1"] + inSpeeDict["bp2"]) /2
|
||||
|
||||
|
||||
outfanprcntg = int((bpavrg / (HIGH_FAN_TRSHD - LOW_FAN_TRSHD)) * TEMP_FACTOR)
|
||||
print(f"outfanprcntg is {outfanprcntg}")
|
||||
|
||||
# Set fan speed
|
||||
if outfanprcntg >= 20:
|
||||
# MDserial.write(("set_speed " + str(outfanprcntg) + " \n\r").encode())
|
||||
return 0
|
||||
else:
|
||||
# Set default value
|
||||
# MDserial.write(("set_speed " + str(defoutprntg) + " \n\r").encode())
|
||||
return 1
|
||||
|
||||
# If something goes super wrong
|
||||
return -1
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
while True:
|
||||
# if True:
|
||||
# MDserial.write("_temp_rd\n\r".encode())
|
||||
|
||||
# CHANGE AFTER TESTING
|
||||
# MDreturning = MDserial.read_until(" >").decode()
|
||||
MDreturning = MDreturn
|
||||
|
||||
# sleep(50)
|
||||
|
||||
MDtempDict = getTemp(MDreturning)
|
||||
|
||||
# setSpeed(MDtempDict)
|
||||
|
||||
setSpeedrcode = setSpeed(MDtempDict)
|
||||
|
||||
# good
|
||||
if setSpeedrcode == 0:
|
||||
print("Were mint")
|
||||
time.sleep(EPYSLEEPY)
|
||||
# not good
|
||||
elif setSpeedrcode == 1:
|
||||
print("Ambigous temperature readings.\nFalling back to safe values.")
|
||||
time.sleep(EPYSLEEPY)
|
||||
# very not good
|
||||
elif setSpeedrcode == -1:
|
||||
print("o nyo")
|
||||
exit()
|
||||
# very very very not good
|
||||
else:
|
||||
print("idk")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def getTemp():
|
||||
# bp1 = 0
|
||||
# bp2 = 0
|
||||
# #exp0 = 0
|
||||
# #exp1 = 0
|
||||
# #simm0 = 0
|
||||
# #simm1 = 0
|
||||
# getMD1200tempReturn = ""
|
||||
|
||||
# MDserial.write(GETTEMP.encode())
|
||||
|
||||
# print(MDserial.readlines())
|
||||
|
||||
# MDreturning = MDserial.readlines().decode()
|
||||
# #if there is smth do smth
|
||||
# if len(MDreturning) >= 1:
|
||||
# print("skibidi")
|
||||
# return MDreturning
|
||||
|
||||
# try:
|
||||
# MDserial.open()
|
||||
# except serial.serialutil.SerialException:
|
||||
# print("Port allready opened.\nTry closing it first")
|
||||
|
||||
|
||||
# # https://stackoverflow.com/questions/52578122/not-able-to-send-the-enter-command-on-pyserial
|
||||
# MDserial.write("_temp_rd\n\r".encode())
|
||||
|
||||
|
||||
# print(MDserial.read_until(" >"))
|
||||
|
||||
# fanprct = 23
|
||||
|
||||
# MDserial.write(f"set_speed {fanprct}\n\r".encode())
|
||||
|
||||
# MDserial.close()
|
||||
54
README.md
54
README.md
@@ -1,8 +1,58 @@
|
||||
# Python scripts for changing fan speed on MD1200
|
||||
# MD1200 fan noise reduction
|
||||
|
||||
This adjusts fan speed "dynamically" based on average backplane temperature reading.
|
||||
A set of scripts that automagically set fan speed on a MD1200 (probably MD1220 as well) based on internal temperature readings.
|
||||
|
||||
## PC
|
||||
|
||||
### Docker
|
||||
|
||||
In .env file change:
|
||||
|
||||
```serial_adapter``` which is a serial port you're using.
|
||||
On linux it is /dev/ttyUSBx and on windows it is COMx
|
||||
|
||||
```wait_time``` is the interval in which script is checking temperature. By default it is 300 seconds, which is 5 minutes.
|
||||
|
||||
Then run with ```sudo docker-compose up -d```
|
||||
|
||||
To see output run ```sudo docker container logs MD_Fan_Changer```
|
||||
|
||||
### Systemd
|
||||
|
||||
First create virtual enviroment
|
||||
|
||||
```
|
||||
python3 -m venv venv
|
||||
```
|
||||
|
||||
Then install required modules
|
||||
```
|
||||
venv/bin/pip3 install PySerial
|
||||
```
|
||||
After that you just need to change a few things
|
||||
```SERIALADAPTER``` to a port you're using.
|
||||
|
||||
On linux it is /dev/ttyUSBx and on windows it is COMx
|
||||
|
||||
```EPPYSLEEPY``` is the interval in which script is checking temperature. By default it is 300 seconds, which is 5 minutes.
|
||||
|
||||
### Proxmox LXC
|
||||
|
||||
You can also run it in LXC container on your Proxmox host. Just follow the [systemd](###systemd) instructions.
|
||||
|
||||
Here you will also need to add ```/dev/ttyUSBx``` to your LXC container. You do it under Resources -> Add -> Device Passthrough -> ```/dev/ttyUSBx``` as Device Path.
|
||||
|
||||
## STM32F103C6T6
|
||||
|
||||
I think it needs a MAX2323 between MD1200.
|
||||
|
||||
Will look into that.
|
||||
|
||||
## Arduino Nano
|
||||
|
||||
Same here
|
||||
|
||||
|
||||
### FAQ
|
||||
|
||||
dc: yuruc3
|
||||
10
STM32_CONTROL/.vscode/extensions.json
vendored
Normal file
10
STM32_CONTROL/.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
BIN
STM32_CONTROL/LiterallyMe.gif
Normal file
BIN
STM32_CONTROL/LiterallyMe.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 MiB |
@@ -8,11 +8,13 @@
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:genericSTM32F103C6]
|
||||
[env:bluepill_f103c6]
|
||||
platform = ststm32
|
||||
board = genericSTM32F103C6
|
||||
framework = arduino
|
||||
board = bluepill_f103c6
|
||||
framework = stm32cube
|
||||
lib_deps = adafruit/DHT sensor library@^1.4.6
|
||||
debug_tool = stlink
|
||||
upload_protocol = stlink
|
||||
; Enable RX and TX 3
|
||||
; build_flags = -D SERIAL_USB -D ENABLE_HWSERIAL3
|
||||
; build_flags = -D SERIAL_USB -D ENABLE_HWSERIAL1 -D ENABLE_HWSERIAL2
|
||||
; build_flags = -DENABLE_HWSERIAL1
|
||||
@@ -1,207 +1,130 @@
|
||||
#include <Arduino.h>
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
// VARS
|
||||
const int MD1200BAUDS = 38400; // From what I've read it is always 38400
|
||||
//const int EPYSLEEPY = 600000; / 10 minutes
|
||||
const int EPYSLEEPY = 300000; // 5 minutes
|
||||
//const int EPYSLEEPY = 150000; // 2,5 minutes
|
||||
HardwareSerial Serial1(31, 30);
|
||||
#include <stm32f1xx_hal.h>
|
||||
|
||||
// declarations
|
||||
int getTemp();
|
||||
int setFanTrsh(int);
|
||||
UART_HandleTypeDef huart1;
|
||||
|
||||
void setup() {
|
||||
// Setup connection to MD1200
|
||||
// Serial1 because we're using RX/TX pins
|
||||
Serial1.begin(MD1200BAUDS);
|
||||
// --- Function prototypes ---
|
||||
void SystemClock_Config(void);
|
||||
static void MX_GPIO_Init(void);
|
||||
static void MX_USART1_UART_Init(void);
|
||||
|
||||
// Just debug
|
||||
Serial.begin(9600);
|
||||
Serial.print("skibidi");
|
||||
// --- Optional RX buffer for interrupt ---
|
||||
uint8_t rx_byte;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
HAL_Init();
|
||||
SystemClock_Config();
|
||||
MX_GPIO_Init();
|
||||
MX_USART1_UART_Init();
|
||||
|
||||
char msg[] = "UART started at 38400 baud\r\n";
|
||||
|
||||
// Send a startup message
|
||||
HAL_UART_Transmit(&huart1, (uint8_t*)msg, sizeof(msg)-1, HAL_MAX_DELAY);
|
||||
|
||||
// Start interrupt-based receive of one byte
|
||||
HAL_UART_Receive_IT(&huart1, &rx_byte, 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// Send a heartbeat message every second
|
||||
char heartbeat[] = "Ping\r\n";
|
||||
HAL_UART_Transmit(&huart1, (uint8_t*)heartbeat, sizeof(heartbeat)-1, HAL_MAX_DELAY);
|
||||
|
||||
HAL_Delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
int fanPercnt = getTemp();
|
||||
|
||||
if (fanPercnt < 10) {
|
||||
setFanTrsh(fanPercnt);
|
||||
}
|
||||
|
||||
/*
|
||||
check temperature and
|
||||
set fan speed every X minutes
|
||||
*/
|
||||
delay(EPYSLEEPY);
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Error handler
|
||||
// -----------------------------------------------------------------------------
|
||||
void Error_Handler(void)
|
||||
{
|
||||
while (1) { }
|
||||
}
|
||||
|
||||
// Get current temperature
|
||||
int getTemp() {
|
||||
|
||||
int bp1 = 0;
|
||||
int bp2 = 0;
|
||||
int exp0 = 0;
|
||||
int exp1 = 0;
|
||||
int simm0 = 0;
|
||||
int simm1 = 0;
|
||||
String MD1200output;
|
||||
// -----------------------------------------------------------------------------
|
||||
// UART1 initialization (38400 baud)
|
||||
// -----------------------------------------------------------------------------
|
||||
static void MX_USART1_UART_Init(void)
|
||||
{
|
||||
huart1.Instance = USART1;
|
||||
huart1.Init.BaudRate = 38400;
|
||||
huart1.Init.WordLength = UART_WORDLENGTH_8B;
|
||||
huart1.Init.StopBits = UART_STOPBITS_1;
|
||||
huart1.Init.Parity = UART_PARITY_NONE;
|
||||
huart1.Init.Mode = UART_MODE_TX_RX;
|
||||
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
|
||||
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
|
||||
|
||||
Serial1.println("_temp_rd");
|
||||
|
||||
// wait for MD1200 to answer
|
||||
delay(30);
|
||||
|
||||
while (Serial1.available()) {
|
||||
MD1200output = Serial1.readStringUntil('\n');
|
||||
|
||||
// Check backplane 1
|
||||
if (MD1200output.startsWith("BP_1")) {
|
||||
// check index number of =
|
||||
int eq = MD1200output.indexOf('=');
|
||||
// check index number of c
|
||||
int c = MD1200output.indexOf('c');
|
||||
// check if both exists
|
||||
if (eq != -1 && c != -1) {
|
||||
/*
|
||||
take value between "= " and "c".
|
||||
NOTICE that eq + 1 is there because in
|
||||
"BP_1[2] = 25c" there is a space between = and 25.
|
||||
*/
|
||||
bp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
if (HAL_UART_Init(&huart1) != HAL_OK)
|
||||
{
|
||||
Error_Handler();
|
||||
}
|
||||
|
||||
// Check backplane 2
|
||||
if (MD1200output.startsWith("BP_2")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
bp2 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment if you want to also get temperature for expanders
|
||||
/*
|
||||
|
||||
// Check expander 0
|
||||
if (MD1200output.startsWith("EXP0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check expander 1
|
||||
if (MD1200output.startsWith("EXP1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 0
|
||||
if (MD1200output.startsWith("SIM0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 1
|
||||
if (MD1200output.startsWith("SIM1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Stop when prompt returns
|
||||
if (MD1200output.endsWith(">")) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do (BP_1 + BP_2) / 2 to get the average of backplane
|
||||
if (bp1 != -1 && bp2 != -1) {
|
||||
int bpAvg = (bp1 + bp2) / 2;
|
||||
|
||||
// define default
|
||||
int outPrcntg = 21;
|
||||
|
||||
// a
|
||||
switch (bpAvg) {
|
||||
case 23:
|
||||
outPrcntg = 21;
|
||||
break;
|
||||
// Minimum is 21 (akhsually 20)
|
||||
case 25:
|
||||
outPrcntg = 23;
|
||||
break;
|
||||
case 27:
|
||||
outPrcntg = 24;
|
||||
break;
|
||||
case 29:
|
||||
outPrcntg = 26;
|
||||
break;
|
||||
case 31:
|
||||
outPrcntg = 27;
|
||||
break;
|
||||
case 33:
|
||||
outPrcntg = 30;
|
||||
break;
|
||||
case 35:
|
||||
outPrcntg = 34;
|
||||
break;
|
||||
case 37:
|
||||
outPrcntg = 38;
|
||||
break;
|
||||
/*
|
||||
I don't wan't to become deaf so max is 40.
|
||||
*/
|
||||
|
||||
default:
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return outPrcntg;
|
||||
|
||||
} else {
|
||||
return -1; // failed to read temp
|
||||
}
|
||||
|
||||
/*
|
||||
BP_1[2] - Back plane, maybe left
|
||||
BP_2[3] - Back plane, maybe right
|
||||
SIM0[0] - Controller A
|
||||
SIM1[1] - Controller B
|
||||
EXP0[4] - Expander 0
|
||||
EXP1[5] - Expander 1
|
||||
|
||||
AVG - average of all sensors
|
||||
*/
|
||||
}
|
||||
|
||||
// take percentage as int and set it.
|
||||
int setFanTrsh(int fanTrshInp) {
|
||||
String outputStatement = "set_speed " + String(fanTrshInp);
|
||||
// -----------------------------------------------------------------------------
|
||||
// GPIO for UART1 pins (PA9 TX, PA10 RX)
|
||||
// -----------------------------------------------------------------------------
|
||||
static void MX_GPIO_Init(void)
|
||||
{
|
||||
__HAL_RCC_GPIOA_CLK_ENABLE();
|
||||
|
||||
Serial.println("Sending " + outputStatement + " to MD1200");
|
||||
GPIO_InitTypeDef GPIO_InitStruct = {0};
|
||||
|
||||
if (Serial1.println(outputStatement)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
// PA9 -> USART1_TX (Alternate Function Push-Pull)
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_9;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
|
||||
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
|
||||
// PA10 -> USART1_RX (Input)
|
||||
GPIO_InitStruct.Pin = GPIO_PIN_10;
|
||||
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
|
||||
GPIO_InitStruct.Pull = GPIO_NOPULL;
|
||||
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Interrupt callback for UART receive
|
||||
// -----------------------------------------------------------------------------
|
||||
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
if (huart->Instance == USART1) {
|
||||
|
||||
// Echo received byte back
|
||||
HAL_UART_Transmit(&huart1, &rx_byte, 1, HAL_MAX_DELAY);
|
||||
|
||||
// Re-enable reception of next byte
|
||||
HAL_UART_Receive_IT(&huart1, &rx_byte, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Basic system clock (HSE not required for 38400 UART)
|
||||
// -----------------------------------------------------------------------------
|
||||
void SystemClock_Config(void)
|
||||
{
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||||
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
|
||||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
|
||||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK |
|
||||
RCC_CLOCKTYPE_SYSCLK |
|
||||
RCC_CLOCKTYPE_PCLK1 |
|
||||
RCC_CLOCKTYPE_PCLK2;
|
||||
|
||||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
|
||||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
|
||||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
|
||||
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0);
|
||||
}
|
||||
|
||||
|
||||
24
STM32_CONTROL/tmp/test.cpp
Normal file
24
STM32_CONTROL/tmp/test.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
// #include <Arduino.h>
|
||||
#include <stm32f1xx_hal.h>
|
||||
#define PIN_SERIAL3_RX PB11
|
||||
#define PIN_SERIAL3_TX PB10
|
||||
|
||||
// UART2 (PA3 = RX, PA2 = TX)
|
||||
HardwareSerial Serial1(PA10, PA9);
|
||||
// HardwareSerial sigma(PA9, )
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
|
||||
Serial1.begin(38400);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial1.write("skibidi");
|
||||
|
||||
delay(5000); // wait before next loop
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
219
STM32_CONTROL/versions/main.cpp
Normal file
219
STM32_CONTROL/versions/main.cpp
Normal file
@@ -0,0 +1,219 @@
|
||||
#include <Arduino.h>
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
// VARS
|
||||
const int MD1200BAUDS = 38400; // From what I've read it is always 38400
|
||||
//const int EPYSLEEPY = 600000; / 10 minutes
|
||||
const int EPYSLEEPY = 300000; // 5 minutes
|
||||
//const int EPYSLEEPY = 150000; // 2,5 minutes
|
||||
HardwareSerial MDSerial(PA3, PA2); // Rx Tx
|
||||
HardwareSerial DeBug(PA10, PA9); // Rx Tx
|
||||
// HardwareSerial DeBug(USART1); // use USART1
|
||||
|
||||
// declarations
|
||||
int getTemp();
|
||||
int setFanTrsh(int);
|
||||
|
||||
void setup() {
|
||||
// Setup connection to MD1200
|
||||
// MDSerial because we're using RX/TX pins
|
||||
MDSerial.begin(MD1200BAUDS);
|
||||
|
||||
// Just debug
|
||||
DeBug.begin(9600);
|
||||
DeBug.println("skibidi");
|
||||
delay(15000);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
DeBug.println("Starting loop");
|
||||
|
||||
int fanPercnt = getTemp();
|
||||
|
||||
if (fanPercnt < 10) {
|
||||
DeBug.println("Executing setFanTrsh");
|
||||
setFanTrsh(fanPercnt);
|
||||
}
|
||||
|
||||
/*
|
||||
check temperature and
|
||||
set fan speed every X minutes
|
||||
*/
|
||||
delay(EPYSLEEPY);
|
||||
DeBug.println("Ending loop");
|
||||
}
|
||||
|
||||
// Get current temperature
|
||||
int getTemp() {
|
||||
DeBug.println("Getting Temperature");
|
||||
|
||||
int bp1 = 0;
|
||||
int bp2 = 0;
|
||||
int exp0 = 0;
|
||||
int exp1 = 0;
|
||||
int simm0 = 0;
|
||||
int simm1 = 0;
|
||||
String MD1200output;
|
||||
|
||||
MDSerial.println("_temp_rd");
|
||||
|
||||
// wait for MD1200 to answer
|
||||
delay(30);
|
||||
DeBug.println("getTemp logic start");
|
||||
while (MDSerial.available()) {
|
||||
MD1200output = MDSerial.readStringUntil('\n');
|
||||
|
||||
// Check backplane 1
|
||||
if (MD1200output.startsWith("BP_1")) {
|
||||
// check index number of =
|
||||
int eq = MD1200output.indexOf('=');
|
||||
// check index number of c
|
||||
int c = MD1200output.indexOf('c');
|
||||
// check if both exists
|
||||
if (eq != -1 && c != -1) {
|
||||
/*
|
||||
take value between "= " and "c".
|
||||
NOTICE that eq + 1 is there because in
|
||||
"BP_1[2] = 25c" there is a space between = and 25.
|
||||
*/
|
||||
bp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check backplane 2
|
||||
if (MD1200output.startsWith("BP_2")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
bp2 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Uncomment if you want to also get temperature for expanders
|
||||
/*
|
||||
|
||||
// Check expander 0
|
||||
if (MD1200output.startsWith("EXP0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check expander 1
|
||||
if (MD1200output.startsWith("EXP1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
exp1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 0
|
||||
if (MD1200output.startsWith("SIM0")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm0 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
// Check controller 1
|
||||
if (MD1200output.startsWith("SIM1")) {
|
||||
int eq = MD1200output.indexOf('=');
|
||||
int c = MD1200output.indexOf('c');
|
||||
if (eq != -1 && c != -1) {
|
||||
simm1 = MD1200output.substring(eq + 1, c).toInt();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// Stop when prompt returns
|
||||
if (MD1200output.endsWith(">")) {
|
||||
DeBug.println("getTemp got all temp info");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Do (BP_1 + BP_2) / 2 to get the average of backplane
|
||||
if (bp1 != -1 && bp2 != -1) {
|
||||
int bpAvg = (bp1 + bp2) / 2;
|
||||
|
||||
// define default
|
||||
int outPrcntg = 21;
|
||||
|
||||
// a
|
||||
DeBug.println("getTemp choosing fan speed");
|
||||
switch (bpAvg) {
|
||||
case 23:
|
||||
outPrcntg = 21;
|
||||
break;
|
||||
// Minimum is 21 (akhsually 20)
|
||||
case 25:
|
||||
outPrcntg = 23;
|
||||
break;
|
||||
case 27:
|
||||
outPrcntg = 24;
|
||||
break;
|
||||
case 29:
|
||||
outPrcntg = 26;
|
||||
break;
|
||||
case 31:
|
||||
outPrcntg = 27;
|
||||
break;
|
||||
case 33:
|
||||
outPrcntg = 30;
|
||||
break;
|
||||
case 35:
|
||||
outPrcntg = 34;
|
||||
break;
|
||||
case 37:
|
||||
outPrcntg = 38;
|
||||
break;
|
||||
/*
|
||||
I don't wan't to become deaf so max is 40.
|
||||
*/
|
||||
|
||||
default:
|
||||
return -1;
|
||||
DeBug.println("getTemp error returning -1");
|
||||
|
||||
|
||||
}
|
||||
DeBug.println("getTemp return " + String(outPrcntg));
|
||||
|
||||
return outPrcntg;
|
||||
|
||||
} else {
|
||||
return -1; // failed to read temp
|
||||
}
|
||||
|
||||
/*
|
||||
BP_1[2] - Back plane, maybe left
|
||||
BP_2[3] - Back plane, maybe right
|
||||
SIM0[0] - Controller A
|
||||
SIM1[1] - Controller B
|
||||
EXP0[4] - Expander 0
|
||||
EXP1[5] - Expander 1
|
||||
|
||||
AVG - average of all sensors
|
||||
*/
|
||||
}
|
||||
|
||||
// take percentage as int and set it.
|
||||
int setFanTrsh(int fanTrshInp) {
|
||||
String outputStatement = "set_speed " + String(fanTrshInp);
|
||||
|
||||
DeBug.println("Sending " + outputStatement + " to MD1200");
|
||||
|
||||
if (MDSerial.println(outputStatement)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <DHT.h>
|
||||
#include <DHT_U.h>
|
||||
#include <HardwareSerial.h>
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// DHT PreConfiguration
|
||||
@@ -22,6 +23,7 @@ const int MD1200BAUDS = 38400; // From what I've read it is always 38400
|
||||
//const int EPYSLEEPY = 600000; / 10 minutes
|
||||
const int EPYSLEEPY = 300000; // 5 minutes
|
||||
//const int EPYSLEEPY = 150000; // 2,5 minutes
|
||||
HardwareSerial MDSerial(PA3, PA2); // Rx Tx
|
||||
|
||||
// declarations
|
||||
int getTemp();
|
||||
@@ -30,8 +32,8 @@ float dhtRead();
|
||||
|
||||
void setup() {
|
||||
// Setup connection to MD1200
|
||||
// Serial1 because we're using RX/TX pins
|
||||
Serial1.begin(MD1200BAUDS);
|
||||
// MDSerial because we're using RX/TX pins
|
||||
MDSerial.begin(MD1200BAUDS);
|
||||
|
||||
// Just debug
|
||||
Serial.begin(9600);
|
||||
@@ -66,13 +68,13 @@ int getTemp() {
|
||||
int simm1 = 0;
|
||||
String MD1200output;
|
||||
|
||||
Serial1.println("_temp_rd");
|
||||
MDSerial.println("_temp_rd");
|
||||
|
||||
// wait for MD1200 to answer
|
||||
delay(30);
|
||||
|
||||
while (Serial1.available()) {
|
||||
MD1200output = Serial1.readStringUntil('\n');
|
||||
while (MDSerial.available()) {
|
||||
MD1200output = MDSerial.readStringUntil('\n');
|
||||
|
||||
// Check backplane 1
|
||||
if (MD1200output.startsWith("BP_1")) {
|
||||
@@ -221,7 +223,7 @@ int setFanTrsh(int fanTrshInp) {
|
||||
|
||||
Serial.println("Sending " + outputStatement + " to MD1200");
|
||||
|
||||
if (Serial1.println(outputStatement)) {
|
||||
if (MDSerial.println(outputStatement)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
|
||||
232
dashboard.json
Normal file
232
dashboard.json
Normal file
@@ -0,0 +1,232 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": {
|
||||
"type": "grafana",
|
||||
"uid": "-- Grafana --"
|
||||
},
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"fiscalYearStartMonth": 0,
|
||||
"graphTooltip": 0,
|
||||
"id": 38,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"collapsed": false,
|
||||
"gridPos": {
|
||||
"h": 1,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"id": 2,
|
||||
"panels": [],
|
||||
"title": "MD1200-1",
|
||||
"type": "row"
|
||||
},
|
||||
{
|
||||
"datasource": {
|
||||
"type": "influxdb",
|
||||
"uid": "bdp80jf4cy328f"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"color": {
|
||||
"mode": "palette-classic"
|
||||
},
|
||||
"custom": {
|
||||
"axisBorderShow": false,
|
||||
"axisCenteredZero": false,
|
||||
"axisColorMode": "text",
|
||||
"axisLabel": "",
|
||||
"axisPlacement": "auto",
|
||||
"barAlignment": 0,
|
||||
"barWidthFactor": 0.6,
|
||||
"drawStyle": "line",
|
||||
"fillOpacity": 0,
|
||||
"gradientMode": "none",
|
||||
"hideFrom": {
|
||||
"legend": false,
|
||||
"tooltip": false,
|
||||
"viz": false
|
||||
},
|
||||
"insertNulls": false,
|
||||
"lineInterpolation": "linear",
|
||||
"lineWidth": 1,
|
||||
"pointSize": 5,
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
},
|
||||
"showPoints": "auto",
|
||||
"spanNulls": false,
|
||||
"stacking": {
|
||||
"group": "A",
|
||||
"mode": "none"
|
||||
},
|
||||
"thresholdsStyle": {
|
||||
"mode": "off"
|
||||
}
|
||||
},
|
||||
"mappings": [],
|
||||
"thresholds": {
|
||||
"mode": "absolute",
|
||||
"steps": [
|
||||
{
|
||||
"color": "green"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
},
|
||||
"unit": "celsius"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Average {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Average"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Backplane1 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Backplane 1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Backplane2 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Backplane 2"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Expander0 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Expander 0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "Expander1 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "Expander 1"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "SASIntModule0 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "SAS interface module 0"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"matcher": {
|
||||
"id": "byName",
|
||||
"options": "SASIntModule1 {LOCATION=\"HQ\", MACHINE=\"CHONGUS1200\"}"
|
||||
},
|
||||
"properties": [
|
||||
{
|
||||
"id": "displayName",
|
||||
"value": "SAS interface module 1"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"gridPos": {
|
||||
"h": 10,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"id": 1,
|
||||
"options": {
|
||||
"legend": {
|
||||
"calcs": [],
|
||||
"displayMode": "list",
|
||||
"placement": "bottom",
|
||||
"showLegend": true
|
||||
},
|
||||
"tooltip": {
|
||||
"hideZeros": false,
|
||||
"mode": "single",
|
||||
"sort": "none"
|
||||
}
|
||||
},
|
||||
"pluginVersion": "12.0.2",
|
||||
"targets": [
|
||||
{
|
||||
"datasource": {
|
||||
"type": "influxdb",
|
||||
"uid": "bdp80jf4cy328f"
|
||||
},
|
||||
"query": "from(bucket: \"JBOD\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"MD1200-script\")\n |> filter(fn: (r) => r[\"LOCATION\"] == \"HQ\")\n |> filter(fn: (r) => r[\"MACHINE\"] == \"CHONGUS1200\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")",
|
||||
"refId": "A"
|
||||
}
|
||||
],
|
||||
"title": "Temperatures",
|
||||
"type": "timeseries"
|
||||
}
|
||||
],
|
||||
"preload": false,
|
||||
"schemaVersion": 41,
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-3h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {},
|
||||
"timezone": "browser",
|
||||
"title": "JBODs",
|
||||
"uid": "1ee6cf76-943c-45e0-8d6f-c92db9691459",
|
||||
"version": 3
|
||||
}
|
||||
18
docker-compose.yml
Normal file
18
docker-compose.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
|
||||
services:
|
||||
mdfanchanger:
|
||||
container_name: MD_Fan_Changer
|
||||
image: yuruc3/md1200_fan_controll:v1.2.1
|
||||
environment:
|
||||
# - MD1200BAUD=
|
||||
- SERIALADAPTER=/dev/ttyUSB0
|
||||
- TEMP_FACTOR=17
|
||||
- EPPYSLEEPY=0.25
|
||||
- MDSERIALTIMEOUT=0.75
|
||||
# - LOW_FAN_TRSHD=
|
||||
# - HIGH_FAN_TRSHD=
|
||||
devices:
|
||||
- /dev/ttyUSB0:/dev/ttyUSB0
|
||||
restart: unless-stopped
|
||||
privileged: false
|
||||
Reference in New Issue
Block a user