후딱 주문을~~

최근에 홈서버도 Proxmox로 재구성하기 시작했고, (비록 소소하지만 … ) 모니터링 할만큼의 부하가 오는건 아니지만, 그래도 궁금하달까…
뽀대가 있달까… +ㅁ+)b
결론적으로는 다음과 같은 화면이 만들어졌다.

엄청 삽질 하긴했지만 GPT넘의 도움으로 해결하긴했지만, 엄둥한 코드를 이것저것 던지는 바람에 더 해깔려서 오래 걸린거 같다.
아두이노 IDE 세팅까지는 물어봐도 될거 같고 핵심은 이녀석의 이름이다.
“싼 노란색 디스플레이” 즉, cheap yellow display 이걸로 구글에 검색하면 모든 설정 파일 및 이슈를 한번에 해결 할 수 있다. (참고: https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display )
TFT_eSPI 설정 파일을 꼭 참조하도록 하자 …
그리고 PROXMOX의 API를 이용하는데 키를 생성하면 위 화면상의 값들을 RestAPI로 받을 수 있게된다.
postMan으로 미리보기 할 때 생성한 키를 Bearer Token에 세팅하면 끝…

난 그리는 함수 따위 모르니 GTP 녀석에게 부분 부분 케물어서 다음과 같은 소스 코드를 완성할 수 있다.
#include <TFT_eSPI.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <WiFiClientSecure.h>
#include <ArduinoJson.h>
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
TFT_eSPI tft = TFT_eSPI();
const char* ssid = "jusun";
const char* password = "와이파이비번";
const char* token = "Bearer PVEAPIToken=root@pam!LVGL=proxmox키이키키키";
void fnConnectWifi(){
WiFi.begin(ssid, password);
Serial.print("WiFi 연결 중");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWiFi 연결 완료!");
Serial.print("IP 주소: ");
Serial.println(WiFi.localIP());
}
//공용변수
float g_cpu = 0;
uint64_t g_mem_used = 0;
uint64_t g_mem_total = 0;
unsigned long g_uptime = 0;
String g_loadavg1 = "";
String g_loadavg5 = "";
String g_loadavg15 = "";
void fnGetProxmoxStatus() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure(); // 인증서 무시
HTTPClient https;
https.begin(client, "https://192.168.1.200:8006/api2/json/nodes/pve/status");
https.addHeader("Authorization", token);
int httpCode = https.GET();
if (httpCode > 0) {
String payload = https.getString();
Serial.println("응답:");
Serial.println(payload);
// JSON 파싱
StaticJsonDocument<2048> doc; // 크기 넉넉히 잡기
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
g_cpu = doc["data"]["cpu"].as<float>();
g_mem_used = doc["data"]["memory"]["used"].as<uint64_t>();
g_mem_total = doc["data"]["memory"]["total"].as<uint64_t>();
g_uptime = doc["data"]["uptime"].as<unsigned long>();
g_loadavg1 = doc["data"]["loadavg"][0].as<String>();
g_loadavg5 = doc["data"]["loadavg"][1].as<String>();
g_loadavg15 = doc["data"]["loadavg"][2].as<String>();
Serial.printf("CPU 사용률: %.2f%%\n", g_cpu * 100);
Serial.printf("메모리 사용량: %llu / %llu bytes\n", g_mem_used, g_mem_total);
Serial.printf("업타임: %lus\n", g_uptime);
} else {
Serial.print("JSON 파싱 실패: ");
Serial.println(error.c_str());
}
} else {
Serial.printf("HTTP 오류: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
}
}
struct VMInfo {
uint64_t vmid;
String name;
String status;
float cpu;
uint64_t mem;
uint64_t maxmem;
unsigned long uptime;
};
//qemu
VMInfo g_qemu_list[20];
int g_qemu_count = 0;
void fnGetProxmoxQEMUStatus() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure(); // 인증서 무시
HTTPClient https;
https.begin(client, "https://192.168.1.200:8006/api2/json/nodes/pve/qemu");
https.addHeader("Authorization", token);
int httpCode = https.GET();
if (httpCode > 0) {
String payload = https.getString();
Serial.println("응답:");
Serial.println(payload);
// JSON 파싱
StaticJsonDocument<2048> doc; // 크기 넉넉히 잡기
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
JsonArray data = doc["data"];
g_qemu_count = min(20U, data.size());
for (int i = 0; i < g_qemu_count; i++) {
JsonObject vm = data[i];
g_qemu_list[i].vmid = vm["vmid"].as<uint64_t>();
g_qemu_list[i].name = vm["name"].as<String>();
g_qemu_list[i].status = vm["status"].as<String>();
g_qemu_list[i].cpu = vm["cpu"].as<float>();
g_qemu_list[i].mem = vm["mem"].as<uint64_t>();
g_qemu_list[i].maxmem = vm["maxmem"].as<uint64_t>();
g_qemu_list[i].uptime = vm["uptime"].as<unsigned long>();
}
} else {
Serial.print("JSON 파싱 실패: ");
Serial.println(error.c_str());
}
} else {
Serial.printf("HTTP 오류: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
}
}
//LXC
VMInfo g_lxc_list[20];
int g_lxc_count = 0;
void fnGetProxmoxLXCStatus() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure(); // 인증서 무시
HTTPClient https;
https.begin(client, "https://192.168.1.200:8006/api2/json/nodes/pve/lxc");
https.addHeader("Authorization", token);
int httpCode = https.GET();
if (httpCode > 0) {
String payload = https.getString();
Serial.println("응답:");
Serial.println(payload);
// JSON 파싱
StaticJsonDocument<2048> doc; // 크기 넉넉히 잡기
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
JsonArray data = doc["data"];
g_lxc_count = min(20U, data.size());
for (int i = 0; i < g_lxc_count; i++) {
JsonObject vm = data[i];
g_lxc_list[i].vmid = vm["vmid"].as<uint64_t>();
g_lxc_list[i].name = vm["name"].as<String>();
g_lxc_list[i].status = vm["status"].as<String>();
g_lxc_list[i].cpu = vm["cpu"].as<float>();
g_lxc_list[i].mem = vm["mem"].as<uint64_t>();
g_lxc_list[i].maxmem = vm["maxmem"].as<uint64_t>();
g_lxc_list[i].uptime = vm["uptime"].as<unsigned long>();
}
} else {
Serial.print("JSON 파싱 실패: ");
Serial.println(error.c_str());
}
} else {
Serial.printf("HTTP 오류: %s\n", https.errorToString(httpCode).c_str());
}
https.end();
}
}
void fnDrawScreen() {
static float last_cpu = -1;
static uint64_t last_mem_used = 0;
static uint64_t last_mem_total = 0;
static unsigned long last_uptime = 0;
tft.setTextSize(2);
tft.setTextColor(TFT_WHITE, TFT_BLACK); // 배경색 포함 덮어쓰기
if (g_cpu != last_cpu) {
tft.setCursor(6, 37);
tft.print("CPU: ");
tft.print(g_cpu * 100, 2);
tft.print("% ");
tft.setCursor(160, 40);
tft.setTextSize(1);
tft.print("Load: ");
tft.print(g_loadavg1);
tft.print(" ");
tft.print(g_loadavg5);
tft.print(" ");
tft.print(g_loadavg15);
last_cpu = g_cpu;
}
tft.setTextSize(2);
if (g_mem_used != last_mem_used || g_mem_total != last_mem_total) {
tft.setCursor(6, 57);
tft.printf("MEM: %llu / %llu MB ", g_mem_used / (1024 * 1024), g_mem_total / (1024 * 1024));
last_mem_used = g_mem_used;
last_mem_total = g_mem_total;
}
if (g_uptime != last_uptime) {
tft.setCursor(6, 77);
unsigned long days = g_uptime / 86400;
unsigned long hours = (g_uptime % 86400) / 3600;
unsigned long minutes = (g_uptime % 3600) / 60;
unsigned long seconds = g_uptime % 60;
tft.printf("UPT: %lud %02luh %02lum %02lus ", days, hours, minutes, seconds);
last_uptime = g_uptime;
}
}
//qemu list
void drawQemuList(){
int y = 125; // 시작 위치
tft.setTextSize(1);
int total_vm_slots = ARRAY_SIZE(g_qemu_list);
std::sort(g_qemu_list, g_qemu_list + g_qemu_count, [](const VMInfo &a, const VMInfo &b) {
return a.vmid < b.vmid;
});
for (int i = 0; i < total_vm_slots; i++) {
if(g_qemu_list[i].name.length() == 0){
continue;
}
tft.setCursor(4, y);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.print("[");
tft.print(g_qemu_list[i].name.c_str());
tft.print("] ");
if(g_qemu_list[i].status == "running"){
tft.print(g_qemu_list[i].cpu * 100);
}else{
tft.print("0.00");
}
tft.print("% ");
tft.print(" ");
//tft.print("/");
//tft.print(g_qemu_list[i].mem / 1024.0 / 1024.0);
if(g_qemu_list[i].status == "running"){
tft.fillCircle(144, y+3, 5, TFT_GREEN);
}else{
tft.fillCircle(144, y+3, 5, TFT_RED);
}
/*
tft.print(g_cpu * 100, 2);
tft.print("% ");
tft.printf("[%s] %s | CPU: %.1f%% | MEM: %.1fMB ",
g_qemu_list[i].name.c_str(),
g_qemu_list[i].status == "running" ? "ON " : "OFF",
g_qemu_list[i].cpu * 100,
g_qemu_list[i].mem / 1024.0 / 1024.0
);
*/
y += 16;
}
}
//qemu list
void drawLXCList(){
int y = 125; // 시작 위치
tft.setTextSize(1);
int total_vm_slots = ARRAY_SIZE(g_lxc_list);
std::sort(g_lxc_list, g_lxc_list + g_lxc_count, [](const VMInfo &a, const VMInfo &b) {
return a.vmid < b.vmid;
});
for (int i = 0; i < total_vm_slots; i++) {
if(g_lxc_list[i].name.length() == 0){
continue;
}
tft.setCursor(164, y);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.print("[");
tft.print(g_lxc_list[i].name.c_str());
tft.print("] ");
if(g_lxc_list[i].status == "running"){
tft.print(g_lxc_list[i].cpu * 100);
}else{
tft.print("0.00");
}
tft.print("% ");
tft.print(" ");
//tft.print("/");
//tft.print(g_qemu_list[i].mem / 1024.0 / 1024.0);
if(g_lxc_list[i].status == "running"){
tft.fillCircle(305, y+3, 5, TFT_GREEN);
}else{
tft.fillCircle(305, y+3, 5, TFT_RED);
}
y += 16;
}
}
void drawLayoutLine(){
tft.fillRect(0, 0, tft.width(), tft.height(), TFT_BLACK); //전체 배경
tft.fillRect(0, 0, tft.width(), 32, TFT_BLUE); //상단 배경
tft.drawLine(0,32,tft.width(),32,TFT_WHITE); //상단줄
tft.drawLine(0,32,tft.width(),32,TFT_WHITE); //상단줄
tft.setTextSize(2);
tft.setTextColor(TFT_WHITE, TFT_BLUE); // 배경색 포함 덮어쓰기
tft.setCursor(6, 10);
tft.printf("Jusun Lab. Proxmox Monitor");
tft.fillRect(0, 97, tft.width(), 117-97, TFT_BLUE); //중단 배경
tft.drawLine(0,97,tft.width(),97,TFT_WHITE); //중간줄
tft.setTextSize(1);
tft.setCursor(70, 104);
tft.printf("QEMU");
tft.setCursor(230, 104);
tft.printf("LXC");
tft.drawLine(0,117,tft.width(),117,TFT_WHITE); //중간줄2
tft.drawLine(tft.width()/2,97,tft.width()/2,tft.height(),TFT_WHITE); //세로줄
tft.drawRect(0, 0, tft.width(), tft.height(), TFT_WHITE); //틀
}
void setup() {
Serial.begin(115200);
//wifi Connect
fnConnectWifi();
pinMode(TFT_BL, OUTPUT);
digitalWrite(TFT_BL, HIGH); // 백라이트 켜기(중요!)
// Start the tft display and set it to black
tft.init();
tft.setRotation(1); //This is the display in landscape
drawLayoutLine();
}
void loop() {
static unsigned long lastRequest = 0;
if (millis() - lastRequest > 1000) {
fnGetProxmoxStatus();
fnGetProxmoxQEMUStatus();
fnGetProxmoxLXCStatus();
lastRequest = millis();
fnDrawScreen();
drawQemuList();
drawLXCList();
}
//delay(200);
}
비워진 부분은 체워서 가동해보면 문제 없다면, 잘 작동할 것이다.
proxmox API 주소도 자신의 네트워크에 맞는걸로… 1초에 한번씩 고치는데 … 이걸 통해서 부하기 크게 생기진 않는것 같으니 적당히 고쳐서 쓰도록 하자 -ㅅ-)
할사람이 있을지 모르겠지만….
난 이 디스플레이가 너무 마음에 들어서 가지고 놀려고 하나더 주문함..
굳럭!
]]>집안 네트워크에서 간단한 통신을 하기 위해서 미리 설치해보는 용도입니다. 정확한 용도는 아직 비밀…
(데비안 기반에서 설치하는겁니다. 다른 OS도 크게 다르지 않을 듯… )
일단 넵다 설치…
sudo apt install mosquitto mosquitto-clients
mosquitto : 모기?? MQTT프로토콜을 위한 브로커 서버 역할인건가…
mosquitto-clients: 이건 일단 테스트를 위해서 설치
서버 시작시 시작하도록 설정하기
sudo systemctl enable mosquitto
/etc/mosquitto/mosquitto.conf 편집
listener 1883
bind_address 0.0.0.0 #이건 적당히 내부 네트워크만 접근해야해서 192.168.1.0 하면될듯...
받는놈 부터 가동(subscribe? )
mosquitto_sub -h localhost -t "test/topic"
수신을 확인해야 하기 때문에 다른 터미널에서 가동하도록 하자…
보내는놈(퍼블리싱?)
mosquitto_pub -h localhost -t "test/topic" -m "Hello, MQTT!"
특정 브로커(localhost)에 특정 토픽(test/topic)에 메시지(Hello, MQTT!)를 전달하는 것 같군….
※ 이 문서는 내가 알아볼 수있게 작성한거라서 나중에 다시 업데이트 될 수 있음.
]]>
다른 OS 사용해봤는데.. 잘 안되는 것 같고… ARMBIAN에서 잘 연동되고 작동되네요..
우선 핀 배치가 필요한데.. OLED는 I2C 방식이라 4개의 핀을 연결해줘야합니다. 판매 패이지에 가보면 핀을 확인할 수 있는데 I2C3 라는 부분에 OLED의 SDA, SCK 를 연결하하고, 5V 를 VDD, GND는 GND에 연결합니다.
(참고로, SPI는 TFT 스크린방식으로 연결 하는 방법)

주의: VDD, GND 거꾸로 끼우면 OLED에서 연기납니다.(당함;; ㅠ_ㅠ )
그다음에 콘솔에 접속하여 명령줄에 armbian-config 를 입력.
System -> Kennel -> Manage device tree overlays -> “i2c3-ph” 라고 붙은걸 선택합니다.

Save후 Back을 선택하면 리부팅하게됩니다.
이 부분 버전에 따라 다를 수는 있는데 최대한 비슷한걸로 i2c3 중에 하나 선택해서 써보심 됨.
이건 안되면 여러번 시도 해볼 수 밖에 없는거 같네요….
원래라면 이렇게 해야되지만……armbian 버전업하면서 목록에서 사라진거 같네요..
/boot/armbianEnv.txt 파일에 다음 내용을 직접 추가해야합니다.
overlays=i2c3-ph
작성 후 리부팅…
초기 설치시 다음과 같은 패키지를 설치해야합니다. 그때그때 필요하다고 한걸 하나씩 추가한거라 진행할려고하는 프로젝트와 차이가 있을 순 있어요..
apt install i2c-tools python3 python3-pip python3-dev python3-rpi.gpio python3-spidev
그 다음에 파이선 패키지 설치. 호환이 안되는건지 break system packages를 넣어줘야 설치가되네요
pip install luma.oled --break-system-packages
i2cdetect로 제대로 연결되었는지 확인해봅니다. 포트를3을 열었으니 0,1,2 순으로 적용되어 2번을 찾아야합니다.
root@orangepizero3:~# i2cdetect -y 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- 3c -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
올바른 연결이 되어있다면 3C로 확인됩니다. 코드에서 사용되는 연결 정보임으로 잘 기록해둡니다.
안되면, amrbian-config 다시 반복 …
0번 1번도 있는데 다른용도로 사용되는거 같에요. (라즈베리파이는 0번 쓸겁니다.)
0번으로 연결되어있다고 믿고 뭔가 하다보면 연결된 모니터가 줄이거거나 모니터 프로그램에 오류를 일으키더군요 -_-
이제 파이선 코드를 짜봅시다. 프롬프트에서 nano test.py 이렇게 하시면 파일 작성되죠…
from luma.core.interface.serial import i2c
from luma.core.render import canvas
from luma.oled.device import ssd1306, ssd1325, ssd1331, sh1106
import time
serial = i2c(port=2, address=0x3C)
device = ssd1306(serial, rotate=0)
with canvas(device) as draw:
draw.text((10, 0), "Hello World!", fill="white")
draw.text((10, 20), "Hello World!", fill="white")
while 1:
time.sleep(1)
위 코드 처럼 i2c부분은 i2cdetect에서 확인된 값으로 맞춰줘야합니다.
ssd1306 이라고 된 부분은 연결되는 oled의 칩에 따라 다른데
보통 알리에서 샀으면
0.9 인치는 ssd1306이였고
1.3인치는 sh1306으로 맞추니 되더군요.. (이건 판매 패이지 참조)
위 코드는 hello world 만 2번 찍힐 뿐이고….
이제 열심히 꾸며볼수있겠죠… 시간이라든가 날씨라든가… 시스템 정보라든가…..
그럼 여기까지 삽질기였습니다.
※ 삽질한거 다시 정리한거라 이글 보고 다 안될수도 있음…
끝~
]]>

(후… 사진입니다. )
-ㅁ-)… 그나마 청소를 했으니 조금 볼만해졌네요 ^^
무지성으로 물만 갈아줬더니 녹조에 녹점에 그냥 ㄷㄷㄷ …
여기는 시판 나나를 종류별로 모아서 키우는 용도로 썼었는데 조금씩 녹고 있어서 청소를 한번 싹 했습니다.
가운데 있던 커피폴리아는 스르르륵… 녹아서 잎만 다 떨궜네요 -_-… 그러면서 백탁도 확 오고…
(나나 녹으면 백탁 오나봐요… -_-a, 커피폴리아 녹은건 넘 잔인해서 생략합니다. ㄷㄷ )
다른 나나에도 영향을 주나 보더라고요… 같이 좀 녹았습니다. 새우도 다 사라졌습니다. (독성?)
그 와중에 물미역모스는 5배는 커진거 같에요…
나나항 이야기는 여기까지 … -ㅅ-).. 날 잡아서 어떻게든 해봐야겠어요… ㅋㅋ
예전에 넣어두었던 마블 나나 두촉을 빼왔습니다.

그러고는 수상 세팅을 시작했어요..
(와비쿠사통이 였지만… 잘 되고 있지 않아서 다른통으로 이사갔어요… )
어디서 본건있어서 빨대(?)를 새워둡니다. =_=) 이게 22mm 여과기 파이프였나 그럴겁니다.
제가 하는게 올바르지 않을수도 있어서 …. ㅋㅋㅋ 참고만 참고만요! (참지마요… 참치마요?)
난석을 깔고~

태운 흑미를 깔아줍니다.
(응????)
죄송합니다 훈탄입니다. =_=) 왕겨 같은건데 태웠나바여

적옥토와 쓰던 소일을 섞었어요..
한숱가락씩 정성스럽게 … 너도 한잎 나도 한잎…..
이게 알아보니 사람마다 다 다릅니다. 전 그냥 이렇게 했습니다.

아까 어항에서 빼온 나나를 준비합니다.
힘순찐이네요 ㅎㅎㅎ 위는 다 초록이지만 아래에서 무늬 잎이 나오고 있었어요…
하나더 있는데 안찍었군요 =_=) 다음 사진에 있어요..

심습니다.
환수 구멍은 돌로 막아놨습니다.
그러고는 촉초옥~~하게 분무질 해줬어요..

뭐 더 심을건 없고해서 이렇게 마무리했어요…
오늘은 여기까지 -ㅅ-)/”
뭘 더 심을지는 고민좀 해봐야겠어요..
]]>부세파란드라의 사육법에 대해서 정리해 놓으려고합니다.
저도 수문원에서 어깨넘어로 이리저리 배우고 좋다는거 해보고 있습니다.
전경옹한테 진짜 많이 배웠어요.. -ㅅ-)b (동지님이 잠시 자리를 비우셔서 아쉽지만요… )
1. 마음가짐

내 부세가 반짝반짝 빛나지 않는다고 실망마세요..
얘도 원래는 ….

예쁜거 사왔는데 키우다보니.. 잎도 다 떨어지고 거의 벌브만 남았으니깐요.. ㄷㄷ
첨에는 이렇게 하면 죽는다 생각했는데… 부세는 유경이랑 다릅니다…
살아요! +ㅁ+)/” 삽니다.
환경이 바껴서 새로운 물에 적응하도록 변화하고 있을 뿐이죠…. 가끔 새로운뿌리가 돋지 않는다면,
한번씩 꺼내서 줄기를 확인해보고 물러 있다면 뜯어줘야합니다.
너덜너덜 한게 보기 좀 그렇다면 같은 어항 내에 안보이는데 짱박아두세요 =_=)…. (저도 자주 그래요 ㅋㅋ)
아래 사진에서 위사진으로 바뀌기까지 최소 3~6개월 걸릴겁니다.
그래도 죽으면 .. 나랑 안 맞는거라고 배웠…. (퍽… )
2. 활착

활착은… 눕혀서 합니다. -_-… 이게 뭔가 극단적일 수도 있는데…. 어짜피 내 어항에 오면… 잎 다 떨어지지 않을까 하는 우려도 있고 … 다글다글하게 자라는 것을 기대하는 마음도 있습니다. -ㅁ- ㅋㅋ
작고 깜찍한게 더 이쁘잖아요…
식물에는 생장점이라는게 있다더군요.. 보통 우리가 사온 위쪽으로 자라는 한촉.. 생장점이 1개 있는거죠 …
눞여서 키우면 생장점이 있는 자리는 빛을 따라갑니다. ㄴ자로 굽어져서 자라게되죠..
그러다가 무슨일이 있어서 생장점이 죽으면, 벌브에서 수많은 생장점이 나타나더군요.. 그러면서 잎이 다글다글 해지는…
부세가 뿔어나는 기적-_-a
다글다글 해지고나서 부터는 어떻게 해야할지 아직 모르겠습니다. ㅋㅋ
이건 부세에 따라 다릅니다. 말짱히 식형 좋은 부세 괜히 눞여서 당분간 안이뻐 질수도 있으니 … -ㅁ- ㅋㅋ
이쁜건 이쁜데로 키우는게 잴 좋아요..
3. 환수

부세 환수는 물 쫙~ 빼리고 배웠습니다. -ㅁ-)
부세의 환경이 수륙양용이라고…
그래서 90%쯤 부세가 물 밖으로 다 나오게 환수합니다. 이때 물빼고 바로 물을 넣지 않고 살짝 건조하게 둡니다.
왠지는 모르겠지만 이끼 방지에 도움이 되는거 같에요… 벽면 열심히 닦아주고 ^^ 벽면만 깔끔깔끔….~
이때 나온짐에 플로엑셀 이런거 뿌리면 안되요…. 제가 해보니.. 탈색되고… 클나유… (야한거 안대~)
식물에 이끼 있다고 닦으면 안됩니다. (헉ㅋㅋㅋ)
환수의 주기는 3~4일로 하고 있지만… 물을 많이 빼고 하는 환수라 일주일에 한번씩해도 괜찮을 것 같습니다.
4. 비료 & 바닥재

부세 비료 필요없다 들었는데 어떨진 모르겠습니다. 전 일단 주고 있습니다. 안먹으면 모스가 먹겠죠 -ㅁ-);;
액비를 주로 쓰고있습니다.
쫄아서 많이 안주고 있어요…
환수 후 권장량의 1/3 정도 네오2 넣어줍니다.
부스터, 에센스 넣어줍니다.
부스터는 여과기 슬러지를 발생시키더군요.. 여과기에 스펀지는 빼주는게 좋더군요..
스펀지 여과기 쓰는 어항에는 부스터 비추입니다.
이틀뒤 네오1 넣어줍니다. 마찬가지로 권장량의 1/3…
자작비료도 있지만 생각하기 싫어서 (네오1,2 써요 -_-;; ㅋㅋ)
비료 과하면 뒷탈이 어우~ … 1/3 보다 더 적게 넣으세요..
비료의 양은 수조내의 수초의 량에 따라 다르지 않나 싶어요 …
바닥재는 비료끼가 없어야할겁니닭…. 다른데 쓰다가 뺀 마피드 씻어서 깔아놨어요..
(다른 소일은 못씻는데 이건 씻어서 써도 괜찮…)
프리미엄소일이런건 안된다 그러더군요.. (안된다 그래서 시도도 안해봄.. ㅋㅋ)
안까는검 좀 허전하고… 뭔가 떠다니는 찌꺼기만 가둘수 있으면 괜찮지 않을까요… 흑사 권장!
5. 이끼의 제거

이끼 제거는 예전에 제가 해둔 메모로 대신합니다.

동지님 +ㅁ+)b
큰환수와 이탄과 여러가지 이유로 새우는 자꾸 죽어나갑니다. (이끼관리상 분기별로 새우 보급필요)
6. 조명 & 이탄

고광량 하면 부세가 하얗게 되더군요 환경변화 때문인진 모르겠지만, 하얗게된 잎은 결국 구멍나거나 떨어지더군요..
적당한 광량이 중요한것 같습니다. 전 메탈라이트 ver2 디머로 40% 정도로 조정해서 사용합니다.
플랜츠 라이트 마렵긴하지만… 일단 있는데로 할려고요.. (주인마님의 허락이 … ) 플라는 2~30% 쓴다고 그러더라고요.
고수님들만의 세팅값이 있던거 같아요 ^^ (찾아보시길…)
좋은 조명쓰면 활용할 수 있는 스펙트럼이 확실히 넓어서 >_<)b 권장합니다.
이탄은 -ㅅ- 수조내에 잔잔히 흩어지도록 적당량을 풀어주세요…
(너무 많이 풀면 새우 용병들이 좀 힘들어해서 … 수조 크기에 따른 일반적인 수준이면 되지 않을까요… )
7. 시간

시간이 걸립니다. 꾸준히 환수해주고 관리해주신다면, 예쁨으로 보답할거에요 ^^
남에집 부세만 예뻐보인다고 실망마시고 꾸준히 가보세요 ~ ㅎㅎ

홧팅!!
수초 문화원에서 제가 적었던 글 : https://cafe.naver.com/iaplc/54997
]]>