FOTA

User avatar
lesny8
Posts: 398
Joined: Mon Dec 11, 2017 9:43 pm

Fri Sep 07, 2018 10:18 pm

FOTA – co to?
FirmwareOverTheAir. A po naszemu coś dla tych, którzy chcą mieć aktualny firmware na swoich modułach bez kabelkologii i rozbierania łączników, puszek itp., aby dostać się do TX i RX, nie licząc oczywiście pierwszego flashowania.


Jak wygląda dobrodziejstwo FOTA?
Wchodzimy w tryb konfiguracji modułu, przestawiamy Firmware Update = YES. Zapisujemy i wychodzimy. Jeśli jest nowsza wersja firmware dla definicji modułu to się pobierze i zaktualizuje (sami musimy ją stworzyć i umieścić tam gdzie trzeba).


Dla kogo jest ten FAQ?
Dla tych co sobie sami kompilują soft. Trzeba deko ogarniać linuxa i minimalnie znać c, bash, sql, php.


Co zawiera ten FAQ w skrócie?
Kilka słów o niezbędnikach,
Trochę teorii,
Instalacja narzędzi,
Jak kompilować i flashować,
Zabiegi na bazie danych,
Jak kompilować pod www,
Zabiegi po stronie www.


Co trzeba mieć/umieć na tym etapie?
1. Umieć kompilować firmware
2. Posiadać konwerter USB ↔ UART i umieć flashować esptool-em
3. Mieć własną instancję SUPLA (ja mam na Dokerze)
4. Własny serwer www, może być lokalnie (u mnie akurat www jest w świecie)
5. Wirtualną maszynę lub jakąś dystrybuję linuxa (u mnie jest to Ubuntu).
6. Pobrać wszystkie niezbędne źródła na linuxa i dla porządku umieścić w jednym katalogu jak poniżej

Code: Select all

cd /home/$USER
mkdir SUPLA
cd SUPLA
git clone https://github.com/SUPLA/supla-espressif-esp
git clone https://github.com/SUPLA/supla-esp-signtool
mkdir Firmware

Jeśli mamy już pobrane oprogramowanie, to co teraz?
Musimy wygenerować klucze publiczny i prywatny.


Po co jest klucz publiczny i prywatny?
Klucz publiczny służy do zweryfikowania poprawności pobranego wsadu w procesie aktualizacji. Klucz prywatny do podpisania skrótu wsadu, zasada jak na schemacie
Image


Skąd wziąć klucze?
Trzeba wygenerować własną parę kluczy, za pomocą pobranych narzędzi supla-esp-signtool


Jak zainstalować supla-esp-signtool?
Najpierw uaktualniamy zainstalowane pakiety i instalujemy libgmp-dev

Code: Select all

sudo apt update
sudo apt upgrade
sudo apt install libgmp-dev 
Potrzebne są jeszcze biblioteki nettle, ale te trzeba już zainstalować ze źródeł.
Pobieramy wersje nettle-3.3, na niej mi wszystko zadziałało. Chętni mogą sprawdzić inne wersje.

https://www.lysator.liu.se/~nisse/nettle/

Rozpakowujemy i będąc wewnątrz katalogu nettle-3.3 wykonujemy

Code: Select all

./configure
make
make check
sudo make install
Jak widać instalujemy z sudo, bo inaczej jest brak dostępu do usr/local gdzie instaluje się nettle.
Następnie przechodzimy do lokalizacji supla-esp-signtool do katalogu Release i kompilujemy

Code: Select all

cd /home/$USER/SUPLA/supla-esp-signtool-master/Release/
make
jeżeli dostaniecie błąd tak jak ja,

Code: Select all

Finished building: ../src/sigtool.c
 
Building target: supla-esp-sigtool
Invoking: Cross GCC Linker
gcc  -o "supla-esp-sigtool"  ./src/sigtool.o   -lhogweed -lnettle
/usr/bin/ld: ./src/sigtool.o: undefined reference to symbol '__gmpz_init'
//usr/lib/x86_64-linux-gnu/libgmp.so.10: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
makefile:30: polecenia dla obiektu 'supla-esp-sigtool' nie powiodły się
make: *** [supla-esp-sigtool] Błąd 1
to trzeba dopisać w pliku objects.mk na końcu -lgmp

Code: Select all

nano objects.mk
tak ma to wyglądać

Code: Select all

################################################################################
# Automatically-generated file. Do not edit!
################################################################################

USER_OBJS :=

LIBS := -lhogweed -lnettle -lgmp
zapisujemy i wracamy do kompilacji signtool

Code: Select all

make clean
make
powinno się skompilować bez błędu.


Jak wygenerować parę kluczy?
Przechodzimy do katalogu z singtool i wykonujemy polecenie

Code: Select all

 
cd /home/$USER/SUPLA/supla-esp-signtool-master/Release/
./supla-esp-sigtool -k klucz -g

Co robić dalej z kluczami?
Klucz prywatny strzeżemy jak oka w głowie. Jeżeli nadpiszemy sobie klucz prywatny, to czekać nas będzie ponownie kabelkologia modułów, które wykorzystują klucz publiczny z tej pary.
Klucz publiczny wykorzystamy później. Na tę chwilę klucz publiczny konwertujemy do tablicy poleceniem

Code: Select all

./supla-esp-sigtool -k klucz.pub -c public_key_in_c_code
i robimy dowiązanie symboliczne, za chwilę się wyjaśni po co

Code: Select all

ln -s /home/$USER/SUPLA/supla-esp-signtool-master/Release/public_key_in_c_code /home/$USER/SUPLA/supla-espressif-esp/src/include/board/public_key_in_c_code

Jeśli mam już parę kluczy to co teraz?
Tworzymy własną definicję płytki, może być zbudowana na bazie przykładów z pobranych źródeł .
Zapisujemy nasze wypociny np. jako moja.c i moja.h. Umieszczamy w definicji płytki klucz publiczny w postaci tablicy

Code: Select all

const uint8_t rsa_public_key_bytes[512] = {
lub prościej dopisujemy w definicji pliku moja.c gdziekolwiek na początku sekcję, wcześniej zrobiliśmy dowiązanie symboliczne więc bez problemu kompilator zobaczy plik z naszym kluczem.

Code: Select all

#include ”public_key_in_c_code”

Co dalej?
Kompilujemy ./build.sh wybierając naszą płytkę z parametrem FOTA=1


Nie mam w build.sh swojej płytki, jak ją dodać?
Analogicznie do pozostałych. Odnajdujemy case z opcjami

Code: Select all

case $1 in
   "moja")
     FLASH_SIZE="2048"
     FOTA=1
   ;;
   "wifisocket")
   ;;
i w pliku supla_esp_board.c dopisujemy przed ostatnim #endif i w pliku supla_esp_board.h to samo ale przed dwoma #endif, gdzie jest nasz plik z definicją płytki

Code: Select all

#elif defined(__BOARD_moja)

#include "board/moja.c"
i kompilujemy

Code: Select all

cd /home/$USER/SUPLA/supla-espressif-esp/src/
./build.sh moja

Gdzie wgrywamy skompilowany firmware?
Na adresy które wyświetlił nam kompilator. Pamiętajmy jednak, że kompilujemy i wgrywamy za pomocą kabli tylko user1 (mam tu na myśli, że nie musimy wgrywać user2)

Code: Select all

boot.bin------------>0x00000
user1.2048.new.5.bin--->0x01000

Jak flashować?
Ja to robię na esptoolu, możemy się w tym miejscu przesiąść na Flash Download Tools lub coś innego, tylko po co :D
Czyścimy i flashujemy, wybierając odpowiednią mapę, tę dla której kompilowaliśmy, czyli w tym przypadku 2MB-c1. Ja na esptoolu mam tak

Code: Select all

esptool.py -p /dev/ttyUSB0 -b 115200 erase_flash
esptool.py -p /dev/ttyUSB0 -b 115200 write_flash -fm dio -ff 40m -fs 2MB-c1 \
0x00000 /home/$USER/SUPLA/Firmware/boot_v1.5.bin \
0x01000 /home/$USER/SUPLA/Firmware/moja_user1.2048.new.5.bin \
0x1fc000 /opt/Espressif/ESP8266_NONOS_SDK154/bin/esp_init_data_default.bin

Dlaczego wgrywamy na 2MB a nie 4MB skoro mam w module dostępne 4MB?
Mapa jest dowolna, ważne żeby kompilację i flashowanie dokonać na tych samych ustawieniach i żeby zmieściło się do modułu. Równie dobrze mogłem skompilować z parametrem 4MB lub 4MB-c1.
Jeśli wgramy na innej mapie, moduł też wstanie i będzie działać, ale aktualizacja już nie będzie działać o czym sam się przekonałem, podczas próby przebrnięcia przez wszystkie etapy. Parametr mapy jest przesyłany do sprawdzenia nowych wersji, dlatego musimy zachować spójność. Kompiluje 4MB-c1 to wgrywam z taką mapą. Jak kompiluję 4MB, to wgrywam z taką samą. Nie zapominajcie także o pliku inicjującym chip esp_init_data_default.bin, którego adres zależy od wybranej mapy.
flash_map__.jpg
flash_map__.jpg (38.89 KiB) Viewed 7166 times

Mam starą wersję esptoola i nie mam takich parametrów, co teraz?
Poszukaj w helpie parametrów dla swojej wersji lub zaktualizuj do najnowszej. Kiedyś pisałem jak to zrobiłem tutaj
viewtopic.php?p=19434#p19434


Co do zrobienia po stronie bazy danych?
Trzeba wskazać gdzie moja kompilacja ma szukać nowych wersji softu, wskazać mapę z jaką jest skompilowany .bin i jeszcze parę innych drobiazgów.
Jeśli macie tabelę esp_update, esp_update_log i niezbędne procedury to fajnie, będzie mniej roboty. Ja nie miałem, moja baza przechodziła konwersje z 2.0 -> 2.1 -> 2.2 i jakoś jej tych tabel zabrakło.


Jak sprawdzić czy mam tabele w bazie?
Dla instalacji dockerowej składnia jest następująca

Code: Select all

source supla-docker/.env && docker exec supla-db mysql -u supla --password=$DB_PASSWORD supla -e "show tables like 'esp_update' "
jeśli jest to powinniśmy dostać taki wynik

Code: Select all

Tables_in_supla (esp_update)
esp_update
Pewnie reszta też będzie, dgdyby jednak nie było to tu są definicje obu tabel
esp_update
esp_update_log

https://github.com/SUPLA/supla-cloud/bl ... 234138.php

i procedura supla_get_device_firmware_url

https://github.com/SUPLA/supla-cloud/bl ... 222022.php


Czy na bazie robimy coś jeszcze?
Gdyby nie było, ja już miałem

Code: Select all

DELIMITER $$
--
-- Procedures
--
DROP PROCEDURE IF EXISTS `supla_get_device_firmware_url`$$
CREATE DEFINER=`root`@`localhost` PROCEDURE `supla_get_device_firmware_url` (IN `device_id` INT, IN `platform` TINYINT, IN `fparam1` INT, IN `fparam2` INT, IN `fparam3` INT, IN `fparam4` INT, OUT `protocols` TINYINT, OUT `host` VARCHAR(100), OUT `port` INT, OUT `path` VARCHAR(100))  NO SQL
BEGIN

SET @protocols = 0;
SET @host = '';
SET @port = 0;
SET @path = '';

SET @fparam1 = fparam1;
SET @fparam2 = fparam2;
SET @platform = platform;
SET @device_id = device_id;

INSERT INTO `esp_update_log`(`date`, `device_id`, `platform`, `fparam1`, `fparam2`, `fparam3`, `fparam4`) VALUES (NOW(),device_id,platform,fparam1,fparam2,fparam3,fparam4);

SELECT u.`protocols`, u.`host`, u.`port`, u.`path` INTO @protocols, @host, @port, @path FROM supla_iodevice AS d, esp_update AS u WHERE d.id = @device_id AND u.`platform` = @platform AND u.`fparam1` = @fparam1 AND u.`fparam2` = @fparam2 AND u.`device_name` = d.name AND u.`latest_software_version` != d.`software_version` AND 

(
version_to_int(d.`software_version`) = 0 OR
version_to_int(u.`latest_software_version`) = 0 OR
version_to_int(u.`latest_software_version`) > version_to_int(d.`software_version`)
)

AND

( u.`device_id` = 0 OR u.`device_id` = device_id ) LIMIT 1;


SET protocols = @protocols;
SET host = @host;
SET port = @port;
SET path = @path;

END$$


DROP FUNCTION IF EXISTS `version_to_int`$$
CREATE DEFINER=`root`@`localhost` FUNCTION `version_to_int` (`version` VARCHAR(10)) RETURNS INT(11) NO SQL
BEGIN
DECLARE result INT DEFAULT 0;
DECLARE n INT DEFAULT 0;
DECLARE m INT DEFAULT 0;
DECLARE dot_count INT DEFAULT 0;
DECLARE last_dot_pos INT DEFAULT 0;
DECLARE c VARCHAR(1);

WHILE n < LENGTH(version) DO
    SET n = n+1;
    SET c = SUBSTRING(version, n, 1);
    
    IF c <> '.' AND ( ASCII(c) < 48 OR ASCII(c) > 57 )
      THEN 
         SET result = 0;
         RETURN 0;
      END IF; 
      
    
   IF c = '.' THEN
     SET dot_count = dot_count+1;
     IF dot_count > 2 THEN 
        SET result = 0;
        RETURN 0;
     END IF;
   END IF;

   IF c = '.' OR n = LENGTH(version) THEN

      SET m = n-last_dot_pos-1;
      
      IF c <> '.' THEN
        SET m = n-last_dot_pos;
        SET dot_count = dot_count+1;
      END IF;
      
          SET result = result + POWER(10, 9-dot_count*3) * SUBSTRING(version, last_dot_pos+1, m);
      
      SET last_dot_pos = n;
   END IF;
      
END WHILE;
RETURN result;
END$$

DELIMITER ;

Co wpisać do tabeli esp_update?
Taki insert robimy, oczywiście nazwę domeny zmieniamy na swoją, nazwę kompilacji, wersję softu i nazwę pliku, oraz fparam1 jeśli kompilujemy z inną mapą.

Code: Select all

source supla-docker/.env && docker exec supla-db mysql -u supla --password=$DB_PASSWORD supla -e " \
INSERT INTO esp_update (id, device_id, device_name, platform, latest_software_version, fparam1, fparam2, protocols, host, port, path) VALUES \
(1, 0, 'moja', 1, '2.7.2', 5, 0, 1, 'www.mojadomena.pl', 80, 'get_file.php?file=moja_user2.2048.new.5.bin'), \
(2, 0, 'moja', 1, '2.7.2', 5, 1, 1, 'www.mojadomena.pl', 80, 'get_file.php?file=moja_user1.2048.new.5.bin');"
Jak skompilować firmware pod upload na www?
Tak samo jak standardowo, ale trzeba skompilować user 1 i user2 a później je podpisać kluczem prywatnym

Code: Select all

./build.sh moja
./build.sh moja user2

Jak podpisać pliki kluczem prywatnym?
Przechodzimy do katalogu z signtool i wskazujemy odpowiedni plik z kluczem i plik do podpisu

Code: Select all

cd /home/$USER/SUPLA/supla-esp-signtool-master/Release
./supla-esp-sigtool -k klucz -s /home/$USER/SUPLA/Firmware/moja_user1.2048.new.5.bin 
./supla-esp-sigtool -k klucz -s /home/$USER/SUPLA/Firmware/moja_user2.2048.new.5.bin 
Można sprawdzić poprawność podpisanych plików

Code: Select all

./supla-esp-sigtool -k klucz -v /home/$USER/SUPLA/Firmware/moja_user1.2048.new.5.bin 
./supla-esp-sigtool -k klucz -v /home/$USER/SUPLA/Firmware/moja_user2.2048.new.5.bin 
Co mam zrobić po stronie serwera www?
Teoretycznie nic, bo pliki *.bin nie są rozpoznawane przez przeglądarkę jako coś do otwarcia i są od razu pobierane, ale dobrze jest sobie wstawić taki prosty skrypt znaleziony w sieci, zapisujemy pod jakąś nazwą np. get_file.php i wrzucamy na serwer www. Tworzymy jeszcze w tym samym miejscu co get_file.php katalog „update” do którego będziemy w wrzucać nasze pliki bin

Code: Select all

<?php
if(!empty($_GET['file'])) { 
    $file = str_replace('..','',$_GET['file']); 
    $cat_with_file = 'update';
    $local_file = $cat_with_file.'/'.$file;
 
    if(file_exists($local_file) && is_file($local_file))
    {
        //Otwarcie pliku
        $fp = fopen($local_file, 'rb');
 
        //Wysyłanie informacji o pliku do przeglądarki
        header('Content-Type: application/octet-stream'); //Typ
        header('Content-Length: ' .filesize($local_file)); //Rozmiar
        header('Content-Disposition: filename='.$file); //Nazwa
 
        //Zrzucanie pliku i zatrzymanie skryptu
        fpassthru($fp);
        exit;
    }
    else die("ERROR: Plik ".$file." nie istnieje!");
}
else header('HTTP/1.0 404 Not Found', true, 404);
?>

Czy to już?
Wystarczy wysłać podpisane pliki na serwer www do katalogu "update" i gotowe. Możemy korzystać z dobrodziejstwa jakie daje nam FOTA :D


P.S. Uff. Taka dygresja mnie naszła, choć nic nowego nie stworzyłem.
Wiecie co jest najbardziej czasochłonne podczas tworzenia oprogramowania :?:
Tworzenie dokumentacji ;)
Last edited by lesny8 on Sat Nov 17, 2018 11:56 am, edited 1 time in total.
User avatar
lesny8
Posts: 398
Joined: Mon Dec 11, 2017 9:43 pm

Fri Sep 07, 2018 10:18 pm

Reserv
User avatar
Espablo
Posts: 1344
Joined: Wed Jun 29, 2016 5:04 pm
Location: Oświęcim
Contact:

Fri Sep 07, 2018 11:25 pm

Super! Wygląda na to, że nie wiele mi brakowało do uruchomienia FOTA. Muszę jeszcze znaleźć serwer gdzie będę mógł wrzucać najnowsze kompilacje :D Dziękuję
Każde urządzenie elektryczne działa o wiele lepiej jeśli podłączysz je do prądu. :? :roll:
https://github.com/Espablo
User avatar
pzygmunt
Posts: 4957
Joined: Tue Jan 19, 2016 9:26 am
Location: Paczków
Contact:

Sat Sep 08, 2018 8:25 am

Co do mapy pamięci. Wybierany taką, która dzieli pamięć na równe dwa „kawałki”. Zazwyczaj C1
User avatar
Espablo
Posts: 1344
Joined: Wed Jun 29, 2016 5:04 pm
Location: Oświęcim
Contact:

Sat Sep 08, 2018 9:57 am

Jak przebiega kompilacja dla np. 4MB-c1 a jak dla 4MB?
Każde urządzenie elektryczne działa o wiele lepiej jeśli podłączysz je do prądu. :? :roll:
https://github.com/Espablo
User avatar
lesny8
Posts: 398
Joined: Mon Dec 11, 2017 9:43 pm

Sat Sep 08, 2018 3:13 pm

Poprzez oficjalny build.sh z opcją FOTA=1 wydaje mi się, że akurat nie da się skompilować dla 4MB, ale na pewno da radę dla 2MB-c1 i 4MB-c1. Nie przetestowałem wszystkich wariantów, a tylko te dwa i jak ustawisz FLASH_SIZE="2048" to skompilujesz z mapą 2MB-c1, a jak ustawisz FLASH_SIZE="4096" to skompilujesz z mapą 4MB-c1.
User avatar
slawek
Posts: 2073
Joined: Mon Mar 14, 2016 11:48 pm
Location: Biała Podlaska

Thu Sep 20, 2018 8:37 pm

Code: Select all

slawek Release # ./supla-esp-sigtool -k klucz -g
./supla-esp-sigtool: error while loading shared libraries: libhogweed.so.4: cannot open shared object file: No such file or directory
Co muszę doinstalować?
Gdy wszystkie możliwe sposoby zawiodą - pozostaje przeczytać instrukcję...
User avatar
Espablo
Posts: 1344
Joined: Wed Jun 29, 2016 5:04 pm
Location: Oświęcim
Contact:

Thu Sep 20, 2018 8:52 pm

Kompilacje supla-esp-sigtool miałeś bez błędów?
Każde urządzenie elektryczne działa o wiele lepiej jeśli podłączysz je do prądu. :? :roll:
https://github.com/Espablo
User avatar
slawek
Posts: 2073
Joined: Mon Mar 14, 2016 11:48 pm
Location: Biała Podlaska

Thu Sep 20, 2018 9:02 pm

Miałem tylko ten
Jeżeli dostaniecie błąd tak jak ja,

Code: Select all

Finished building: ../src/sigtool.c
 
Building target: supla-esp-sigtool
Invoking: Cross GCC Linker
gcc  -o "supla-esp-sigtool"  ./src/sigtool.o   -lhogweed -lnettle
/usr/bin/ld: ./src/sigtool.o: undefined reference to symbol '__gmpz_init'
//usr/lib/x86_64-linux-gnu/libgmp.so.10: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
makefile:30: polecenia dla obiektu 'supla-esp-sigtool' nie powiodły się
make: *** [supla-esp-sigtool] Błąd 1
to trzeba dopisać w pliku objects.mk na końcu -lgmp
I po tym poszło OK
Gdy wszystkie możliwe sposoby zawiodą - pozostaje przeczytać instrukcję...
User avatar
Espablo
Posts: 1344
Joined: Wed Jun 29, 2016 5:04 pm
Location: Oświęcim
Contact:

Thu Sep 20, 2018 9:16 pm

Brakuje biblioteki libhogweed. Może spróbuj doinstalować ręcznie.
https://ubuntu.pkgs.org/16.04/ubuntu-ma ... 6.deb.html

Code: Select all

sudo apt-get install libhogweed4
Każde urządzenie elektryczne działa o wiele lepiej jeśli podłączysz je do prądu. :? :roll:
https://github.com/Espablo
Post Reply