9/25/2025

Proxmox : upgrade PVE version from 8 to 9

 1.ตรวจสอบว่ามีปัญหาในการ upgrade หรือไม่ แล้วแก้ไขรายการที่ fail ให้ผ่านก่อน
มีสีเหลืองได้ แต่ถ้าสีแดงต้องแก้ก่อน

  1. pve8to9

2.Shutdown VM และ CT ทั้งหมด
3.ตรวจสอบสถานะปัจจุบัน
  1. apt update
  2. apt dist-upgrade
  3. pveversion


4.แก้ไข Repositories ให้เป็นตัวใหม่ ต้องแก้ตัวนี้ให้เป็นตัวใหม่ก่อน เพราะตอน update ยังใช้ sources นี้อยู่
  1. sed -i 's/bookworm/trixie/g' /etc/apt/sources.list


5. สร้างไฟล์ Repositories ที่ต้องใช้สำหรับ Version ใหม่
  1. cat > /etc/apt/sources.list.d/pve-enterprise.sources << EOF
  2. Types: deb deb-src
  3. URIs: http://mirror.kku.ac.th/debian/
  4. Suites: trixie
  5. Components: main non-free-firmware
  6. Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
  7.  
  8. Types: deb deb-src
  9. URIs: http://security.debian.org/debian-security/
  10. Suites: trixie-security
  11. Components: main non-free-firmware
  12. Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
  13.  
  14. Types: deb deb-src
  15. URIs: http://mirror.kku.ac.th/debian/
  16. Suites: trixie-updates
  17. Components: main non-free-firmware
  18. Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg
  19. EOF

6.update+upgrade
apt update
apt dist-upgrade
จะมีข้อความให้ตอบ
ตอบ q enter
ตอบ Yes เฉพาะ /etc/lvm/lvm.conf
นอกนั้น No ทั้งหมด

7. ปิด sources.list เดิมไม่ได้ใช้ ใส่ # ไว้
  1. nano /etc/apt/sources.list


หรือปิดผ่านหน้า GUI ใน Nodes --> pve --> Repositories

ที่มา : https://pve.proxmox.com/wiki/Upgrade_from_8_to_9

 

หากมีปัญหาหรือ Error ให้กลับไปใช้ Kernel เดิม แล้วทำการ แก้ไขเริ่มต้น upgrade ใหม่
1. ดูว่าใช้ kernel ไหนอยู่

  1. uname -a

Linux pve44 6.8.12-15-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-15 (2025-09-12T11:02Z) x86_64 GNU/Linux

2. list ดู kernel
  1. proxmox-boot-tool kernel list

แล้วย้อนกลับไปที่ kernel เก่า
  1. proxmox-boot-tool kernel pin 6.8.12-15-pve --next-boot

3. reboot
แล้วแก้ไขทำการเริ่ม upgrade ใหม่

เมื่อ upgrade ได้แล้ว ต้อง unpin kernel เพื่อให้ใช้ kernel ล่าสุด
  1. proxmox-boot-tool kernel unpin 
  1. proxmox-boot-tool kernel list
  1. uname -a

 

9/23/2025

Ubuntu 18.04 Samba share เข้า terminal ภาษาไทยไม่แสดง

 Ubuntu 18.04 Samba share เข้า terminal ภาษาไทยไม่แสดง

ตั้งตั้งค่า locales
1. คำสั่ง

  1. dpkg-reconfigure locales

2. เลือก
th_TH.UTF-8 UTF-8

 


 

Home Assistant with Docker กล้อง ONVIF แจ้งเตือนเข้า Rocketchat

 *** หาต้องการให้แสดงรูป ต้องใช้ url
https://rocket.scivalve.com
- หากใช้ IP จะเห็น รูปได้เครื่องอยู่ในวง network เดียวกัน
- ใช้ chat.scivalve.com ใน app จะไม่เห็น เพราะ app ชี้ url ไปที่ rocket.scivalve.com
ให้ใช้ rocket.scivalve.com จะเห็นทั้งในหมด
ขึ้นตอน
1. Add integration ONVIF ถ้ากล้องอยู่วงเดียวกันกับ HA จะเจอเลย ถ้าไม่เจอ Add Manual Port 10080
2. Add กล้องสำหรับ view เข้า Dashboard ไว้ดู By entity แล้วเลือก Profile กล้องที่ต้องการ
*** หาวิธีส่งรูปตรง ๆ จาก HA แล้วไม่ได้ ติดปัญหา กล้องไม่มี function ที่ snap เป็น jpg จึงทำไม่ได้ ****
แก้ปัญหาโดย เขียน code python save ลง docker แล้วให้ HA เรียกใช้ python ส่งแจ้งเตือนเข้า Rocketchat
3. สร้างไฟล์ python ที่ Home Assistant
ไว้ที่ /HA/snapshot.py
Code

  1. #!/usr/bin/env python3
  2. import requests
  3.  
  4. url = "http://xxx.xx.xx.xx:8080/snapshot.cgi?user=xxx&pwd=xxx"
  5. res = requests.get(url, stream=True)
  6.  
  7. if res.status_code == 200:
  8.     #with open("/HA/www/snapshot.jpg", "wb") as f:
  9.     with open("/config/www/snapshot.jpg", "wb") as f:
  10.        for chunk in res.iter_content(1024):
  11.             f.write(chunk)
  12.  
  13.     url = "http://xxx.xx.xx.xx:3000/api/v1/rooms.upload/RoomId"
  14.     #url = "https://chat.scivalve.com/api/v1/rooms.upload/RoomId"
  15.     headers = {
  16.         "X-Auth-Token": "xxx",
  17.         "X-User-Id": "xxx"
  18.     }
  19.    
  20.     files = {
  21.         #"file": ("snapshot.jpg", open("/HA/www/snapshot.jpg", "rb"), "image/jpeg")
  22.         "file": ("snapshot.jpg", open("/config/www/snapshot.jpg", "rb"), "image/jpeg")
  23.     }
  24.  
  25.     data = {
  26.         "msg": "พบการเคลื่อนไหวจากกล้อง SERVER A"
  27.     }
  28.  
  29.     response = requests.post(url, headers=headers, files=files, data=data)
  30.     #print(response.text)
  31.     #print("Snapshot saved")
  32. else:
  33.     print("Error:", res.status_code)


***สำคัญไฟล์ ที่ save และส่ง ต้องใช้ใน /config/ เพื่อให้รูปได้จริง หากไว้ใน /HA/ จะ run คำสั่ง python ตรง ๆ ได้ แต่เมื่อ Home Assistant เรียกใช้จะส่งรูปไม่ได้ ***
RoomId หาได้จาก คำสั่ง
  1. curl -H "X-Auth-Token: xxx" \
  2.      -H "X-User-Id: xxx" \
  3.      http://xxx.xxx.xx.xx:3000/api/v1/rooms.info?roomName=ชื่อห้อง

เช่น
  1. curl -H "X-Auth-Token: xxx" \
  2.      -H "X-User-Id: xxx" \
  3.      http://xxx.xxx.xx.xx:3000/api/v1/rooms.info?roomName=Test

จะได้ _id คือ room id
{"room":{"_id":"xxx","fname":"Test"
{"room":{"_id":"xxx","fname":"IT_Notification",

4. configuration.yaml สำหรับเรียกใช้ python เพิ่ม
  1. shell_command:
  2.    send_snapshot: "python3 /config/snapshot.py"
  3.  


5. automation.yaml เพิ่ม
  1. - id: motion_alert_server_a
  2.   alias: "แจ้งเตือน SERVER A พร้อมส่งรูป"
  3.   trigger:
  4.     - platform: state
  5.       entity_id: binary_sensor.ip_camera_cell_motion_detection
  6.       to: "on"
  7.   action:
  8.     - service: shell_command.send_snapshot

9/18/2025

ส่งค่าอุณหภูมิจาก Pi ไป Home Assistant แบบ Docker

 ส่งค่าอุณหภูมิจาก Pi ไป Home Assistant แบบ Docker

ต่อจาก
https://intranet.scivalve.com/blog.php?u=281&b=2051

1. ตัว HA ลงแบบ Docker ก็ต้อง Mosquitto ด้วย Docker container
1.1. สร้างโฟลเดอร์เก็บ config/data/log ของ Mosquitto:

  1. mkdir -p /HA/mosquitto/config /HA/mosquitto/data /HA/mosquitto/log

1.2. สร้างไฟล์ config
  1. nano /HA/mosquitto/config/mosquitto.conf

1.3. ใส่ค่า
แบบใช้ได้หมด ไม่ต้องใส่ use password ไม่ปลอดภัย
  1. persistence true
  2. persistence_location /mosquitto/data/
  3. log_dest file /mosquitto/log/mosquitto.log
  4.  
  5. allow_anonymous true
  6. listener 1883

แบบตั้ง user password
  1. persistence true
  2. persistence_location /mosquitto/data/
  3. log_dest file /mosquitto/log/mosquitto.log
  4.  
  5. allow_anonymous false
  6. password_file /mosquitto/config/password.txt
  7. listener 1883


1.4. สร้าง user ด้วยคำสั่ง
docker run --rm -it \
  1.  -v /HA/mosquitto/config:/mosquitto/config \
  2.   eclipse-mosquitto mosquitto_passwd -c /mosquitto/config/password.txt hauserXXXXX

มันจะถาม password ให้คุณใส่ → เก็บไว้ใน /HA/mosquitto/config/password.txt

1.5. รัน container Mosquitto:
  1. docker run -d \
  2.   --name mosquitto \
  3.   -p 1883:1883 \
  4.   -p 9001:9001 \
  5.   -v /HA/mosquitto/config:/mosquitto/config \
  6.   -v /HA/mosquitto/data:/mosquitto/data \
  7.   -v /HA/mosquitto/log:/mosquitto/log \
  8.   eclipse-mosquitto


1.6. Restart Mosquitto
  1. docker restart mosquitto


1.7. ทดสอบ ที่เครื่อง HA Run
  1. mosquitto_sub -h localhost -p 1883 -u "hauser" -P "รหัสผ่าน" -t "#"


1.8. ที่เครื่องเรา ติดตั้ง
  1. apt install mosquitto-clients -y

แล้วลองส่งค่าไป
  1. mosquitto_pub -h 192.168.2.5 -p 1883 -u "xxx" -P "xxxx" -t "test/topic" -m "Hello MQTT"
  1. mosquitto_pub -h 192.168.2.5 -p 1883 -u "xxx" -P "xxxx" -t "hass/sensor/temperature" -m "27"

ที่ Terminal ของ HA จะต้องเห็นข้อความ Hello MQTT

1.9. ที่ เครื่อง HA เพิ่ม ที่ไฟล์ configuration.yaml เป็น Sensor และรอรับค่า MQTT
  1. mqtt:
  2.   sensor:
  3.     - name: "Server Temp."
  4.       state_topic: "hass/sensor/temperature"
  5.       value_template: "{{ value_json.temperature }}"
  6.       unit_of_measurement: "°C"
  7.  
  8.     - name: "Server Hum."
  9.       state_topic: "hass/sensor/temperature"
  10.       value_template: "{{ value_json.humidity }}"
  11.       unit_of_measurement: "%"


1.10. เข้า Setting --> Devices & Services Add integration MQTT เข้าไปด้วย
ใส่ IP User Password

1.11. ที่เครื่อง pi ทดลอง run python Code temp2mqtt.2.5.py
  1. #!/usr/bin/python3
  2. import sys
  3. import Adafruit_DHT
  4.  
  5. import time, json
  6. import RPi.GPIO as GPIO
  7. import paho.mqtt.client as mqtt
  8.  
  9. import requests
  10.  
  11. # Config
  12. MQTT_BROKER = "192.168.2.5"   # IP ของ Home Assistant
  13. MQTT_PORT = 1883
  14. MQTT_USER = "xx"
  15. MQTT_PASSWORD = "xx"
  16. MQTT_TOPIC = "hass/sensor/temperature"
  17.  
  18. SENSOR = Adafruit_DHT.AM2302  # หรือ DHT11 แล้วแต่ที่ใช้
  19. PIN = 4  # GPIO ที่ต่อ sensor
  20.  
  21. # Connect MQTT
  22. client = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
  23. client.username_pw_set(MQTT_USER, MQTT_PASSWORD)
  24. client.connect(MQTT_BROKER, MQTT_PORT, 60)
  25.  
  26. # Try to grab a sensor reading.  Use the read_retry method which will retry up
  27. # to 15 times to get a sensor reading (waiting 2 seconds between each retry).
  28. humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN)
  29.  
  30. # Un-comment the line below to convert the temperature to Fahrenheit.
  31. # temperature = temperature * 9/5.0 + 32
  32.  
  33. from datetime import datetime
  34. if humidity is not None and temperature is not None:
  35.    print('Temp={0:0.1f}*  Humidity={1:0.1f}%  Date={2}'.format(temperature, humidity, datetime.today().strftime('%Y-%m-%d %H:%M:%S')))
  36.    payload = {
  37.         "temperature": round(temperature, 2),
  38.         "humidity": round(humidity, 2)
  39.    }
  40.    #print('{0}'.format(json.dumps(payload)))
  41.    client.publish(MQTT_TOPIC, json.dumps(payload))
  42.  


แก้ Code ให้ส่ง MQTT ไป 2 เครื่อง
  1. #!/usr/bin/python3
  2. import Adafruit_DHT
  3. import time, json
  4. from datetime import datetime
  5. import paho.mqtt.client as mqtt
  6.  
  7. # Config broker 1
  8. MQTT_BROKER1   = "192.168.0.187"
  9. MQTT_PORT1     = 1883
  10. MQTT_USER1     = "xxx"
  11. MQTT_PASSWORD1 = "xxx"
  12. BROKER1_TOPIC  = "hass/sensor/temperature"
  13.  
  14. # Config broker 2
  15. MQTT_BROKER2   = "192.168.2.5"
  16. MQTT_PORT2     = 1883
  17. MQTT_USER2     = "xxx"
  18. MQTT_PASSWORD2 = "xxx"
  19. BROKER2_TOPIC  = "hass/sensor/temperature"
  20.  
  21. SENSOR = Adafruit_DHT.AM2302
  22. PIN = 4
  23.  
  24. # อ่านค่าจาก DHT
  25. humidity, temperature = Adafruit_DHT.read_retry(SENSOR, PIN)
  26.  
  27. if humidity is not None and temperature is not None:
  28.     payload = {
  29.         "temperature": round(temperature, 2),
  30.         "humidity": round(humidity, 2)
  31.     }
  32.  
  33.     print(f"Publish: {payload} at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
  34.  
  35.     # ส่งไป broker 1
  36.     client1 = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
  37.     client1.username_pw_set(MQTT_USER1, MQTT_PASSWORD1)
  38.     client1.connect(MQTT_BROKER1, MQTT_PORT1, 60)
  39.     client1.publish(BROKER1_TOPIC, json.dumps(payload))
  40.     client1.disconnect()
  41.  
  42.     # ส่งไป broker 2
  43.     client2 = mqtt.Client(callback_api_version=mqtt.CallbackAPIVersion.VERSION2)
  44.     client2.username_pw_set(MQTT_USER2, MQTT_PASSWORD2)
  45.     client2.connect(MQTT_BROKER2, MQTT_PORT2, 60)
  46.     client2.publish(BROKER2_TOPIC, json.dumps(payload))
  47.     client2.disconnect()

 

HA + Pi สั่งปิดเปิด Air Auto แทนเครื่อง MN-SERVER

 HA + Pi สั่งปิดเปิด Air Auto แทนเครื่อง MN-SERVER

คำสั่ง Restart service HA docker

  1. docker restart Docker-ID

ตั้งค่า Timezone ให้ Debian เพื่อให้เวลาตรง
  1. timedatectl set-timezone Asia/Bangkok
  2. timedatectl
  3. date


1. ติดตั้ง Home Assistant with Docker
https://intranet.scivalve.com/blog.php?u=281

2. HA และ PI สร้าง Private Key เพื่อให้ HA สามารถ SSH เข้าเครื่อง PI โดยไม่ต้องใช้รหัส
จะทำให้ HA สามารถเรียกคำสั่งโปรแกรมที่เครื่อง PI ได้
2.1. ใช้ Terminal ล็อคอินเข้าไปที่ เครื่อง Server ที่รัน Docker และ Home Assistant ของคุณ
2.2. รันคำสั่งนี้เพื่อสร้าง Key คู่ใหม่:
  1. ssh-keygen -t rsa -b 4096

2.3. ระบบจะถามคำถาม 2-3 ข้อ ให้ กด Enter ผ่านไปทั้งหมด เพื่อยอมรับค่าเริ่มต้น และ ไม่ต้องใส่รหัสผ่าน (passphrase) นะครับ
2.4. คำสั่งนี้จะสร้างไฟล์ id_rsa (กุญแจลับ) และ id_rsa.pub (กุญแจสาธารณะ) ขึ้นมาในโฟลเดอร์ .ssh ของ user ที่คุณกำลังล็อคอินอยู่บน Server (เช่น /root/.ssh/ หากคุณล็อคอินเป็น root)

[บนเครื่อง HA Server] ขั้นตอนที่ 2: คัดลอกเนื้อหา Public Key

2.5. รันคำสั่งนี้เพื่อแสดงเนื้อหาของ Public Key:
  1. cat ~/.ssh/id_rsa.pub

2.6. คัดลอก (Copy) ข้อความทั้งหมด ที่แสดงขึ้นมา มันจะขึ้นต้นด้วย ssh-rsa และลงท้ายด้วยชื่อ user@hostname ของคุณ

[บนเครื่อง Raspberry Pi] ขั้นตอนที่ 3: ติดตั้ง Public Key

2.7. ตอนนี้ ให้ใช้ Terminal ล็อคอินเข้าไปที่ เครื่อง Raspberry Pi ของคุณ
2.8. รันคำสั่งนี้เพื่อสร้างโฟลเดอร์และไฟล์ที่จำเป็น (หากยังไม่มี) และตั้งค่า permission ให้ถูกต้อง:
  1. mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys

2.9. เปิดไฟล์ authorized_keys ด้วยโปรแกรม nano:
  1. nano ~/.ssh/authorized_keys

2.10. วาง (Paste) Public Key ที่คุณคัดลอกมาจากขั้นตอนที่ 2 ลงในไฟล์นี้ จากนั้นกด Ctrl+X > กด Y > กด Enter เพื่อบันทึกและออกจากโปรแกรม

[บนเครื่อง HA Server] ขั้นตอนที่ 4: คัดลอก Private Key ให้ Docker
2.11. กลับมาที่ Terminal ของ เครื่อง HA Server
2.12. ตอนนี้ให้ทำขั้นตอนที่เราคุยกันล่าสุด คือคัดลอก Private Key (id_rsa) ที่เพิ่งสร้างในขั้นตอนที่ 1 ไปยังโฟลเดอร์คอนฟิกของ HA ที่แชร์กับ Docker

# แก้ /root/.ssh/id_rsa หาก Key ของคุณอยู่ที่อื่น
# แก้ /path/to/your/ha/config/ ให้เป็น Path จริง
เครื่องจริงอยู่ที่ /config/id_rsa
  1. cp /root/.ssh/id_rsa /path/to/your/ha/config/

2.13. ตั้งค่า permission ให้ไฟล์ที่คัดลอกไป:
  1. chmod 600 /path/to/your/ha/config/id_rsa

2.14. ทดสอบ SSH จากเครื่อง HA ไปเครื่อง PI จะต้องไม่ขึ้นถามรหัส Login

3. แก้ไข ไฟล์ configuration.yaml เพื่อให้มี Switch ปิดเปิด Air manual เพิ่ม
  1. ### Air ####
  2. shell_command:
  3.   # !!! สำคัญ: แก้ไข <IP_ของ_RPi> และ path ไปยังไฟล์ .py ของคุณให้ถูกต้อง !!!
  4.   #### TEST #####
  5.   #air1_on:  "sshpass -p 'XXX' ssh pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  6.   #air1_off: "sshpass -p 'XXX' ssh pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  7.   #air1_on:  "ssh -i /HA/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  8.   #air1_off: "ssh -i /HA/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  9.   #air1_on:  "ssh pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  10.   #air1_off: "ssh pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  11.   ##### Test Rocketchat #######
  12.   #air1_on:  "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  13.   #air1_off: "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Test.py 2302 4'"
  14.  
  15.   air1_on:  "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/On_air1.py'"
  16.   air1_off: "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Off_air1.py'"
  17.  
  18.   air2_on:  "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/On_air2.py'"
  19.   air2_off: "ssh -i /config/id_rsa -o 'StrictHostKeyChecking=no' pi@192.168.0.3 'python3 /home/pi/Off_air2.py'"
  20.  
  21.   # --- DEBUG COMMANDS ---
  22.   #debug_find_path: "pwd > pwd.txt && ls -la >> pwd.txt"
  23.  
  24. # New sensor for human-readable status
  25. sensor:
  26.   - platform: template
  27.     sensors:
  28.       air_status:
  29.         friendly_name: "สถานะแอร์"
  30.         value_template: >-
  31.           {% set state = states('input_select.active_air') %}
  32.           {% if state == 'air1' %}
  33.             Air 1 กำลังทำงาน
  34.           {% elif state == 'air2' %}
  35.             Air 2 กำลังทำงาน
  36.           {% elif state == 'both' %}
  37.             Air 1 และ Air 2 กำลังทำงาน
  38.           {% else %}
  39.             แอร์ทุกเครื่องปิดอยู่
  40.           {% endif %}
  41.  
  42. switch:
  43.   - platform: template
  44.     switches:
  45.       air1_switch:
  46.         friendly_name: "Air 1"
  47.         value_template: "{{ states('input_select.active_air') in ['air1', 'both'] }}"
  48.         turn_on:
  49.           - service: shell_command.air1_on
  50.           - service: input_select.select_option
  51.             target:
  52.               entity_id: input_select.active_air
  53.             data:
  54.               option: >-
  55.                 {% if is_state('input_select.active_air', 'air2') %}
  56.                   both
  57.                 {% else %}
  58.                   air1
  59.                 {% endif %}
  60.         turn_off:
  61.           - service: shell_command.air1_off
  62.           - service: input_select.select_option
  63.             target:
  64.               entity_id: input_select.active_air
  65.             data:
  66.               option: >-
  67.                 {% if is_state('input_select.active_air', 'both') %}
  68.                   air2
  69.                 {% else %}
  70.                   none
  71.                 {% endif %}
  72.  
  73.       air2_switch:
  74.         friendly_name: "Air 2"
  75.         value_template: "{{ states('input_select.active_air') in ['air2', 'both'] }}"
  76.         turn_on:
  77.           - service: shell_command.air2_on
  78.           - service: input_select.select_option
  79.             target:
  80.               entity_id: input_select.active_air
  81.             data:
  82.               option: >-
  83.                 {% if is_state('input_select.active_air', 'air1') %}
  84.                   both
  85.                 {% else %}
  86.                   air2
  87.                 {% endif %}
  88.         turn_off:
  89.           - service: shell_command.air2_off
  90.           - service: input_select.select_option
  91.             target:
  92.               entity_id: input_select.active_air
  93.             data:
  94.               option: >-
  95.                 {% if is_state('input_select.active_air', 'both') %}
  96.                   air1
  97.                 {% else %}
  98.                   none
  99.                 {% endif %}
  100.  
  101.       # New switch for controlling both
  102.       all_air_switch:
  103.         friendly_name: "Air1+Air2"
  104.         value_template: "{{ is_state('input_select.active_air', 'both') }}"
  105.         turn_on:
  106.           - service: shell_command.air1_on
  107.           - service: shell_command.air2_on
  108.           - service: input_select.select_option
  109.             target:
  110.               entity_id: input_select.active_air
  111.             data:
  112.               option: 'both'
  113.         turn_off:
  114.           - service: shell_command.air1_off
  115.           - service: shell_command.air2_off
  116.           - service: input_select.select_option
  117.             target:
  118.               entity_id: input_select.active_air
  119.             data:
  120.               option: 'none'
  121.  
  122. input_select:
  123.   active_air:
  124.     name: Air ที่ทำงานอยู่
  125.     options:
  126.       - none
  127.       - air1
  128.       - air2
  129.       - both # Added 'both' state
  130.     initial: none


4. ไฟล์ automation.yaml เพื่อให้สลับ Air อัตโนมัติ เพิ่ม
  1. #### Off ก่อนแล้วค่อย ON เพื่อไม่ให้ Switch เปิดทั้ง 2
  2. #### delay 15 วิ รอให้ คำสั่งแรกทำงานเสร็จก่อน ถ้าทำต่อเลย คำสั่งแรกยังทำไม่เสร็จ Status จะไม่ถูก
  3. - id: air1_0000
  4.   alias: "Air1 00:00 - 02:59"
  5.   trigger:
  6.     - platform: time
  7.       at: "00:00:00"
  8.   action:
  9.     - service: switch.turn_off
  10.       target:
  11.         entity_id: switch.all_air_switch
  12.     - delay: "00:00:15"   # รอ 15 วินาที      
  13.     - service: switch.turn_on
  14.       target:
  15.         entity_id: switch.air1_switch
  16.  
  17. - id: air2_0300
  18.   alias: "Air2 03:00 - 05:59"
  19.   trigger:
  20.     - platform: time
  21.       at: "03:00:00"
  22.   action:
  23.     - service: switch.turn_off
  24.       target:
  25.         entity_id: switch.all_air_switch
  26.     - delay: "00:00:15"   # รอ 15 วินาที      
  27.     - service: switch.turn_on
  28.       target:
  29.         entity_id: switch.air2_switch
  30.  
  31. - id: air1_0600
  32.   alias: "Air1 06:00 - 08:59"
  33.   trigger:
  34.     - platform: time
  35.       at: "06:00:00"
  36.   action:
  37.     - service: switch.turn_off
  38.       target:
  39.         entity_id: switch.all_air_switch
  40.     - delay: "00:00:15"   # รอ 15 วินาที      
  41.     - service: switch.turn_on
  42.       target:
  43.         entity_id: switch.air1_switch
  44.  
  45. - id: air2_0900
  46.   alias: "Air2 09:00 - 11:59"
  47.   trigger:
  48.     - platform: time
  49.       at: "09:00:00"
  50.   action:
  51.     - service: switch.turn_off
  52.       target:
  53.         entity_id: switch.all_air_switch
  54.     - delay: "00:00:15"   # รอ 15 วินาที      
  55.     - service: switch.turn_on
  56.       target:
  57.         entity_id: switch.air2_switch
  58.  
  59. - id: air1_1200
  60.   alias: "Air1 12:00 - 14:59"
  61.   trigger:
  62.     - platform: time
  63.       at: "12:00:00"
  64.   action:
  65.     - service: switch.turn_off
  66.       target:
  67.         entity_id: switch.all_air_switch
  68.     - delay: "00:00:15"   # รอ 15 วินาที      
  69.     - service: switch.turn_on
  70.       target:
  71.         entity_id: switch.air1_switch
  72.  
  73. - id: air2_1500
  74.   alias: "Air2 15:00 - 17:59"
  75.   trigger:
  76.     - platform: time
  77.       at: "15:00:00"
  78.   action:
  79.     - service: switch.turn_off
  80.       target:
  81.         entity_id: switch.all_air_switch
  82.     - delay: "00:00:15"   # รอ 15 วินาที    
  83.     - service: switch.turn_on
  84.       target:
  85.         entity_id: switch.air2_switch
  86.  
  87. - id: air1_1800
  88.   alias: "Air1 18:00 - 20:59"
  89.   trigger:
  90.     - platform: time
  91.       at: "18:00:00"
  92.   action:
  93.     - service: switch.turn_off
  94.       target:
  95.         entity_id: switch.all_air_switch
  96.     - delay: "00:00:15"   # รอ 15 วินาที      
  97.     - service: switch.turn_on
  98.       target:
  99.         entity_id: switch.air1_switch
  100.  
  101. - id: air2_2100
  102.   alias: "Air2 21:00 - 23:59"
  103.   trigger:
  104.     - platform: time
  105.       at: "21:00:00"
  106.   action:
  107.     - service: switch.turn_off
  108.       target:
  109.         entity_id: switch.all_air_switch
  110.     - delay: "00:00:15"   # รอ 15 วินาที      
  111.     - service: switch.turn_on
  112.       target:
  113.         entity_id: switch.air2_switch

5. ที่เครื่อง PI เพิ่มไฟล์ 4 ไฟล์ สำหรับ HA เรียกใช้
On_air1.py, On_air2.py, Off_air1.py, Off_air2.py
Code
On_air1.py
  1. #!/usr/bin/python3
  2. import time
  3. import RPi.GPIO as GPIO
  4.  
  5. GPIO.setmode(GPIO.BCM)
  6.  
  7. GPIO.setwarnings(False)
  8. GPIO.setup(20, GPIO.OUT)
  9. GPIO.output(20, GPIO.LOW)
  10. #GPIO.setup(21, GPIO.OUT)
  11. #GPIO.output(21, GPIO.LOW)
  12.  
  13. ##### Rocketchat #####
  14. import requests
  15. from datetime import datetime
  16. def send_to_rocketchat(message):
  17.    url = "http://xx.xx.xx.xx:3000/api/v1/chat.postMessage"
  18.  
  19.    headers = {
  20.       "Content-type": "application/json",
  21.       "X-Auth-Token": "XXX",
  22.       "X-User-Id": "XXX"
  23.    }
  24.  
  25.    payload = {
  26.        "channel": "#Test", #IT_Notification
  27.        "text": message
  28.    }
  29.    response = requests.post(url, json=payload, headers=headers)
  30.  
  31. message = "แจ้งเตือน เปิด AIR1 ปิด AIR2 " + datetime.today().strftime('%Y-%m-%d %H:%M:%S')
  32.  
  33. send_to_rocketchat(message)
  34.  

On_air2.py
  1. #!/usr/bin/python3
  2. import time
  3. import RPi.GPIO as GPIO
  4.  
  5. GPIO.setmode(GPIO.BCM)
  6.  
  7. GPIO.setwarnings(False)
  8. #GPIO.setup(20, GPIO.OUT)
  9. #GPIO.output(20, GPIO.LOW)
  10. GPIO.setup(21, GPIO.OUT)
  11. GPIO.output(21, GPIO.LOW)
  12.  
  13.  
  14. ##### Rocketchat #####
  15. import requests
  16. from datetime import datetime
  17. def send_to_rocketchat(message):
  18.    url = "http://192.168.2.76:3000/api/v1/chat.postMessage"
  19.  
  20.    headers = {
  21.       "Content-type": "application/json",
  22.       "X-Auth-Token": "XXX",
  23.       "X-User-Id": "XXX"
  24.    }
  25.  
  26.    payload = {
  27.        "channel": "#Test", #IT_Notification
  28.        "text": message
  29.    }
  30.    response = requests.post(url, json=payload, headers=headers)
  31.  
  32. message = "แจ้งเตือน เปิด AIR2 ปิด AIR1 " + datetime.today().strftime('%Y-%m-%d %H:%M:%S')
  33.  
  34. send_to_rocketchat(message)
  35.  

Off_air1.py

  1. import time
  2. import RPi.GPIO as GPIO
  3.  
  4. GPIO.setmode(GPIO.BCM)
  5.  
  6. GPIO.setwarnings(False)
  7. GPIO.setup(20, GPIO.OUT)
  8. GPIO.output(20, GPIO.HIGH)
  9. #GPIO.setup(21, GPIO.OUT)
  10. #GPIO.output(21, GPIO.HIGH)
  11. GPIO.cleanup()
  12.  

Off_air2.py
  1. #!/usr/bin/python3
  2. import time
  3. import RPi.GPIO as GPIO
  4.  
  5. GPIO.setmode(GPIO.BCM)
  6.  
  7. GPIO.setwarnings(False)
  8. #GPIO.setup(20, GPIO.OUT)
  9. #GPIO.output(20, GPIO.HIGH)
  10. GPIO.setup(21, GPIO.OUT)
  11. GPIO.output(21, GPIO.HIGH)
  12. GPIO.cleanup()

 

Home Assistant with Docker HACS+Editor-card

 Home Assistant with Docker HACS+Editor-card

 

1. add lxc debian template
2. install sudo ติดตั้ง docker และ program ที่ต้องใช้
  1. for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do apt-get remove $pkg; done
  2. apt-get install ca-certificates curl
  3. install -m 0755 -d /etc/apt/keyrings
  4. curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
  5. echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  6. $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |   tee /etc/apt/sources.list.d/docker.list > /dev/null
  7. apt-get update
  8. apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

3.ติดตั้ง Portainer : https://intranet.scivalve.com/blog.php?u=3&b=1961
  1. docker volume create portainer_data
  2. docker run -d -p 8000:8000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:latest

4. สร้างที่เก็บ config
  1. mkdir /HA

5. ติดตั้ง docker แล้วตั้งค่า
  1. docker run -d \
  2.   --name homeassistant \
  3.   --privileged \
  4.   --restart=unless-stopped \
  5.   -e TZ=Asia/Bangkok \
  6.   -v /HA:/config \
  7.   -v /run/dbus:/run/dbus:ro \
  8.   --network=host \
  9.   ghcr.io/home-assistant/home-assistant:stable

6. ติดตั้ง HACS
  1. docker ps
  2. docker exec -it [CONTAINER_ID] bash -c "wget -O - https://get.hacs.xyz | bash -"

7. restart HA
  1. docker restart <container_name_or_id>

8. เข้า IP:8123 ตั้งค่า HA, Password และอื่น ๆ เพิ่ม integration ชื่อ HACS
เข้าไปที่ Settings --> Devices & Services กด Add integration ค้นหา HACS เพิ่มกด Link ไป github แล้วเอา เลยไปใส่ใน Account github
9. ติดตั้ง Config Editor เพื่อช่วยแก้ไฟล์ config ต่าง ๆ
- เข้าเมนู HACS
- ค้นหาคำว่า config editor
- Download addon ทั้ง 2 ตัว (Config Editor, Config Editor Card)
- เพิ่มข้อความในไฟล์ configuration.yaml
  1. config_editor:


- Restart HA + Reload browser
- เพิ่มเมนูใน Dashboard
- Setting --> Dashboards --> + Add dashboard
- ไปที่ Dashboards ที่เพิ่มมาใหม่ เปลี่ยน View configuration ที่ Add ขึ้นมาใหม่ให้เป็น Panel (single card) เพื่อจะได้เต็มจอ
- Add card ค้นหา Config Editor Card กด save
type text จะเป็น
  1. type: custom:config-editor-card