Home Unraid硬盘散热控制
Post
Cancel

Unraid硬盘散热控制

前言

我有一台nas,不过nas的硬盘风扇电源不知道接哪里最合适,因为接主板上,需要手动去控制转速。而接硬盘背板时,这样会一直满负荷运行,导致太吵了。

所以这里产生了一个想法,用arduino去控制风扇,再在nas里面去添加一个脚本,实时根据温度去发送应该的转速,然后使用pwm去控制风扇转速。

nas python脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# coding=utf-8
import os
import socket

from time import sleep


def get_temp():
    temp = os.popen("ls -1 /dev/sd? | xargs -n1 smartctl -A | grep Celsius").read()
    item_temp = temp.split('\n')
    max_temp = 0
    for item in item_temp:
        if not item:
            continue
        split = item.split(' ')
        index = split.index("(Min/Max")
        item_temp = split[index - 1]
        max_temp = max(int(item_temp), max_temp)
    return max_temp

def convert(temp):
    if temp > 44:
        return 1000
    elif temp < 35:
        return 0
    else:
        return (temp - 35) * 100

sk = socket.socket()  # 创建socket对象
sk.bind(("0.0.0.0", 9001))  # 绑定IP和端口
sk.listen()  # 开启监听

print("start listen")

while 1:  # 让服务端和客户端循环通信
    conn, address = sk.accept()  # 等待客户端连接 阻塞
    print("accept client")
    try:
        while 1:
            temp = get_temp()
            send_msg = str(convert(temp))+'\n'  # 要发送的消息
            conn.send(send_msg.encode("utf-8"))  # 发送消息给客户端
            print("send temp success, current temp: " + str(temp) + "fan speed: " + send_msg)
            sleep(1)
    except OSError:
        print("send to client error")
        conn.close()

首先使用ls -1 /dev/sd? | xargs -n1 smartctl -A | grep Celsius去获取当前所有硬盘的状态。根据获取到的值去进行拆分,获取到温度最大值。这里原计划是发送到公共的广播,但是esp8266的udp代码部分出现问题,所以改成还是用tcp实现了。这个可以添加为unraid的脚本,然后在array建立时直接运行。

arduino

这里使用的是esp8266,价格便宜,用在这里也算是大材小用了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <ESP8266WiFi.h>                        // 本程序使用ESP8266WiFi库

const char* ssid     = "xxxx-xxxx";                // 需要连接到的WiFi名
const char* password = "xxxxxxxx";             // 连接的WiFi密码
int gpio = 16; // D0

void setup() {
  Serial.begin(115200);                         // 初始化串口通讯波特率为115200

  analogWriteFreq(25000);            // 频率设置为25kHz
  analogWriteRange(1000);           // 范围设置为1000
  analogWrite(gpio, 1000);

  WiFi.mode(WIFI_STA);                          // 设置Wifi工作模式为STA,默认为AP+STA模式
  WiFi.begin(ssid, password);                   // 通过wifi名和密码连接到Wifi
  Serial.print("\r\nConnecting to ");           // 串口监视器输出网络连接信息
  Serial.print(ssid); Serial.println(" ...");   // 显示NodeMCU正在尝试WiFi连接

  int i = 0;                                    // 检查WiFi是否连接成功
  while (WiFi.status() != WL_CONNECTED)         // WiFi.status()函数的返回值是由NodeMCU的WiFi连接状态所决定的。
  {                                             // 如果WiFi连接成功则返回值为WL_CONNECTED
    delay(1000);                                // 此处通过While循环让NodeMCU每隔一秒钟检查一次WiFi.status()函数返回值
    Serial.print("waiting for ");
    Serial.print(i++); Serial.println("s...");
  }

  Serial.println("");                           // WiFi连接成功后
  Serial.println("WiFi connected!");            // NodeMCU将通过串口监视器输出"连接成功"信息。
  Serial.print("IP address: ");                 // 同时还将输出NodeMCU的IP地址。这一功能是通过调用
  Serial.println(WiFi.localIP());               // WiFi.localIP()函数来实现的。该函数的返回值即NodeMCU的IP地址。
}

const char* host = "192.168.10.235";
const uint16_t port = 9001;

void loop() {
  /* 新建一个WiFiClient类对象,作为TCP客户端对象 */
  WiFiClient tcpclient;

  /* 建立TCP连接 */
  Serial.print("connecting to "); Serial.print(host); Serial.print(':'); Serial.println(port);
  if (!tcpclient.connect(host, port)) {
    Serial.println("connection failed");        // 如果连接失败,则打印连接失败信息,并返回
    delay(3000);
    return;
  }

  while (true)
  {
    String str = tcpclient.readStringUntil('\n');
    if (str.length()==0)
    {
      // 读取失败时风扇满载运行
      analogWrite(gpio, 1000);
      break;
    }
    int value = str.toInt();
    analogWrite(gpio, value);
    Serial.println(str);
  }

}

这里实现很简单,主要参考实例程序改写,首先是链接WiFi,然后接收服务端发送来的消息,然后根据传递过来的数字设置转速。

代码地址

https://github.com/jiangkerLove/temp_ctrl

This post is licensed under CC BY 4.0 by the author.