DIR-320 + Freeduino: выводим системную информацию на LCD

Я долго думал, как можно сделать простой и удобный мониторинг роутера, а именно нагрузку, свободную память, аптайм и др. В этой статье я расскажу как можно подключить Freeduino к D-Link DIR-320 для вывода системной информации на LCD-дисплей. Всё не так трудно, как может показаться на первый взгляд.

Роутер содержит внутренний последовательный порт, который можно использовать для сервисных функций и отладки.

Его-то мы и задействуем. Его распиновка следующая:

Слева направо:

  • RX — приём
  • NC — не подключается (ключ)
  • VCC — питание (3.3 вольта)
  • GND — земля
  • TX — передача

Для наших нужд нужно только два контакта — GND и TX. Подключаем их к Freeduino: GND к GND, TX к RX (второй контакт).

LCD подключим к цифровым пинам с 8 по 13.

Теперь необходимо выяснить скорость порта роутера. Для этого в консоли по SSH/telnet даём команду:

cat /proc/tty/driver/serial

Должны увидеть что-то подобное:

Нас интересует строчка

0: uart:16550A port:B8000300 irq:3 baud:9585 tx:1009317 rx:0 CTS|DSR|CD

В данном случае скорость порта составляет 9585 бод.

Напишем скетч, который зальём в микроконтроллёр:

#include <LiquidCrystal.h>

// инициализируем библиотеку LCD
LiquidCrystal lcd(12, 13, 11, 10, 9, 8);

void ScreenSaver()
{
	int i;
	lcd.clear();
	lcd.setCursor(0,0);
	lcd.print(" D-Link DIR-320 ");
	lcd.setCursor(0,1);
	lcd.print(" & Freeduino ");
	delay(3000);
	lcd.clear();
	for (i=0;i<8;i++) 
	{ 
		lcd.setCursor(i,0); 
		lcd.print("="); 
		lcd.setCursor(16-i-1,0); 
		lcd.print("="); 
		delay(200); 
	} 
	lcd.clear(); 
}

void setup()
{ 
	// устанавливаем параметры дисплея: 
	lcd.begin(16, 2); 
	// инициализируем последовательный порт: 
	Serial.begin(9585); //здесь не забываем указать скорость вашего порта роутера 
}

void loop() 
{
	char s; 
	if (Serial.available()) 
	{ 
		delay(100); 
		while (Serial.available() > 0)
		{
			s = Serial.read();

			if (s == '^')
			{
				switch (Serial.read()) 
				{
					case '1':
						lcd.setCursor(0, 1);
						Serial.read();
						break;
					case '0':
						lcd.setCursor(0, 0);
						Serial.read();
						break;
					case 'c':
						lcd.clear();
						Serial.read();
						break;
					case 's':
						Serial.read();
						ScreenSaver();
						break;
				} //switch
			}
			else
			{
				// Выводим каждый символ на LCD
				lcd.write(s);
			}
		}
	}
}

Команды, подаваемые на микроконтроллёр будут такими:
^c: — очистить дисплей
^0:text — вывести text на первой строке
^1:text — вывести text на второй строке
^s: — вывести небольшую заставочку 🙂

Проверим работу. Введём в консоли роутера команду:

echo "Hello, world!" > /dev/tts/0

На экране должна появиться надпись.

Уже хорошо:)

Теперь необходимо научить маршрутизатор выводить информацию о своём состоянии. Для этого служит следующий скрипт:
lcdduino.sh

#!/bin/sh

port="/dev/tts/0"

lcdWrite() {
#Вывод на экран
echo -n "^"${1}:$2 > $port
}

lcdClear() {
#Очистка экрана
echo -n "^c:" > $port
}

lcdScreenSaver() {
#Запуск заставки
echo -n "^s:" > $port
}

WidgetLoad() {
#Отображение загрузки процессора
s=`/usr/bin/uptime`
s2=":"
for i in 1 2 3 4 5 6
do #Удаляем всё лишнее до последнего двоеточия
n=`expr index "$s" "$s2"`
s="${s:$n}"
done
s="${s:1}" #Удаляем первый символ (пробел)
lcdClear
lcdWrite 0 "Load CPU"
lcdWrite 1 "$s"
}

WidgetWiFiClientsCount() {
#Виджет, показывающий количество подключенных WiFi клиентов
s=`wl assoclist | wc -l`
lcdClear
lcdWrite 0 "Wi-Fi Clients"
lcdWrite 1 "$s"
}

WidgetUptime() {
#Аптайм роутера
s=`/usr/bin/uptime`
s2="l"
n=`expr index "$s" "$s2"`
n=`expr $n - 3`
s="${s:0:$n}"
s2="u"
n=`expr index "$s" "$s2"`
n=`expr $n + 2`
s="${s:$n}"
lcdClear
lcdWrite 0 "Uptime"
lcdWrite 1 "$s"
}

WidgetRAM() {
#Свободная память
set `cat /proc/meminfo | grep "Mem:"`
n=`expr $4 + $6 + $7`
p=`expr 100 '*' $n / $2`
n=`expr $n / 1024`
lcdClear
lcdWrite 0 "FreeRAM"
lcdWrite 1 "$n Kb ${p}%"
}

WidgetHDD() {
#Свободное место в /opt
set `df | grep "/opt"`
p=`expr 100 '*' $3 / $1`
n=`expr $3 / 1024`
lcdClear
lcdWrite 0 "Free HDD"
lcdWrite 1 "$n Mb ${p}%"
}

WidgetDateTime() {
#Дата и время
set `date`
lcdClear
lcdWrite 0 "$3 $2 $6"
lcdWrite 1 "$4"
}

#Main script
while [ : ]
do
WidgetRAM
sleep 3
WidgetLoad
sleep 3
WidgetUptime
sleep 3
WidgetWiFiClientsCount
sleep 3
WidgetHDD
sleep 3
WidgetDateTime
sleep 3
done

Запускаем скрипт, проверяем.

Скрипт добавляем в автозагрузку. Например, в файл /opt/etc/init.d/rc.firewall , который мы создали ранее.

/opt/etc/scripts/lcdduino.sh &