Router WiFi GSM utilizând Raspberry PI Zero W

Plăcile de dezvoltare Raspberry PI sunt cunoscute pentru ușurința cu care se poate implementa un router / gateway TCP/IP grație sistemului de operare Linux ce rulează pe aceste plăci. Placa Raspberry PI 3 ce integrează o interfață de rețea WiFi (pe lângă interfața ethernet clasică) poate sta la baza unui AP WiFi printr-o configurare foarte simplă (a se vedea „Cum putem utiliza placa Raspberry Pi ca Access Point WiFi?”). Chiar dacă implementarea unor astfel de dispozitive (router, gateway sau AP) poate părea la prima vedere doar un exercițiu educațional având în vedere multitudinea de dispozitive comerciale cu aceste funcționalități, realizarea unui sistem de control al comunicațiilor personalizat poate permite implementarea unor funcționalități proprii inedite și de multe ori un cost mai mic decât al dispozitivelor comerciale.

Placa de dezvoltare Raspberry PI Zero W este un membru mai nou al familiei de plăci Raspberry introducând un format mai mic al plăcii și un cost mult mai mic dar fiind limitată din punct de vedere al puterii de calcul și al memorie și neavând interfață de rețea ethernet (doar WiFi). La prima vedere această placă nu am putea să o utilizăm la implementarea unui sistem de tip router având o singură interfață de rețea. Având în vedere dimensiunea, costul și consumul mult mai mici decât al unei plăci Raspberry PI 3 este totuși o alegere foarte bună pentru implementarea unui router WiFi GSM. Pentru aceste lucru avem nevoie de un modem USB GSM (în cadrul testelor s-a utilizat un modem Huawei E3131 dar se poate utiliza orice modem USB GSM, de exemplu). Conectarea modemului la placa de dezvoltare necesită un adaptor microUSB – USB. Bineînțeles, pentru funcționarea sistemului sunt necesare un card microSD pentru sistemul de operare și un alimentator de 5V, 1A.

Punerea în funcțiune a unei plăci Raspberry PI Zero este o provocare din cauza numărului mic de porturi USB. Recomandăm utilizarea unui cablu serial de debug pentru a interacționa mai ușor cu placa de dezvoltare (a se vedea și materialul „Raspberry Pi Zero Headless Quick Start”). Ca sistem de operare vom utiliza Raspbian Lite pentru a nu încărca procesorul plăcii de dezvoltare cu servicii și pachete software inutile (testele au fost realizate utilizând versiunea 2018-03-13-raspbian-stretch-lite).

Chiar dacă în final conexiunea la Internet a sistemului se va face prin intermediul conexiunii modemului USB GSM, pentru a instala pachetele necesare este nevoie să activăm temporar conexiunea WiFi a plăcii de dezvoltare pentru acces la Internet. Astfel în fișierul /etc/wpa_supplicant/wpa_supplicant.conf vom adăuga liniile cu datele de acces la rețeaua WiFi locală (aceste linii vor fi șterse după realizarea configurării de AP):

network={

 ssid=”…”

 psk=”…”

}

Configurarea WiFi se poate face și la nivel card de memorie înainte de prima pornire a sistemului – a se vedea materialul: „Manually setting up Pi WiFi using wpa_supplicant.conf”.

După repornirea sistemului vom instala update-urile sistemului de operare:

# sudo apt-get update

# sudo apt-get upgrade

și pachetele necesare necesare comunicației cu modemul GSM:

# sudo apt-get install ppp usb-modeswitch usb-modeswitch-data

După conectarea fizică a modemului și o nouă repornire a sistemului putem configura legătura de date GSM. În fișierul /etc/network/interfaces se vor adăuga următoarele linii:

auto gprs

iface gprs inet ppp

provider gprs

Ulterior vom crea fișierul gprs în directorul /etc/ppp/peers cu următorul conținut (cartela SIM utilizată nu avea activat codul PIN):

connect “/usr/sbin/chat -v -f /etc/chatscripts/gprs -T em”

/dev/ttyUSB0

noipdefault

defaultroute

replacedefaultroute

hide-password

noauth

persist

usepeerdns

După o nouă restartare conexiunea de date GSM va deveni funcțională și putem șterge configurația din fișierul /etc/wpa_supplicant/wpa_supplicant.conf și putem trece la configurația AP. Vom instala pachetele software necesare managementului clienților WiFi:

# sudo apt-get update

# sudo apt-get install dnsmasq hostapd

și vom opri pentru moment serviciile până după configurarea corectă a acestora:

# sudo systemctl stop dnsmasq

# sudo systemctl stop hostapd

Interfața de rețea WiFi va avea în configurația de AP adresă IP statică deci vom configura acest lucru în serviciul DHCP (fișierul /etc/dhcpcd.conf):

interface wlan0

    static ip_address=192.168.66.1/24

și vom reporni serviciul:

# sudo service dhcpcd restart

Având în vedere că funcționalitatea de AP necesită oferirea clienților WiFi de configurații dinamice de rețea este necesară configurarea serverului DHCP (dnsmasq). Vom crea un nou fișier de configurare:

# sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig 

# sudo nano /etc/dnsmasq.conf

în care vom indica plaja de adrese IP oferite clienților WiFi:

interface=wlan0   

  dhcp-range=192.168.66.2,192.168.66.20,255.255.255.0,24h

În fișierul serviciului de management AP (/etc/hostapd/hostapd.conf) vom introduce următoarea configurație (personalizând, bineînțeles, datele de conectare la AP):

interface=wlan0

driver=nl80211

ssid=…

hw_mode=g

channel=7

wmm_enabled=0

macaddr_acl=0

auth_algs=1

ignore_broadcast_ssid=0

wpa=2

wpa_passphrase=…

wpa_key_mgmt=WPA-PSK

wpa_pairwise=TKIP

rsn_pairwise=CCMP

și vom referi fișierul în fișierul de configurare principal al serviciului hostapd (/etc/default/hostapd):

DAEMON_CONF=”/etc/hostapd/hostapd.conf”

După aceste configurări putem porni cele două servicii:

# sudo systemctl start hostapd

# sudo systemctl start dnsmasq

Pentru ca sistemul să retransmită pachetele din rețeaua WiFi în rețeua Internet este necesar să achivăm rutarea pachetelor TCP/IP – în fișierul /etc/sysctl.conf vom decomenta următoarea linie:

net.ipv4.ip_forward=1

Ultimul pas este configurarea serviciului de filtrare a pachetelor (iptables). Vom adăuga și salva o regulă de MASQUERADE:

sudo iptables -t nat -A  POSTROUTING -o ppp0 -j MASQUERADE

sudo sh -c “iptables-save > /etc/iptables.ipv4.nat”

și o vom executa la fiecare repornire a sistemului prin adăugarea următoarei linii în fișierul /etc/rc.local înainte de linia exit 0:

iptables-restore < /etc/iptables.ipv4.nat

După o ultimă repornire routerul WiFi GSM este funcțional.

Router WiFi GSM utilizând LinkIt Smart 7688 Duo

Chiar dacă implementarea funcționalității de router WiFi GSM utilizând familia de plăci LinkIt Smart 7688 nu este nouă în cadrul lecțiilor noastre, o să încercăm în materialul de față să propunem o versiune îmbunătățită a acestui tip de sistem. Placa de dezvoltare LinkIt Smart 7688 Duo, spre deosebire de placa LinkIt Smart 7688, deține un microcontroler ATmega32U4 ce poate fi utilizat în cadrul sistemului pentru diverse sarcini de timp real (comandă de motoare, interfață utilizator, achiziție de valori de la diverși senzori etc.). În cadrul sistemului nostru vom utiliza microcontrolerul prezent pe placa de dezvoltare pentru implementarea interfeței utilizator, mai exact vom adăuga sistemului un ecran ce va afișa în timp real date despre funcționarea routerului (număr de clienți WiFi, puterea semnalului GSM, traficul prin intermediul routerului).

Pentru configurarea de bază a routerului se vor efectua exact aceeași pași ca și în cazul plăcii LinkIt Smart 7688 (a se vedea și „Router WiFi GSM utilizând LinkIt Smart 7688”), mai exact (pe scurt):

  • Vom configura placa în mod client WiFi pentru a putea instala pachetele necesare funcționării modemului GSM;
  • Vom instala și configura modemul GSM prin definirea unei noi interfețe de rețea;
  • Noua interfață de rețea va fi introdusă în firewall în zoua wan și vom configura pornirea automată a interfeței la pornirea sistemului de operare;
  • Vom reconfigura placa în modul AP setând numele și parola de acces dorită.

Pentru afișare vom utiliza un ecran OLED monocrom ce va comunica cu placa de dezvoltare prin I2C:

  • Alimentarea se va face la 3.3V (3.3V conectat la 3.3V, GND la GND);
  • Pinul Data al afișajului la pinul D2 (SDA) al plăcii de dezvoltare;
  • Pinul Clk al afișajului la pinul D3 (SCL) al plăcii de dezvoltare;
  • Pinul Rst al afișajului la pinul D5 al plăcii de dezvoltare (opțional).

2

Programul (pentru microcontrolerul ATmega32U4) va utiliza bibliotecile Adafruit GFX și Adafruit SSD1306 pentru partea de comunicație cu ecranul OLED și biblioteca Process (Bridge) pentru a comunica cu sistemul de operare OpenWRT.

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define OLED_RESET 5

Adafruit_SSD1306 display(OLED_RESET);

#include <Process.h>

Secțiunea setup() va inițializa ecranul OLED și comunicația cu sistemul de operare OpenWRT. Ecranul va afișa mesajul Initializing… pâna la încărcarea și inițializarea sistemului de operare (funcția Bridge.begin() va bloca programul până la stabilirea comunicației cu sistemul de operare).

3

void setup() {

  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);

  display.display();

  delay(2000);

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(WHITE);

  display.setCursor(0,0);

  display.println(“Initializing…”);

  display.display();

  delay(1);

  Bridge.begin();

  delay(1000);

}

Secțiunea loop() este responsabilă cu interogarea sistemului de operare și afișarea răspunsurilor pe ecranul OLED. Pe prima linie este afișată ora și data (utile pentru a verifica dacă sistemul funcționează corect, nu s-a blocat), a doua linie va afișa calitatea semnalului GSM (utilă pentru poziționarea unei antene externe), a treia linie va afișa numărul de clienți WiFi iar ultima linie cantitatea de informație (recepționată și transmisă) transferată prin intermediul conexiunii GSM (informații utile în cazul unui abonament de date cu limitări la datele transferate). Datele sunt împrospătate o dată la 30 de secunde.

4

void loop() {

  Process MyProc;

  display.clearDisplay();

  display.setTextSize(1);

  display.setTextColor(WHITE);

  display.setCursor(0,0);

  MyProc.runShellCommand(“date +%H:%M”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

  if (c!=’\n’) display.print((char)c);

  }

  display.print(” “);

  MyProc.runShellCommand(“date +%D”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  display.print(“RSSI:”);

  MyProc.runShellCommand(“/root/get_rssi”);

  while (MyProc.available() > 0) {

      char c = MyProc.read();

      if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  display.print(“Clients:”);

  MyProc.runShellCommand(“/root/clients”);

  while (MyProc.available() > 0) {

      char c = MyProc.read();

      if (c!=’\n’) display.print((char)c);

  }

  display.println();

  display.println();

  MyProc.runShellCommand(“ifconfig 3g-gsm | grep ‘RX bytes’ | awk ‘{ print $1 $3 $4 }'”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.println();

  MyProc.runShellCommand(“ifconfig 3g-gsm | grep ‘RX bytes’ | awk ‘{ print $5 $7 $8}'”);

  while (MyProc.available() > 0) {

    char c = MyProc.read();

    if (c!=’\n’) display.print((char)c);

  }

  display.display();

  delay(30000);

}

Este posibil ca legătura dintre microcontrolerul ATmega32U4 și sistemul de operare OpenWRT să fie oprită implicit (să fie oprit serviciul responsabil la nivel de sistem de operare). În acest caz este necesară rularea următoarelor comenzi în linia de comenzi a sistemului de operare:

# uci set yunbridge.config.disabled=’0’

# uci commit

# reboot

Pentru rularea scripturilor de interogare a puterii semnalului și a numărului de clienți este necesară instalarea pachetului bash sub sistemul de operare OpenWRT:

# opkg update

# opkh install bash

Scriptul de interogare a puterii semnalului se va salva în diretorul /root sub denumirea get_rssi (tebuie acordate permisiuni de execuție #chmod +x get_rssi). Scriptul va interpreta o valoare pentru calitatea semnalului mai mare de 25 ca fiind excelentă, între 19 și 25 bună, între 13 și 19 medie, între 7 și 13 slabă și sub 7 foarte slabă. Lipsa semnalului poate însemna atât aflarea într-o zonă fără semnal dar și o problemă cu modemul GSM (deconectat?) sau cu SIM-ul GSM (neintrodus, fără credit?).

#!/bin/bash

rssi=`printf “%s\n” $((/usr/sbin/chat -V -s ” ‘AT+CSQ’ ‘OK’ ” > /dev/ttyUSB2 < /dev/ttyUSB2) 2>&1 | /bin/grep CSQ: | /usr/bin/awk ‘{print $2}’)`

rssi=”${rssi//,/.}”

rssi=$(printf “%.0f” $rssi)

if [ $rssi -gt 25 ]; then

        echo “$rssi Excellent”

elif [ $rssi -gt 19 ] && [ $rssi -le 25 ]; then

        echo “$rssi Good”

elif [ $rssi -gt 13 ] && [ $rssi -le 19 ]; then

        echo “$rssi Average”

elif [ $rssi -gt 7 ] && [ $rssi -le 13 ]; then

        echo “$rssi Low”

elif [ $rssi -gt 0 ] && [ $rssi -le 7 ]; then

        echo “$rssi Very low”

else

        echo “No signal”

fi

Scriptul de interogare a numărului de clienți WiFi se va salva în diretorul /root sub denumirea clients (tebuie acordate permisiuni de execuție #chmod +x clients). Scriptul va verifica numărul de înregistrări ARP din rețeaua WiFi. Atenție!!! Conectarea unui nou client WiFi va conduce la incrementarea imediată a numărului de clienți dar deconectarea nu va conduce la o decrementare decât în momentul în care expiră cache-ul ARP.

nr=0

for ip in $(cat /proc/net/arp | grep -v IP | awk ‘{print

$1}’); do

    nr=$((nr+1))

done

echo $nr

 

Dacă doriți să explorați și alte variante de implementare puteți vedea și „Smart Router With WiFi Connection Visualization”.

Router WiFi GSM utilizând LinkIt Smart 7688

Asigurarea conexiunii la Internet în cazul absenței unei conexiuni terestre (prin cablu sau fibră optică) se poate face, bineînțeles, apelând la serviciile oferite de companiile de telefonie mobilă prin intermediul unei cartele SIM ce oferă transfer de pachete de date. Există multe opțiuni comerciale pentru implementarea acestei facilități de routare între o rețea de date WiFi și o rețea GSM: routere WiFi GSM, telefoane mobile ce funcționează ca AP (tethering) ș.a.m.d. dar majoritatea acestor soluții nu oferă o flexibilitate sau un control al conexiunilor foarte bune. Din acest motiv realizarea unui router „personalizat” se poate dovedi și o soluție mult mai ieftină și o metodă de a implementa mecanisme de filtrare, autentificare, control al conexiunilor mult mai sofisticate.

Pentru implementare vom utiliza o placă de dezvoltare LinkIt Smart 7688 bazată pe circuitul SoC MediaTek MT7688AN și care rulează distribuția Linux OpenWRT. Această placă de dezvoltare oferă, la un preț redus, toate facilitățile de routare, filtrare și control al traficului TCP/IP oferite de sistemele de operare Linux. Pentru mai multe detalii legate de funcționarea și utilizarea plăcii de dezvoltare LinkIt Smart 7688 puteți consulta wiki-ul oficial. Pentru conexiunea de date GSM vom utiliza un modem USB GSM – testele au fost realizate utilizând un modem Huawei E220 dar se poate utiliza orice alt modem USB GSM compatibil. Conectarea modemului USB la placa de dezvoltare necesită un adaptor microUSB – USB. Alimentarea sistemului se va face la 5V, minim 500mA – preferabil 1A (orice încărcător de mobil de 1A și mufă microUSB e bun).

2

La punere în funcțiune a plăcii de dezvoltare aceasta funcționează în mod AP. Ne vom conecta la AP-ul LinkIt_Smart_7688_XXXXXX și apoi la interfața de administrare web (IP 192.168.100.1).

3

La prima conectare se va stabili parola utilizatorului root (contul de administrare a sistemului de operare).

4

Pentru a putea instala pachetele software necesare funcționării modemului USB GSM vom configura placa de dezvoltare ca și client WiFi – Station Mode (pentru a avea conexiune Internet).

ATENȚIE!!! Placa de dezvoltare are definită implicit o interfață de rețea cu IP-ul 192.168.100.1 . Orice încercare de a introduce placa de dezvoltare într-o rețea ce oferă prin DHCP adrese IP în clasa 192.168.100.0/24 va eșua.

După configurarea și repornirea plăcii ne putem conecta la aceasta prin SSH (utilizând PUTTY de exemplu). IP-ul de conectare depinde de rețeaua locală. Vom rula următoarele comenzi pentru instalarea pachetelor software necesare configurării conexiunii de date GSM:

# opkg update

# opkg install comgt kmod-usb-serial kmod-usb-serial-option kmod-usb-serial-wwan usb-modeswitch

Eventual putem instala și un editor de text suplimentar dacă nu ne place vi :

# opkg install nano

Având conectat modemul USB GSM vom reporni placa de dezvoltare. Ne vom reconecta prin SSH și vom verifica dacă modemul este recunoscut de sistemul de operare în mod corect (vom rula comanda dmesg).

6

În cazul în care modemul este recunoscut corect de sistemul de operare vom regăsi în jurnalul de pornire a sistemului de operare (consultat anterior cu ajutorul comenzii dmesg) linii care indică instalarea modemului GSM ca dispozitiv specific USB (ttyUSB0 de exemplu). În cazul în care modemul este văzut ca alt tip de dispozitiv (de stocare în masă – memorie usb de exemplu) înseamnă că pachetul usb-modeswitch care se ocupă de autoconfigurarea modemului nu are în baza de date proprie modelul de modem utilizat. Este recomandat să căutăm un modem care să fie deja în baza de date a pachetului software. Configurarea manuală a modemului este destul de dificilă. Pentru mai multe informații se poate parcurge materialul „Use 3g/UMTS USB Dongle for WAN connection”.

Pentru a putea accesa Internetul prin intermediul modemului USB GSM este nevoie să avem o cartelă SIM funcțională (se poate testa prealabil modemul pe un sistem de calcul obișnuit) și să realizăm următoarele configurări în fișierele sistemului de operare. În fișierul /etc/config/network vom adăuga la final (pinul și APN-ul sunt specifice cartelei SIM utilizate):

config interface ‘gsm’

        option proto ‘3g’

        option service ‘umts’

        option device ‘/dev/ttyUSB0’

        option apn ‘net’

        option pincode ‘0000’

În fișierul /etc/config/firewall vom adăuga noua interfață de rețea în categoria wan :

config zone

        option name ‘wan’

        list network ‘gsm’

        …

Pentru ca intefața GSM să fie pornită automat după repornirea sistemului vom adăuga în fișierul /etc/rc.local linia ifup gsm (comanda de pornire a conexiunii GSM) înainte de linia exit 0 .

ifup gsm

exit 0

După finalizarea configurării conexiunii GSM (se poate reporni sistemul și verifica prin intermediul comenzii route dacă există conexiune Internet GSM) se va trece sistemul în configurație AP din interfața web de administrare (se va stabili numele și parola de acces pentru rețeaua WiFi).

7

După o ultimă repornire a sistemului routerul WiFi GSM este gata de utilizare. Acesta va oferi adrese în clasa 192.168.100.0/24 și vom putea accesa interfața de administrare prin intermediul adresei IP 192.168.100.1 . Pentru configurări avansate (firewall, port-forwarding) se poate accesa consola Luci specifică sistemului de operare OpenWRT (link în interfața de administrare, încercuit cu roșu în imaginea precedentă).

În cazul în care se efectuează modificări ale sistemului de operare care conduc la stări nefericite din care nu știm cum să ieșim, există întotdeauna posibilitatea de a reseta placa la setările inițiale și de a relua procesul de configurare de la început. Pentru resetarea plăcii la setările inițiale se va ține apăsat minim 20 de secunde butonul WiFi Reset.

9

O posibilă îmbunătățire a sistemului nostru este adăugarea unei antene WiFi externe pentru creșterea puterii semnalului. Placa are un conector special I-PEX pentru acest lucru dar utilizarea acestuia necesită dezlipirea de pe placă a unei rezistențe (imagine de mai jos).

10

Control WiFi pentru luminițele de Crăciun

Farmecul sărbătorilor de iarnă este dat, printre altele, de instalațiile de lumini. În sute de variante, în zeci de culori, aflate undeva între plăcerea de a decora și obsesie, jucării sau elemente de iluminat, instalațiile de luminițe sunt cu siguranță un element important în cadrul pregătirilor pentru sărbătoarea de Crăciun. Dacă ați experimentat suficiente instalații și simțiți că vreți să treceți la un nivel următor (adică să începeți să le personalizați), în cadrul proiectului de față vă propunem modificarea unei instalații existente prin adăugarea unei comenzi de pornire prin WiFi.

Comanda de pornire se poate realiza simplu prin intermediul unui element de tip releu. Pentru a realiza comanda de la distanță prin intermediul WiFi este necesar să conectăm elementul de tip releu la o placă de dezvoltare ce permite comunicație WiFi. Realizarea unui ansamblu compact, placă de dezvoltare WiFi plus releu de comandă, este însă o sarcină destul de anostă. Din acest motiv vă propunem utilizarea unei platforme integrate: ESP8266-EVB-BAT-BOX.

2

Această platformă este echipată cu un microprocesor WiFi ESP8266 și un releu 220VAC/10A. Platforma se poate alimenta de la alimentator de rețea de 5V sau de la un acumulator LiPo de 3.7V. Platforma se comercializează împreună cu o carcasă de protecție HAMMOND și conține un conector WAGO cu șurub de tip mufă (din două părți) pentru integrarea facilă a releului într-un montaj. Datorită facilităților oferite de această platformă este ideală pentru o aplicație de comandă de tip WiFi.

3

ATENȚIE!!! Chiar dacă releul de pe platforma ESP8266-EVB-BAT-BOX suportă comanda unor circuite conectate la tensiune de rețea (220V), NU este recomandată realizarea de montaje proprii la această tensiune fără supravegherea sau îndrumarea unui specialist. Pericol de electrocutare, moarte, scurtcircuit, incendiu!!! Pentru montaje personale de tip hobby se recomandă comanda unor circuite de luminițe alimentate de la baterii sau cu alimentator de rețea (tensiunea din firele conectate la releu să fie de 3V-12V) eliminând astfel riscul de accidentare.

Conectarea instalației se va face prin secționarea firului de curent (nu cel de masă) și intercalarea releului. Astfel, platforma ESP8266-EVB-BAT-BOX va putea controla alimentarea instalației și vom putea programa când aceasta să se aprindă. Sistemul propus va putea să aprindă instalația la o anumită oră sau în urma unei comenzi directe.

4

Programarea platformei necesită un programator FTDI de 3.3V. Pentru mai multe detalii despre programarea platformei EVB-BAT-BOX este necesară consultarea materialului „HOW TO USE ESP8266 WITH ARDUINO IDE”. Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 având instalată extensia ESP8266 Community 2.3.0.

#include <ESP8266WiFi.h>

#include <ESP8266mDNS.h>

#include <WiFiUdp.h>

#include <ESP8266WebServer.h>

#include <TimeLib.h>

const int timeZone = 2;

WiFiUDP Udp;

const int NTP_PACKET_SIZE = 48;

byte packetBuffer[NTP_PACKET_SIZE];

unsigned int localPort = 2390;   

WiFiServer server(80);

În cadrul programului trebuie personalizate datele de conectare la rețeaua WiFi (variabilele ssid și pass).

char ssid[] = “…”;

char pass[] = “…”;

WiFiClient client;

#define HOSTNAME “ESP8266-“

#define RELAY_PIN 5

int start_hour = 20;

int stop_hour = 23;

boolean automatic = true;

În cadrul secțiunii setup() se va inițializa conexiunea WiFi și se va raporta în consola serială adresa IP a sistemului. Aceasta trebuie folosită pentru a accesa sistemul dintr-un client web (browser) din aceiași rețea locală. Programul va utiliza biblioteca Time și conexiunea de rețea pentru a menține ora exactă (prin sincronizare NTP).

void setup() {

  Serial.begin(115200);

  Serial.println();

  Serial.println();

  pinMode(RELAY_PIN, OUTPUT);

  digitalWrite(RELAY_PIN,LOW);

  String hostname(HOSTNAME);

  hostname += String(ESP.getChipId(), HEX);

  Serial.println(“Hostname:” + hostname);

  WiFi.mode(WIFI_STA);

  WiFi.hostname(hostname);

  WiFi.begin(ssid, pass);

  delay(5000);

  if (WiFi.status() != WL_CONNECTED) {

    delay(10000);

    ESP.restart();

  }

  Serial.print(“IP:”);

  Serial.println(WiFi.localIP());

  server.begin();

  Udp.begin(localPort);

  setSyncProvider(getNtpTime);

}

Secțiunea loop() implementează comunicația HTTP ce ne va permite acționarea releului de la distanță. Interfața de comandă (ce poate fi accesată la adresa IP a sistemului) prezintă ora curentă, modul de funcționare (automat sau manual), ora de pornire și oprire automată precum și comenzile manuale de pornire / oprire. La pornire sistemul este în mod automat și are setate ca oră de pornire ora 20:00 și ca oră de oprire ora 23:00. Prin acționarea semnelor +/- din dreptul celor două ore presetate acestea pot fi modificate.

5

Prin acționarea comenzilor manuale de oprire sau pornire se va comuta în modul manual de comandă în care intervalul de funcționare automată este ignorat și sistemul răspunde doar la comenzile manuale de pornire și oprire. Reactivarea modului de funcționare automat se poate face apelând orice modificare (+/-) a orelor de pornire / oprire automată.

6

void loop() {

  if (automatic)

    if ((hour()>start_hour) && (hour()<stop_hour))

digitalWrite(RELAY_PIN, HIGH);

    else digitalWrite(RELAY_PIN, LOW);

  WiFiClient client = server.available();

  if (!client) return;  

  Serial.println(“new client”);

  while(!client.available()){ delay(1); }

  String request = client.readStringUntil(‘\r’);

  Serial.println(request);

  client.flush();

  if (request.indexOf(“/COMMAND=ON”) != -1) {

    digitalWrite(RELAY_PIN, HIGH); 

    automatic = false;

  }

  else if (request.indexOf(“/COMMAND=OFF”) != -1) {

    digitalWrite(RELAY_PIN, LOW); 

    automatic = false;

  }

  else if (request.indexOf(“/COMMAND=PLUS_START”) != -1) {

    start_hour++;

    if (start_hour>23) start_hour=0;

    automatic = true;

  }

  else if (request.indexOf(“/COMMAND=MIN_START”) != -1) {

    start_hour–;

    if (start_hour<0) start_hour=23;

    automatic = true;

  }

  else if (request.indexOf(“/COMMAND=PLUS_STOP”) != -1) {

    stop_hour++;

    if (stop_hour>23) stop_hour=23;

    automatic = true;

  }

  else if (request.indexOf(“/COMMAND=MIN_STOP”) != -1) {

    stop_hour–;

    if (stop_hour<0) stop_hour=23;

    automatic = true;

  }

  client.println(“HTTP/1.1 200 OK”);

  client.println(“Content-Type: text/html”);

  client.println(“”);

  client.println(“<!DOCTYPE HTML>”);

  client.println(“<html>”);

  client.println(“<h1>WiFi Christmas Lights</h1>”);

  client.println(“<br>”);

  client.print(“Time now: “);

  client.print(hour());

  client.print(“:”);

  client.print(minute());

  client.print(“:”);

  client.println(second());

  client.println(“<br>”);

  if (automatic) client.print(“Mode: Automatic”);

  else client.print(“Mode: Manual”);

  client.println(“<br>”);

  client.println(“Click <a href=\”/COMMAND=ON\”>here</a> to turn ON the Christmas Lights<br>”);

  client.println(“Click <a href=\”/COMMAND=OFF\”>here</a> to turn OFF the Christmas Lights<br>”);

  client.print(“Autostart at <a href=\”/COMMAND=PLUS_START\”>(+)</a>”);

  client.print(start_hour);

  client.println(“<a href=\”/COMMAND=MIN_START\”>(-)</a> hour.”);

  client.println(“<br>”);

  client.print(“Autostop at <a href=\”/COMMAND=PLUS_STOP\”>(+)</a>”);

  client.print(stop_hour);

  client.println(“<a href=\”/COMMAND=MIN_STOP\”>(-)</a> hour.”);

  client.println(“</html>”);

  delay(1);

  Serial.println(“Client disonnected”);

  Serial.println(“”);

}

Funcțiile getNtpTime() și sendNTPpacket() sunt apelate periodic automat de biblioteca Time pentru sincronizarea timpului.

IPAddress timeServerIP;

const char* ntpServerName = “time.nist.gov”;

time_t lastsyncr;

time_t getNtpTime() {

  WiFi.hostByName(ntpServerName, timeServerIP);

  while (Udp.parsePacket() > 0) ;

  sendNTPpacket(timeServerIP);

  uint32_t beginWait = millis();

  while (millis() – beginWait < 2500) {

    int size = Udp.parsePacket();

    if (size >= NTP_PACKET_SIZE) {

      Udp.read(packetBuffer, NTP_PACKET_SIZE); 

      unsigned long secsSince1900;

      secsSince1900 =  (unsigned long)packetBuffer[40] << 24;

     secsSince1900 |= (unsigned long)packetBuffer[41] << 16;

      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;

      secsSince1900 |= (unsigned long)packetBuffer[43];

      lastsyncr = (time_t) (secsSince1900 – 2208988800UL + timeZone * SECS_PER_HOUR);

      return lastsyncr;

    }

  }

 return 0;

}

void sendNTPpacket(IPAddress &address) {

  memset(packetBuffer, 0, NTP_PACKET_SIZE);

  packetBuffer[0] = 0b11100011;  

  packetBuffer[1] = 0;

  packetBuffer[2] = 6;

  packetBuffer[3] = 0xEC; 

  packetBuffer[12]  = 49;

  packetBuffer[13]  = 0x4E;

  packetBuffer[14]  = 49;

  packetBuffer[15]  = 52;

  Udp.beginPacket(address, 123);

  Udp.write(packetBuffer, NTP_PACKET_SIZE);

  Udp.endPacket();

}

Pentru alte variante de realizare puteți consulta și proiectele:

Calendar de Crăciun

Calendarul de Crăciun sau Calendarul de Advent este o modalitate de a face să treacă timpul mai ușor în așteptarea sărbătorii de Crăciun. Acest calendar indică câte zile au trecut și câte zile mai sunt (în luna decembrie bineînțeles) până în dimineața zilei de Crăciun. Pentru copii există variante care oferă zilnic mici surprize (bomboane sau ciocolată) pentru a atenua nerăbdarea așteptării cadourilor de Crăciun dar, în cadrul proiectului de față, propunem construirea unui calendar de Crăciun bazat pe 24 de LED-uri: un calendar de Crăciun cu luminițe.

Pentru a comanda mai ușor cele 24 de LED-uri vom utiliza LED-uri RGB adresabile WS2812. Acestea nu necesită comandă individuală, este suficientă o singură linie de comandă între cele 24 de LED-uri și placa de dezvoltare. Se pot utiliza LED-uri NeoPixel  sau module WS2812 breakout. Pentru mai multe detalii legate de funcționarea LED-urilor WS2812 se recomandă parcurgerea materialului: „Adafruit NeoPixel Überguide”.

2

Pentru comandă vom utiliza placa de dezvoltare WiDo echipată cu un microcontroler ATmega32U4 (prezent și pe placa Arduino Leonardo) și un controler WiFi CC3000. Această combinație este perfectă pentru implementarea sistemului nostru: microcontrolerul ATmega32U4 va asigura comanda LED-urilor la o tensiune de 5V iar controlerul WiFi va fi utilizat pentru a putea ști în ce zi calendaristică ne aflăm (sincronizare de timp de tip NTP).

3

Conexiunile dintre placa de dezvoltare și LED-uri sunt prezentate în schema următoare. Sistemul necesită o alimentare de 5V minim 2A (pentru placa de dezvoltare și cele 24 de LED-uri). Pinul de comandă este pinul D6. Comanda se va transmite serial de la un LED la următorul. LED-urile pot fi aranjate pe un carton pictat cu un brad de crăciun sau orice alt suport doriți (o căsuță de poveste sau o ilustrată de Crăciun).

4

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.8.3 și bibliotecile Adafruit Neopixel 1.1.3 și o versiune modificată a bibliotecii Adafruit CC3000. Placa se va programa în Arduino IDE ca o placă Arduino Leonardo obișnuită.

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__

  #include <avr/power.h>

#endif

#define PIN 6

#define NUMPIXELS 24

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS,PIN, NEO_GRB + NEO_KHZ800);

#include <Adafruit_CC3000.h>

#include <ccspi.h>

#include <SPI.h>

#define WiDo_IRQ   7

#define WiDo_VBAT  5

#define WiDo_CS    10

Adafruit_CC3000 WiDo = Adafruit_CC3000(WiDo_CS, WiDo_IRQ,  WiDo_VBAT,SPI_CLOCK_DIVIDER);

În cadrul programului trebuie personalizate datele de conectare la rețeaua WiFi (WLAN_SSID și WLAN_PASS).

#define WLAN_SSID       “…”          

#define WLAN_PASS       “…”

#define WLAN_SECURITY   WLAN_SEC_WPA2

Adafruit_CC3000_Client client;

#include <TimeLib.h>

Pentru sistemul final, directiva debug se poate comenta pentru a suprima mesajele din consola serială.

#define debug

void setup() {

  #ifdef debug

    SerialUSB.begin(115200);

    while(!SerialUSB) { ; }

    SerialUSB.println(F(“Calendar de Craciun\n”));

    SerialUSB.println(F(“\nInitialising the CC3000 …”));

  #endif

  if (!WiDo.begin())  {

    #ifdef debug

      SerialUSB.println(F(“Unable to initialise the

CC3000! Check your wiring?”));

    #endif

    while(1);   }

 if (!WiDo.connectToAP(WLAN_SSID,WLAN_PASS,WLAN_SECURITY)) {

    #ifdef debug

      SerialUSB.println(F(“Failed to connect to AP!”));

    #endif

    while(1);   }

  #ifdef debug

    SerialUSB.println(F(“Connected to AP!”));

    SerialUSB.println(F(“Request DHCP”));

  #endif

  while (!WiDo.checkDHCP())  {    delay(100);  } 

  while (! displayConnectionDetails()) {

      delay(1000);

    }

  setSyncProvider(getTime);

  pinMode(6,OUTPUT);

  pixels.begin();

  randomSeed(analogRead(0));

  startprogram();

}

bool displayConnectionDetails(void)

{

  uint32_t ipAddress, netmask, gateway, dhcpserv, dnsserv;

  if(!WiDo.getIPAddress(&ipAddress, &netmask, &gateway, &dhcpserv, &dnsserv))  {

    #ifdef debug

      SerialUSB.println(F(“Unable to retrieve the IP Address!\r\n”));

    #endif

    return false;

  }

  else

  {

    #ifdef debug

      SerialUSB.print(F(“\nIP Addr: “));

     WiDo.printIPdotsRev(ipAddress);

      SerialUSB.print(F(“\nNetmask: “));

      WiDo.printIPdotsRev(netmask);

      SerialUSB.print(F(“\nGateway: “));

      WiDo.printIPdotsRev(gateway);

      SerialUSB.print(F(“\nDHCPsrv: “));

      WiDo.printIPdotsRev(dhcpserv);

      SerialUSB.print(F(“\nDNSserv: “));

      WiDo.printIPdotsRev(dnsserv);

      SerialUSB.println();

    #endif

    return true;

  }

}

Procedura startprogram(), apelată o singură dată în secțiunea setup(), aprinde toate LED-urile de trei ori în trei culori diferite: roșu, verde, albastru. Este o procedură de verificare a montajului ce se execută la fiecare pornire a sistemului.

void startprogram() {

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(255,0,0));

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(0,0,0));

  }

  pixels.show();

  delay(100);

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(0,255,0));

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(0,0,0));

  }

  pixels.show();

  delay(100);

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(0,0,255));

    pixels.show();

    delay(100);

  }

  for (int i=0; i<NUMPIXELS; i++) {

    pixels.setPixelColor(i, pixels.Color(0,0,0));

  }

  pixels.show();

  delay(100);

}

Secțiunea loop() va aștepta realizarea sincronizării de timp după care va verifica o dată la 10 minute data calendaristică. Între 1 decembrie și 24 decembrie va aprinde un număr de LED-uri egal cu data calendaristică. Culoarea va fi de fiecare dată generată aleatoriu. În data de 25 decembrie programul va executa un joc de lumini pe toată perioada zilei (va aprinde toate cele 24 de LED-uri treptat în culori aleatorii). În restul anului LED-urile vor rămâne stinse.

void loop() {

   #ifdef debug

    if(timeStatus()==timeNotSet) SerialUSB.println(“Time Not Set”);

    if(timeStatus()==timeNeedsSync) SerialUSB.println(“Time Needs Sync”);

   #endif

   while(timeStatus()==timeNotSet) delay(1000);

   for (int i=0; i<NUMPIXELS; i++) {

      pixels.setPixelColor(i, pixels.Color(0,0,0));

    }

   pixels.show();

   delay(100);

   if(month()==12) {

    if (day()<25) {

      #ifdef debug

        SerialUSB.print(“Days to Christmas: “); SerialUSB.println(25-day());

      #endif

      for (int i=0; i<NUMPIXELS; i++) {

        pixels.setPixelColor(i, pixels.Color(0,0,0));

      }

      pixels.show();

      delay(100);

      for (int i=0; i<day(); i++) {

        pixels.setPixelColor(i,pixels.Color(random(0,255),random(0,255),random(0,255)));

      }

      pixels.show();

    }

    if (day()==25) {

        for (int i=0; i<NUMPIXELS; i++) {

          pixels.setPixelColor(i,pixels.Color(random(0,255), random(0,255),random(0,255)));

         pixels.show();

         delay(1000);

        }

    }

   }

   delay(600000);

}

Funcția getTime() este folosită de biblioteca Time pentru sincronizarea de timp NTP.

const unsigned long

  connectTimeout  = 15L * 1000L,

  responseTimeout = 15L * 1000L;

unsigned long getTime(void) {

  uint8_t       buf[48];

  unsigned long ip, startTime, t = 0L;

  #ifdef debug

    SerialUSB.print(F(“Locating time server…”));

  #endif

  if(WiDo.getHostByName(“pool.ntp.org”, &ip)) {

    static const char PROGMEM

      timeReqA[] = { 227,  0,  6, 236 },

      timeReqB[] = {  49, 78, 49,  52 };

    #ifdef debug

      SerialUSB.println(F(“\r\nAttempting

                 connection…”));

    #endif

    startTime = millis();

    do {

      client = WiDo.connectUDP(ip, 123);

    } while((!client.connected()) &&

            ((millis() – startTime) < connectTimeout));

    if(client.connected()) {

      #ifdef debug

        SerialUSB.print(F(“connected!\r\nIssuing

                 request…”));

      #endif

      memset(buf, 0, sizeof(buf));

      memcpy_P( buf    , timeReqA, sizeof(timeReqA));

      memcpy_P(&buf[12], timeReqB, sizeof(timeReqB));

      client.write(buf, sizeof(buf));

      #ifdef debug

        SerialUSB.print(F(“\r\nAwaiting response…”));

      #endif

      memset(buf, 0, sizeof(buf));

      startTime = millis();

      while((!client.available()) &&

            ((millis() – startTime) < responseTimeout));

      if(client.available()) {

        client.read(buf, sizeof(buf));

        t = (((unsigned long)buf[40] << 24) |

             ((unsigned long)buf[41] << 16) |

             ((unsigned long)buf[42] <<  8) |

              (unsigned long)buf[43]) – 2208988800UL;

        #ifdef debug

          SerialUSB.print(F(“OK\r\n”));

        #endif

      }

      client.close();

    }

  }

  #ifdef debug

    if(!t) SerialUSB.println(F(“error”));

  #endif

  return t;

}

Pentru idei suplimentarea în realizarea artistică a aranjamentului se pot vedea și următoarele două proiecte:

Cum putem utiliza placa Raspberry Pi ca Access Point WiFi?

La momentul actual nu se poate concepe o rețea locală fără componentă de acces fără fir (WiFi). Prețul dispozitivelor Access Point (ce permit accesul WiFi într-o rețea locală) a scăzut destul de mult și există o diversitate foarte mare de astfel de dispozitive acoperind o funcționalitate variată. Totuși, posibilitatea de personalizare a acestor dispozitive se rezumă de cele mai multe ori la o interfață web destul de sărăcăcioasă cu funcții predefinite pentru o utilizare generică. În cazul în care dorim implementarea unor funcționalități specifice (pentru o rețea de dispozitive IoT de exemplu) ce implică filtrarea traficului, cifrarea traficului sau detectarea și prevenirea intruziunilor suntem obligați să achiziționăm dispozitive AP scumpe cu funcționalități avansate de router / firewall.

Placa Raspberry Pi 3 oferă posibilitatea implementării facile a funcționalității de Access Point WiFi datorită celor două interfețe de rețea integrate: interfață ethernet și interfață WiFi, permițând implementarea de funcții avansate (VPN, IDS/IDPS) și o personalizare completă a funcționării datorită sistemului de operare Linux. În plus, conectivitatea USB a plăcii permite conectarea de dispozitive de tip modem GSM oferind posibilitatea de conectare la Internet a rețelei locale prin intermediul rețelelor mobile de date (*),(*). Pentru implementarea funcționalității de AP WiFi nu este necesară distribuția Raspbian with Pixel (cu interfață grafică), se poate utiliza și Raspbian Lite deoarece toată configurare se va efectua în linie de comandă (în Terminal). Testarea configurației prezentate s-a făcut pe un sistem Raspberry Pi 3 rulând Raspbian 8 Jessie Lite cu kernel 4.9.28-v7+.

Configurarea interfeței de rețea WiFi

Ambele interfețe de rețea ale plăcii Raspberry Pi 3 (ethernet și WiFi) sunt configurate implicit să funcționeze în rețele locale ce oferă configurație dinamică (prin serviciul de DHCP). Primul pas în implementarea funcționalității de AP WiFi este configurarea adresei IP a interfeței WiFi – modificarea configurației din alocare dinamică în alocare statică – trebuie să stabilim adresa IP a interfeței și clasa de adrese IP pentru viitori clienți WiFi.

Primul lucru este dezactivarea serviciului de configurare dinamică. Se va edita fișierul /etc/dhcpcd.conf și se va adăuga la sfârșit următoarea linie:

denyinterfaces wlan0

După dezactivarea achiziției configurației dinamice trebuie să stabilim adresa IP statică a sistemului. Se va edita fișierul /etc/network/interfaces și pentru interfața wlan0 se va introduce următoarea configurație:

allow-hotplug wlan0

iface wlan0 inet static

address 192.168.99.1

netmasq 255.255.255.0

network 192.168.99.0

broadcast 192.168.99.255

unde 192.168.99.1 este adresa locală a sistemului AP și 192.168.99.0/24 este clasa de adrese a viitorilor clienți WiFi. Se poate alege orice altă clasă de adrese IP nerutabile atâta timp cât nu intră în conflict cu clasa de adrese a interfeței ethernet. Pentru ca modificările să-și facă efectul sistemul trebuie repornit. Atenție!!! Interfața ethernet trebuie să fie conectată al o rețea locală cu acces Internet, interfața WiFi a sistemului va avea rolul, de acum încolo, de AP WiFi, nu va mai putea asigura conectivitatea de rețea normală.

Instalarea și configurarea aplicației HostAPD

Aplicația HostAPD implementează partea de autentificare și control al conexiunilor WiFi. Pentru instalarea acestei aplicației vom rula comanda:

sudo apt-get install hostapd

După instalare vom crea fișierul /etc/hostapd/hostpad.conf cu următorul conținut:

interface=wlan0

ssid=Pi3-AP

hw_mode=g

channel=6

ieee80211n=1

wmm_enabled=1

ht_capab=[HT40][SHORT-GI-20][DSSS_CCK-40]

macaddr_acl=0

auth_algs=1

ignore_broadcast_ssid=0

wpa=2

wpa_key_mgmt=WPA-PSK

wpa_passphrase=raspberry

rsn_pairwise=CCMP

Denumirea AP-ului și parola de acces pot fi stabilite, bineînțeles, după bunul plac. Fișierul de configurare creat trebuie referit în fișierul de inițializare a aplicației hostapd: /etc/default/hostapd, prin inserarea următoarei linii:

DAEMON_CONF=”/etc/hostapd/hostapd.conf”

După repornirea sistemului vom putea să vedem AP-ul generat de placa Raspberry Pi dar acesta nu va funcționa încă corect.

Instalarea și configurarea aplicației DNSMASQ

Funcționalitatea de Access Point implică în mod obligatoriu două servicii de bază fără de care clienții nu pot accesa rețeaua Internet: serviciul de configurare dinamică a informațiilor IP (DHCP) și serviciul de rezolvare a adreselor IP (DNS). Aplicația DNSMASQ oferă ambele servicii pentru rețele de mici dimensiuni cum este o rețea locală formată de un AP. Instalarea aplicației se va face cu ajutorul comenzii:

sudo apt-get install dnsmasq

După instalarea aplicație vom înlocui fișierul de configurare (/etc/dnsmasq.conf)

sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig

sudo nano /etc/dnsmasq.conf

cu următorul conținut:

interface=wlan0

listen-address=192.168.99.1

bind-interfaces

server=8.8.8.8

domain-needed

bogus-priv

dhcp-range=192.168.99.2,192.168.99.100,12h

Bineînțeles, adresa interfeței WiFi a AP și plaja de adrese pentru clienții WiFi pot fi personalizate în funcție de alegerea clasei de adrese IP făcută anterior. Pentru ca aplicația DNSMASQ să devină funcțională utilizând configurația stabilită trebuie repornit sistemul.

Activarea rutării pachetelor și configurarea regulilor de rutare

Ultimul pas în configurarea sistemului AP este activarea rutării pachetelor între cele două interfețe de rețea a plăcii Raspberry Pi, adică pachetele provenite de la clienții WiFi să fie retrimise spre rețeaua plăcii ethernet (spre Internet). Acest lucru necesită editarea fișierului /etc/sysctl.conf și decomentarea liniei următoare:

net.ipv4.ip_forward=1

În plus de activarea rutării este necesar să definim reguli suplimentare deoarece clasa de adrese IP oferită clienților WiFi este privată. Aceste reguli vor fi impuse cu ajutorul utilitarului iptables specific sistemului de operare Linux. Vom utiliza următoarea succesiune de instrucțiuni pentru definirea regulilor:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

sudo iptables -A FORWARD -i eth0 -o wlan0 -m state –state

RELATED,ESTABLISHED -j ACCEPT

sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT

Vom salva apoi regulile într-un fișier:

sudo sh -c “iptables-save > /etc/iptables.ipv4.nat”

Pe care îl vom utiliza pentru reinițializare la fiecare repornire a sistemului. Pentru acest lucru vom adăuga în fișierul /etc/rc.local următoarea linie (chiar înainte de linia exit 0):

iptables-restore < /etc/iptables.ipv4.nat

După repornirea sistemului vom avea un sistem AP complet funcțional.

Posibile funcționalități suplimentare

Configurarea prezentată este cea mai rapidă modalitate de implementare a funcționalității de AP WiFi pe o placă Raspberry Pi 3, în nici un caz nu este singura soluție – puteți vedea mai multe informații consultând (*), (*), (*), (*), (*), (*).

În plus, sistemul AP poate căpăta funcționalități suplimentare specifice sistemelor router avansate, ca de exemplu:

 

  • Server VPN (Virtul Private Network) ce permite realizarea de canale de comunicație complet cifrate între două sisteme Internet sau între un sistem Internet și un server VPN ce deservește o rețea locală. Distribuția Raspbian 8 Jessy include pachetul openvpn) ce poate fi instalat cu ajutorul comenzii (se poate consulta și materialul (*)):

sudo apt-get install openvpn

2

  • Server IDS (Intrusion Detection System) – este un sistem ce permite analiza traficului de rețea în vederea detectării activității malițioase și protejarea calculatoarelor din rețeaua locală. Distribuția Raspbian 8 Jessy include pachetul snort ce poate fi instalat cu ajutorul comenzii (se poate consulta și materialul (*)):

sudo apt-get install snort

3

  • PPPoE gateway – mulți furnizori de Internet oferă serviciile de acces la Internet prin intermediul unei conexiuni de PPPoE, conexiune ce necesită de obicei un echipament specializat. Interfața ethernet a plăcii Raspberry Pi poate fi utilizată și în acest scop utilizând pachetul ppp. Se poate vedea și materialul (*).
  • Server proxy – serviciu ce permite accelerarea traficului web într-o rețea cu conexiune la Internet mai lentă. Distribuția Raspbian include pachetul squid ce implementează această funcționalitate. Se poate vedea și materialul (*). Suplimentar, combinând funcționalitatea oferită de pachetul squid cu funcționalitatea oferită de sistemul antivirus clamav se poate obține un sistem ce poate scana tot traficul web împotriva aplicațiilor malițioase și a programelor de tip virus. În acest sens se pot consulta materialele (*), (*).

Proiect Instalație de Crăciun WiFi

Instalațiile de lumini pentru crăciun sunt printre cele mai distractive montaje care se pot realiza cu ajutorul plăcii de dezvoltare Arduino Uno. În cadrul proiectului de față vom realiza o instalație de lumini pentru crăciun conectată prin WiFi și controlabilă prin intermediul telefonului mobil.

1

Pe lângă placa de dezvoltare Arduino Uno vom utiliza shield-ul Sparkfun WiFi CC3000 ce va permite conectarea la rețeaua Internet și recepționarea comenzilor transmise de pe telefonul mobil inteligent.

2

https://www.robofun.ro/wireless/wireless-wifi/cc3000-wifi-shield

Pentru informații legate de utilizarea shield-ului Sparkfun WiFi CC3000 puteți consulta și următorul tutorial:

CC3000 Hookup Guide

https://learn.sparkfun.com/tutorials/cc3000-hookup-guide

Pentru partea de lumini vom utiliza un șir de leduri RGB de 12mm de la Adafruit (se pot utiliza mai multe seturi înseriate atâta timp cât se respectă puterea sursei de alimentare):

3

https://www.robofun.ro/electronice/led/led-uri-pixeli-rgb-de-12mm

Se recomandă citirea cu atenție a informațiilor de utilizare furnizate de producător:

12mm LED Pixels

https://learn.adafruit.com/12mm-led-pixels

Pentru a realiza conexiunea între sistemul de lumini și telefonul mobil, fără a fi nevoie să scriem o aplicație mobilă personalizată, vom utiliza platforma IoT Blynk:

First drag-n-drop IoT app builder for Arduino, Raspberry Pi, ESP8266, SparkFun

boards, and others

http://www.blynk.cc/

Pentru o mai bună înțelegere a lecției de față se poate vedea și proiectul:

Cum să realizăm un sistem IoT fără să scriem nici o linie de cod?

Cea mai importantă grijă în realizarea montajului este alimentarea corectă a acestuia. Trebuie avut în vedere că sistemul va necesita o sursă externă de tensiune de 5V, minim 2A. Schema de interconectare este următoarea:

4

Chiar dacă schema nu prezintă shield-ul WiFi se presupune că acesta este instalat deasupra plăcii Arduino Uno utilizând un set de conectori Arduino R3.

Sursa de tensiune externă va alimenta atât ansamblul placă de dezvoltare Arduino Uno + shield WiFi cât și șirul de 25 de leduri RGB. Comanda de la placa de dezvoltare se va transmite către șirul de leduri pe două fire: pinul 5 – fir galben – date și pinul 6 – fir verde – semnal de ceas.

În cadrul programului Arduino se vor utiliza următoarele biblioteci externe mediului Arduino IDE:

Blynk Library

https://github.com/blynkkk/blynk-library

Adafruit WS2801 Library

https://github.com/adafruit/Adafruit-WS2801-Library

Adafruit CC3000 Library

https://github.com/adafruit/Adafruit_CC3000_Library

#include <Adafruit_WS2801.h>

#define ADAFRUIT_CC3000_IRQ   2

#define ADAFRUIT_CC3000_VBAT  7

#define ADAFRUIT_CC3000_CS    10

#include <SPI.h>

#include <Adafruit_CC3000.h>

#include <BlynkSimpleCC3000.h>

int dataPin = 5;

int clockPin = 6;

Adafruit_WS2801 strip = Adafruit_WS2801(25, dataPin, clockPin);

În program se va personaliza AUTH TOKEN furnizat de aplicația mobilă Blynk la crearea aplicației de comandă:

char auth[] = “AUTH TOKEN“;

și datele de conectarea la rețeaua WiFi locală:

char ssid[] = ““;

char pass[] = ““;

int wifi_sec = WLAN_SEC_WPA2;

Dacă se dorește urmărirea mesajelor de control ale sistemului Blynk în consola serială se va lăsa următoarea linie necomentată:

#define BLYNK_PRINT Serial 

Următoarele variabile globale permit controlul funcționării sistemului de lumini. Variabila mode reține comportamentul de funcționare, există 5 moduri de funcționare: modul 0 – toate ledurile sunt stinse, modul 1 – toate ledurile sunt aprinse având aceiași culoare dictată de aplicația de comandă, modul 2 – toate ledurile sunt aprinse având culori diferite, modul 3 – este aprins un singur led care se plimbă de la un capăt la altul al șirului de leduri și modul 4 – sunt aprinse toate ledurile iar culoarea este dată de accelerometrul telefonului mobil de pe care se face comanda. Variabila shift va reține comanda de culoare dată de aplicația mobilă. Variabila automat indică declanșarea unui interval de funcționare automată la oră fixă stabilită în aplicația mobilă de comandă. Variabilele lastmode și lastshift conțin ultimele valori ale variabilelor corespondente pentru ca sistemul să poată să răspundă la modificarea acestora.

byte mode = 0;

byte lastmode = 255;

int shift = 0;

int lastshift = -1;

byte automat = 0;

În cadrul secțiunii setup() se va inițializa conexiunea cu platforma Blynk și obiectul de comandă al șirului de leduri.

void setup()

{ Serial.begin(9600);

  Blynk.begin(auth, ssid, pass, wifi_sec);

  strip.begin();

  strip.show(); }

Procedurile BLYNK_WRITE preiau comenzile primite de la aplicația mobilă prin intermediul unor pini virtuali: pinul V1 va transmite comanda de culoare, pinul V2 va transmite comanda de mod de funcționare, pinul V3 va transmite comanda de funcționare automată și pinul V4 va transmite valorile primite de la accelerometrul telefonului mobil.

BLYNK_WRITE(V4) {

  if (mode==4) {

    int r = param[0].asFloat();

    int g = param[1].asFloat();

    int b = param[2].asFloat();

    shift = Color(r,g,b); }

}

BLYNK_WRITE(V3) {

  automat = param.asInt();

  mode = 3; }

BLYNK_WRITE(V2) { mode = param.asInt(); }

BLYNK_WRITE(V1) { shift = param.asInt(); }

În cadrul secțiunii loop() este implementat algoritmul de funcționare propriu-zisă a instalației de lumini – cele 5 moduri de funcționare.

void loop()

{ Blynk.run();

  if ((lastmode!=mode) || (lastshift!=shift) || automat) {

  switch (mode) {

    case 0:

      for (int i = 0; i < strip.numPixels(); i++)

        strip.setPixelColor(i, 0);

      strip.show();

      break;

    case 1:

      for (int i = 0; i < strip.numPixels(); i++)

        strip.setPixelColor(i, Wheel(shift & 255));

      strip.show();

      break;

    case 2:

      for (int i = 0; i < strip.numPixels(); i++)

        strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + shift) & 255));

      strip.show();

      break;

    case 3:

      for (int i = 0; i < strip.numPixels(); i++) {

        if(i>0) strip.setPixelColor(i-1, 0);     

        strip.setPixelColor(i, Wheel(shift & 255));

        strip.show();

        delay(200);

      }     

      strip.setPixelColor(strip.numPixels()-1, 0);

      strip.show();

      break;

    case 4:

      for (int i = 0; i < strip.numPixels(); i++)

        strip.setPixelColor(i, shift);

      strip.show();

      break;

  }

  lastmode = mode;

  lastshift = shift;

  }

}

Funcțiile Wheel și Color sunt folosite pentru prelucrarea comenzilor de culoare.

uint32_t Wheel(byte WheelPos) {

  if (WheelPos < 85) {

    return Color(WheelPos * 3, 255 – WheelPos * 3, 0);

  } else if (WheelPos < 170) {

    WheelPos -= 85;

    return Color(255 – WheelPos * 3, 0, WheelPos * 3);

  } else {

    WheelPos -= 170;

    return Color(0, WheelPos * 3, 255 – WheelPos * 3);

  }

}

uint32_t Color(byte r, byte g, byte b) {

  uint32_t c;

  c = r;

  c <<= 8;

  c |= g;

  c <<= 8;

  c |= b;

  return c;

}

Programul a fost dezvoltat și testat utilizând Arduino IDE 1.6.12, Arduino AVR Boards 1.6.15, Blynk Library 0.4.0, Adafruit CC3000 Library 1.0.3 și Adafruit WS2801 Library 1.0.0.

Bineînțeles, după realizarea și programarea sistemului de lumini este necesară generarea aplicației mobile utilizând aplicația Blynk:

https://play.google.com/store/apps/details?id=cc.blynk

https://itunes.apple.com/us/app/blynk-control-arduino-raspberry/id808760481?ls=1&mt=8

Se generează o aplicație nouă, putem să o botezăm ”cristmas wifi” de exemplu.

5

Este important să notăm AUTH TOKEN furnizat la crearea aplicației pentru a putea să-l trecem în program.

Aplicația va include 4 controale (Widget Box):

  • Un Slider S (200 de credite) conectat la pinul virtual V2 ce va stabili modul de funcționare a sistemului, variază între 0 și 4;

6

  • Un Slider L (200 de credite) conectat la pinul virtual V1 ce va stabili comanda de culoare, variază între 0 și 500;

7

  • Un Timer (200 de credite) conectat la pinul virtual V3 ce va declanșa funcționarea automată la oră fixă;

8

  • Un Accelerometer (400 de credite) conectat la pinul virtual V4 ce va transmite valorile pe cele 3 axe ale accelerometrului telefonului mobil.

9

În final aplicația va arăta în acest fel. Costul total al aplicație 1000 de credite.

10

La final obținem o instalație de lumini de crăciun la care putem să stabilim culoarea de aprindere, tiparul de aprindere, putem să o programăm să lumineze la oră fixă sau putem pur și simplu să ne facem de cap comandând-o prin intermediul accelerometrului din telefonul mobil. Puteți explora și alte facilități ale platformei Blynk pentru a vă personaliza instalația așa cum doriți.

Se pot consulta și alte metode de comandă WiFi pentru o instalație de lumini dar soluția propusă este una dintre cele mai simple și mai flexibile:

WiFi Controlled LED Christmahanukwanzaa Tree

https://learn.adafruit.com/wifi-controlled-led-christmahanukwanzaa-tree

ESP8266 controlling WS2812 Neopixel LEDs using Arduino IDE – A Tutorial

http://www.instructables.com/id/ESP8266-controlling-Neopixel-LEDs-using-Arduino-ID/

Arduino NeoPixel Wifi

https://create.arduino.cc/projecthub/andres-santos/arduino-neopixel-wifi-d1a93c

Controlling Neopixels with processing via wifi to nodeMCU

http://fablab.ruc.dk/controlling-neopixels-with-processing-via-wifi-to-nodemcu/