IoT

라즈베리파이 부팅시 와이파이 설정 및 할당된 아이피 알림받기

콩메모 2024. 1. 3. 22:07

라즈베리파이제로에 라즈비안을 설치하였다.

와이파이를 설정하고 원격으로 접속하고 필요한 작업을 하는데, 들고 다니다가 와이파이 환경이 바뀐 곳에서는 다시 와이파이 설정하기 까다롭다.

그래서, 다음과 같은 절차를 생각해본다.

<시나리오>

SD카드를 컴퓨터에 꼽으면 boot 파티션이 연결된다. 그 드라이브 루트 아래에 와이파이 접속 정보를 가지고 있는 파일을 하나 생성해두고, 라즈베라피이가 부팅될 때 그 파일에서 와이파이정보를 가져와서 와이파이 설정을 한다.

그리고, 재부팅될 때 할당된 아이피를 텔레그램으로 쏴준다.

<작업전 준비사항>

원격 가능한 상태의 라즈베리파이를 준비한다.

<작업1> /boot/wifiinfo.txt 파일을 만든다.

SD카드를 컴퓨터에 연결하면 인식되는 드라이브가 하나 생긴다. 그 드라이브에 들어가서 루트에 wifiinfo.txt 파일을 만든 후, 아래와 같은 내용으로 저장한다.

SSID이름
와이파이비번

 

이제 SD카드를 라즈베리파이에 장착한 후 부팅을 해서 원격접속을 한다.

( 사실 이 작업은 작업이 완전히 마무리 된 후 와이파이 정보가 바뀌는 상황에 필요한 작업이다. 일단, 미리 준비해두기 위해 파일을 생성해둔다. )

<작업2> connect_wifi.sh 파일을 만든다.

/boot 파티션에 들어가보면 wifiinfo.txt 파일이 존재함을 확인할 수 있다.

그다음 자신의 루트폴더에 다음과 같은 쉘파일을 만든다.

cd
vi connect_wifi.sh

내용은 아래와 같이 한다.

#!/bin/bash

FILE="/boot/wifiinfo.txt"

if [ -f "$FILE" ]; then
    max_attempts=10
    attempt=0

    while true; do
        if ip link show wlan0 2>/dev/null | grep -q "state UP"; then
            echo "wlan0 is up and running."
            break
        else
            if [ $attempt -lt $max_attempts ]; then
                echo "Waiting for wlan0 to be available... Attempt $((attempt + 1)) of $max_attempts"
                sleep 5
                attempt=$((attempt + 1))
            else
                break
            fi
        fi
    done

    SSID=$(sed -n '1p' "$FILE" | tr -d '\r')
    PASSWORD=$(sed -n '2p' "$FILE" | tr -d '\r')

    /usr/sbin/wpa_cli -i wlan0 add_network
    /usr/sbin/wpa_cli -i wlan0 set_network 0 ssid "\"$SSID\""
    /usr/sbin/wpa_cli -i wlan0 set_network 0 psk "\"$PASSWORD\""
    /usr/sbin/wpa_cli -i wlan0 enable_network 0
    /usr/sbin/wpa_cli -i wlan0 save_config
    /usr/sbin/wpa_cli -i wlan0 reconfigure
else
    echo "The file $FILE does not exist. Exiting script."
fi

 

wifiinfo.txt 파일은 윈도우에서 만들었을수도 있고, 리눅스나 맥에서 만들어졌을수도 있다.

운영체제에 따라 엔터를 치면 \r\n문자가 들어갈수도 있고, \n만 들어갈 수도 있다.

\n 기준으로 1p, 2p 로 구분이 되어 \r 문자가 SSID와 비밀번호 끝에 추가될수도 있다.

그래서, 존재할지도 모르는 \r을 지워주는 작업을 해줘야 한다.

그리고, 와이파이가 잡혀이지 않은 상태일수도 있고, 잡혀있는 상태일수도 있는 상황일수도 있다.

아무튼 wifiinfo.txt 파일을 읽어들이기 전에 위에 몇가지 상황에 대한 처리를 해준다.

( wifiinfo.txt 파일이 존재하는 경우에만 실행되도록 한다 )

이제 이 파일을 실행가능하게 만들어준다.

chmod +x ./connect_wifi.sh

 

<작업3> connect_wifi.sh를 부팅때마다 실행시키도록 한다.

그다음 crontab을 이용하여 부팅될때마다 실행을 시켜준다.

crontab -e

 

가장 마지막 줄에 아래 줄을 입력한다.

@reboot /bin/bash /home/각자의경로/connect_wifi.sh > /home/각자의경로/connect_wifi.log 2>&1

실행결과를 로그파일에 남기도록 했는데, 경로는 편할대로 하면 된다.

이제 당신의 라즈베리파이는 부팅할 때마다 wifiinfo.txt 파일에서 와이파이 정보를 읽어와서 와이파이 연결을 하게 된다. ( 파일이 존재하지 않는 경우에는 아무 일도 일어나지 않는다. )

카페나 다른 곳에 가서 와이파이 잡을때는 SD카드를 컴퓨터에 연결하여 루트에 wifiinfo.txt 파일을 생성하여 카페의 와이파이 정보를 저장한 후 라즈베리파이에 장착하여 부팅해주면 와이파이가 잡히게 된다.

<작업4> alert.py 파일을 만든다.

아이피는 DHCP로 할당받으므로 어떤 아이피로 받는지 모른다.

집이라면 공유기에 접속하여 할당된 아이피를 알 수 있지만, 카페같은 공공장소라면 알 수 없다.

모니터도 장착할수 없는 상황이니 이왕이면 부팅될 때 할당된 아이피를 알림 받으면 좋을 것이다.

텔레그램은 개인이 봇을 만들고 자유롭게 쓸수 있어서 알림으로 쓰기 좋다.

자신의 루트경로에 아래와 같이 파이썬 파일을 만든다. ( 경로는 편한데 만들면 된다. )

vi alert.py

그런 후 아래와 같은 코드를 작성한다.

* 봇ID와 쳇ID는 아래 링크를 참조한다.

 

https://kongmemo.tistory.com/10

 

아두이노에서 텔레그램 알림 문자 보내기

아두이노에서 특정 상황에 폰으로 알림을 받고싶은 경우가 있는데, 이걸 처리하려면 직접 PUSH 앱을 만들던지, 범용적인 앱을 이용하던지, 해야 한다. ​ 기존에는 "푸시불릿"이 대안으로 많이 쓰

kongmemo.tistory.com

import socket
import time
import telepot

TOKEN = '자신이만들어둔봇ID'
CHAT_ID = '자신의쳇ID'

def get_ip_address():
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        IP = None
        try:
                s.connect(('8.8.8.8', 80))
                IP = s.getsockname()[0]
        except:
                pass
        finally:
                s.close()
        return IP

def send_telegram_message(message):
        try:
                bot = telepot.Bot(TOKEN)
                bot.sendMessage(chat_id=CHAT_ID, text=message, parse_mode='HTML')
        except:
                print('send message error')

if __name__ == '__main__':
        ip_address = get_ip_address()
        while ip_address is None:
                time.sleep(10)
                ip_address = get_ip_address()

        send_telegram_message(f"IP Address : {ip_address}")
 

위 코드를 실행하려면 telepot가 설치되어 있어야 한다.

설치가 안되어 있다면 설치한다.

pip install telepot

 

즉, 구글DNS에 연결을 시도해서 연결이 성공하면 아이피 할당받았다고 가정하고, 실패하면 10초 대기후 다시 연결해본다.

그리고, 연결이 되면 현재 아이피를 텔레그램으로 알려준다.

<작업5> alert.sh 파일을 만든다.

위와 같이 alert.py 파일을 만든후 이 또한 부팅시마다 실행되도록 해준다.

편하게 실행시키고자 아래와 같은 쉘파일을 또 만든다.

vi alert.sh

그리고, 아래와 같이 한줄을 입력후 저장한다.

python /home/각자의경로/alert.py

이제 alert.sh 파일을 실행가능하게 만든다.

chmod +x ./alert.sh

 

<작업6> alert.sh를 부팅시마다 실행되도록 한다.

그다음 crontab을 이용하여 부팅될때마다 실행을 시켜준다.

crontab -e

 

가장 마지막 줄에 아래 줄을 입력한다.

@reboot /bin/bash /home/각자의경로/alert.sh > /home/각자의경로/alert.log 2>&1

이제 다시 재부팅을 시켜보면 자신의 텔레그램봇으로부터 알림이 오게 된다.

<와이파이 연결후에 wifiinfo.txt 자동 삭제>

와이파이가 잡히는 경우에는 wifiinfo.txt 파일을 알아서 지워주면 편할것이다.

문제는 /boot/wifiinfo.txt 파일을 지우려면 루트권한이 필요하다.

그래서, 위에서 작업한 것들중 몇가지를 수정해본다.

<추가작업1> alert.py 수정

alert.py 파일은 와이파이가 잡히면 알림을 쏘는 것이므로, 알림을 쏜 다음에 wifiinfo.txt 파일이 존재하면 지워주면 될 것이다.

아래와 같이 수정한다.

import socket
import time
import telepot
import os

TOKEN = '자신의봇ID'
CHAT_ID = '자신의쳇ID'

def get_ip_address():
        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        IP = None
        try:
                s.connect(('8.8.8.8', 80))
                IP = s.getsockname()[0]
        except:
                pass
        finally:
                s.close()
        return IP

def send_telegram_message(message):
        try:
                bot = telepot.Bot(TOKEN)
                bot.sendMessage(chat_id=CHAT_ID, text=message, parse_mode='HTML')
        except:
                print('send message error')

if __name__ == '__main__':
        ip_address = get_ip_address()
        while ip_address is None:
                time.sleep(10)
                ip_address = get_ip_address()

        send_telegram_message(f"IP Address : {ip_address}")
		
        wifi_info_file = '/boot/wifiinfo.txt'

        if os.path.exists(wifi_info_file):
                try:
                        os.remove(wifi_info_file)
                        print(f"Deleted {wifi_info_file}")
                except Exception as e:
                        print(f"Error deleting {wifi_info_file}: {e}")

알림을 쏜 후 파일이 존재하면 삭제하는 코드를 추가하였다.

문제는 이 alert.py는 관리자권한으로 실행이 되어야 한다.

<추가작업2>

아마도 sudo alert.sh 명령을 실행시키면 telepot이 없다고 나올 수 있다.

그런 경우 아래와 같이 관리자에게도 설치를 해준다.

sudo pip install telepot

<추가작업3>

crontab -e 를 실행하여 기존에 등록해두었던 두 줄을 삭제한다.

그리고 다음과 같이 관리자의 crontab에 같은 내용을 등록한다.

> sudo crontab -e

@reboot /bin/bash /home/각자의경로/connect_wifi.sh > /home/각자의경로/connect_wifi.log 2>&1
@reboot /bin/bash /home/각자의경로/alert.sh > /home/각자의경로/alert.log 2>&1

위와 같이 하면 재부팅시에 실행되는 스크립트들이 관리자권한으로 실행되므로 /boot/wifiinfo.txt 파일을 삭제하는 것이 가능해진다.