ITСooky

IT-рецепты съедобные и не очень!

Дубликатор USB флешек на Raspberry Pi c Wi-Fi интерфейсом на Node-RED!

дата 13.06.2020

Буду делать устройство для копирования данных с одной USB флешки на другу. В качестве начинки Raspberry Pi 4, доступ по Wi-Fi, движок Node-RED!

Дубликаторы USB существуют, это такие башенки от 15 до 199 флешек — по космическим ценам! Самое близкое что нашел вот StarTech 1:2 Standalone USB 2.0 Flash Drive Duplicator and Eraser (Black) на Западе по 100$ у нас по 300$ — но это USB 2(и без Wi-Fi), а на малинке будет дубликатор USB 3!

Сегодня у меня малинка будет в корпусе Argon NEO Pi 4 Raspberry Pi Case Очень добротный корпус — металл, стильно красиво, крышка на магнитах в любой моменты доступны пины! Но сильно горячий!






ОСТОРОЖНО: Надо учесть нюансы — у Raspberry Pi 4 есть нюансы!
1. Сильно греются USB порты и с ними флешки — так сильно что в руках горячо держать. Думал прошивка старая — она реально была горячая — нет, прошивка новейшая. Видимо из-за того что Rpi 4 ревизии 1.1 у них пробелмы с питанием по USB-C от неродных БП — ну и из-за корпуса конечно тоже!
2. Сами USB 3 разъемы, плохие. Задираются при попытки вставить фирменную USB флешку Samsung. Пришлось поджать слегка вот эти прижымки (4 шт.) — в USB 2 их нет!

Надо ставить Raspberry Pi OS (32-bit) Lite (ранее известный как Raspbian) в этой версии нет Desktop окружения.

Качаю её тут www.raspberrypi.org/downloads/raspbian/
А вот тут качаю установщик — есть для Ubuntu — круто! https://www.raspberrypi.org/downloads/

Однако на Ubuntu ничего не получилось… сделал на Windows, эх! Мы убунтные об этом не говорим, но мягко говоря, с подключаемыми флешками Ubuntu работает плохо… а скорость копирования на usb флешку, и момент когда её можно же вынимать, она до сих пор (июнь, 2020) не умеет определять — не верьте прогресс бару — только софт анмаунт, он скажет точно можно выдергивать или нет!

Чтобы ssh работал, на карте в BOOT разделе надо сделать файл с именем ssh и оно после этого будет работать. После этого можно карту вставлять в малинку и смотреть какой малинка получила IP я посмотрел на роутере, можно и на малинку руками зайти и посмотреть коммандой
ifconfig

Имя: pi
пароль: raspberry

Посмотрю что у меня за модель
cat /sys/firmware/devicetree/base/model

Raspberry Pi 4 Model B Rev 1.1

Посмотрим сколько памяти
free -h

              total        used        free      shared  buff/cache   available
Mem:          3.8Gi        90Mi       3.5Gi       8.0Mi       242Mi       3.6Gi
Swap:          99Mi          0B        99Mi

о 4Gb!

sudo apt update
sudo apt full-upgrade

замерим температуру сразу полсе апгрейда
vcgencmd measure_temp

temp=46.0'C

Вообще не вспотел!

Проверяю скорость записи файла на Малинке на SD карту
dd if=/dev/zero of=test.file count=10000 bs=1048576

10485760000 bytes (10 GB, 9.8 GiB) copied, 1050.75 s, 10.0 MB/s

такой же результат был и у Raspberry Pi 4 на 2 Gb

Теперь на флешку USB 3.1 через USB 3 на малинке. Производители флешек форматируют в vFAT оно же FAT32, хреновая fs максимальный размер файла 4GB

Будем форматировать в NTfS
sudo apt-get install ntfs-3g
уже был установлен

sudo mkntfs --fast --label USB32gb /dev/sda1
sudo mkdir /mnt/usb1
sudo mkdir /mnt/usb2
sudo mount /dev/sda1 /mnt/usb1
cd /mnt/usb1

date&&dd if=/dev/zero of=test.file count=10000 bs=1048576&&date&&vcgencmd measure_temp
итого

Mon Jun  8 14:12:18 BST 2020
10000+0 records in
10000+0 records out
10485760000 bytes (10 GB, 9.8 GiB) copied, 437.284 s, 24.0 MB/s
Mon Jun  8 14:19:35 BST 2020
temp=56.0'C

Теперь подключаю вторую такуюже флешку, и ставлю
sudo apt-get install pv
для тестирования копирования с флешки на флешку
pv /mnt/usb1/test.file > /mnt/usb2/test.file

Mon Jun  8 15:24:58 BST 2020
9.77GiB 0:07:07 [23.4MiB/s] [=======================================>] 100%            
Mon Jun  8 15:32:06 BST 2020
temp=61.0'C

Делаем из Малинки точку доступа Wi-Fi
Все прекрасно описано вот тут https://learn.sparkfun.com/tutorials/setting-up-a-raspberry-pi-3-as-an-access-point/all для RPI4 надо толко еще одну команду добавить!

Однако сначала надо обновиться а то не ставится
sudo apt-get update
sudo apt install dnsmasq hostapd

все равно не ставится, ставлю так
sudo apt install dnsmasq hostapd --fix-missing

Поставилось, дальше много чего редактруем
sudo vi /etc/dhcpcd.conf
Добавляю

denyinterfaces wlan0

sudo vi /etc/network/interfaces
Добавляем

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet static
    address 10.100.10.1
    netmask 255.255.255.0
    network 10.100.10.0
    broadcast 10.100.10.255

sudo vi /etc/hostapd/hostapd.conf
Добавляем

interface=wlan0
driver=nl80211
ssid=Itcooky
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=QWErty123
rsn_pairwise=CCMP

sudo vi /etc/default/hostapd
Добавляем

DAEMON_CONF="/etc/hostapd/hostapd.conf"

sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.bak
sudo vi /etc/dnsmasq.conf

Добавляем

interface=wlan0 
listen-address=10.100.10.1
bind-interfaces 
server=8.8.8.8
domain-needed
bogus-priv
dhcp-range=10.100.10.10,10.100.10.250,24h

Выполняем
sudo systemctl start dnsmasq
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd

И для RPI4 надо еще
sudo rfkill unblock wlan

Перегружаемся
sudo reboot


Ставим Node Red

Для RPI есть способ от самих красных
https://nodered.org/docs/getting-started/raspberrypi

Надо только выпонить
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
И чтобы само грузилось
sudo systemctl enable nodered.service

И все, заходим на http://111.222.33.44:1880 и делаем что хотим

Не скажу что это было просто, но простенький скрипт по копироания с одной флешки на другую готов
Вот кирпичи

Вот тоже самое кодом

[{"id":"b44d7514.83389","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"54fb509b.2c2ed","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda1m.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":370,"y":160,"wires":[["becfcd98.7c18f"],[],[]]},{"id":"e32b03af.b293f","type":"ui_text","z":"b44d7514.83389","group":"7f5c3aa5.c49854","order":0,"width":0,"height":0,"name":"","label":"Size of data:","format":"{{msg.payload}}Mb","layout":"row-left","x":1150,"y":160,"wires":[]},{"id":"58b931c3.744ac8","type":"ui_button","z":"b44d7514.83389","name":"","group":"7f5c3aa5.c49854","order":1,"width":0,"height":0,"passthru":false,"label":"Mount","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":130,"y":160,"wires":[["54fb509b.2c2ed"]]},{"id":"4de280ba.95e15","type":"switch","z":"b44d7514.83389","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"asize","vt":"str"},{"t":"cont","v":"label","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":730,"y":200,"wires":[["cea5bb16.b5a5a8"],["cedce86d.2aa818"]]},{"id":"cea5bb16.b5a5a8","type":"split","z":"b44d7514.83389","name":"","splt":"#","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":870,"y":180,"wires":[["e32b03af.b293f"]]},{"id":"284f5a3e.56b85e","type":"ui_text","z":"b44d7514.83389","group":"7f5c3aa5.c49854","order":0,"width":0,"height":0,"name":"","label":"Label:","format":"{{msg.payload}}","layout":"row-left","x":1170,"y":220,"wires":[]},{"id":"cedce86d.2aa818","type":"split","z":"b44d7514.83389","name":"","splt":"#","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":870,"y":220,"wires":[["284f5a3e.56b85e"]]},{"id":"becfcd98.7c18f","type":"split","z":"b44d7514.83389","name":"","splt":";","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":610,"y":200,"wires":[["4de280ba.95e15"]]},{"id":"54348537.5cdffc","type":"ui_button","z":"b44d7514.83389","name":"","group":"7f5c3aa5.c49854","order":3,"width":0,"height":0,"passthru":false,"label":"Un mount","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":140,"y":240,"wires":[["e2c3bf55.06fee"]]},{"id":"e2c3bf55.06fee","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda1u.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":370,"y":240,"wires":[["becfcd98.7c18f"],[],[]]},{"id":"826e7da6.89bc","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda2m.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":370,"y":340,"wires":[["5ca805f5.1e5734"],[],[]]},{"id":"ee6a802b.3ad798","type":"ui_text","z":"b44d7514.83389","group":"ec3ace8.c36b93","order":3,"width":0,"height":0,"name":"","label":"Free size:","format":"{{msg.payload}}Mb","layout":"row-left","x":1160,"y":340,"wires":[]},{"id":"baa5392d.c28648","type":"ui_button","z":"b44d7514.83389","name":"","group":"ec3ace8.c36b93","order":1,"width":0,"height":0,"passthru":false,"label":"Mount","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":130,"y":340,"wires":[["826e7da6.89bc"]]},{"id":"bda8585a.0472e8","type":"switch","z":"b44d7514.83389","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"asize","vt":"str"},{"t":"cont","v":"label","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":890,"y":420,"wires":[["6b20dc3b.1afd9c"],["ce94c5f1.65b9b"]]},{"id":"6b20dc3b.1afd9c","type":"split","z":"b44d7514.83389","name":"","splt":"#","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":1010,"y":340,"wires":[["ee6a802b.3ad798"]]},{"id":"9c0610b1.2325c8","type":"ui_text","z":"b44d7514.83389","group":"ec3ace8.c36b93","order":4,"width":0,"height":0,"name":"","label":"Label:","format":"{{msg.payload}}","layout":"row-left","x":1170,"y":460,"wires":[]},{"id":"ce94c5f1.65b9b","type":"split","z":"b44d7514.83389","name":"","splt":"#","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":1010,"y":460,"wires":[["9c0610b1.2325c8"]]},{"id":"bc7259c4.a27fd","type":"split","z":"b44d7514.83389","name":"","splt":";","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":770,"y":420,"wires":[["bda8585a.0472e8"]]},{"id":"3592ca8.0bf7db6","type":"ui_button","z":"b44d7514.83389","name":"","group":"ec3ace8.c36b93","order":2,"width":0,"height":0,"passthru":false,"label":"Un mount","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":140,"y":420,"wires":[["692f75d5.160f24"]]},{"id":"692f75d5.160f24","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda2u.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":370,"y":420,"wires":[["bc7259c4.a27fd"],[],[]]},{"id":"154aa879.197de","type":"ui_button","z":"b44d7514.83389","name":"","group":"2fa9608d.2ce59","order":2,"width":0,"height":0,"passthru":false,"label":"Start copy","tooltip":"","color":"","bgcolor":"","icon":"","payload":"reset","payloadType":"str","topic":"","x":140,"y":560,"wires":[["7ee0395c.eba5b","611d713d.726e48"]]},{"id":"611d713d.726e48","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sdacopy.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":670,"y":620,"wires":[["44ed3481.f21c14"],[],[]]},{"id":"9abe71d5.48763","type":"ui_text","z":"b44d7514.83389","group":"2fa9608d.2ce59","order":3,"width":0,"height":0,"name":"","label":"","format":"Coping to USB IN to folder /{{msg.payload}}","layout":"row-left","x":1170,"y":520,"wires":[]},{"id":"fdd997bc.69107","type":"ui_gauge","z":"b44d7514.83389","name":"","group":"2fa9608d.2ce59","order":4,"width":0,"height":0,"gtype":"donut","title":"progress","label":"%","format":"{{value}}","min":0,"max":"100","colors":["#00b500","#e6e600","#ca3838"],"seg1":"","seg2":"","x":640,"y":560,"wires":[]},{"id":"7ee0395c.eba5b","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sdaspeed.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":380,"y":560,"wires":[["fdd997bc.69107","a0ec9eaa.97de38"],[],[]]},{"id":"5ca805f5.1e5734","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda2s.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":650,"y":320,"wires":[["bc7259c4.a27fd"],[],[]]},{"id":"207aabab.8d4fc4","type":"inject","z":"b44d7514.83389","name":"","topic":"null on start","payload":" ","payloadType":"str","repeat":"","crontab":"","once":true,"onceDelay":0.1,"x":170,"y":80,"wires":[["e32b03af.b293f","284f5a3e.56b85e","ee6a802b.3ad798","9c0610b1.2325c8","fdd997bc.69107","9abe71d5.48763"]]},{"id":"7fd33d21.b6d0dc","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sdatemp.sh","addpay":true,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"","x":380,"y":680,"wires":[["3ad9aa64.4a2d8e"],[],[]]},{"id":"3ad9aa64.4a2d8e","type":"ui_text","z":"b44d7514.83389","group":"2fa9608d.2ce59","order":4,"width":0,"height":0,"name":"","label":"Rpi4","format":"{{msg.payload}}","layout":"row-left","x":590,"y":680,"wires":[]},{"id":"3b1fe249.a09c66","type":"inject","z":"b44d7514.83389","name":"","topic":"","payload":"","payloadType":"date","repeat":"5","crontab":"","once":false,"onceDelay":0.1,"x":170,"y":680,"wires":[["7fd33d21.b6d0dc"]]},{"id":"a0ec9eaa.97de38","type":"exec","z":"b44d7514.83389","command":"bash /home/pi/sda2sup.sh","addpay":true,"append":"","useSpawn":"true","timer":"","oldrc":false,"name":"","x":670,"y":480,"wires":[["6b20dc3b.1afd9c"],[],[]]},{"id":"44ed3481.f21c14","type":"switch","z":"b44d7514.83389","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"pathonusb","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":890,"y":560,"wires":[["2ed432f3.bb44be"]]},{"id":"2ed432f3.bb44be","type":"split","z":"b44d7514.83389","name":"","splt":"#","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":1010,"y":560,"wires":[["9abe71d5.48763"]]},{"id":"7f5c3aa5.c49854","type":"ui_group","z":"","name":"USB OUT","tab":"636d4846.38f48","order":1,"disp":true,"width":"6","collapse":false},{"id":"ec3ace8.c36b93","type":"ui_group","z":"","name":"USB IN","tab":"636d4846.38f48","order":2,"disp":true,"width":"6","collapse":false},{"id":"2fa9608d.2ce59","type":"ui_group","z":"","name":"Copy","tab":"636d4846.38f48","order":3,"disp":true,"width":"5","collapse":false},{"id":"636d4846.38f48","type":"ui_tab","z":"","name":"USB dublicator","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

Надо доустановить для консоли линукс
sudo apt-get install bc
Так же должны быть папки
/mnt/usb1
/mnt/usb2

А в самом Node-Red надо установить node-red-dashboard

Все держится на кирпиче exec - который запускает bash скрипт - напрямую запускать комманды линукс он не умеет! Так что нужны еще скрипты!

В папку /home/pi/ создайте следующие скрипты

sda1m.sh - этот скрипт монтирует первую флешку с которой будем копировать, после нажатия кнопки. И делает это не просто так а проверяет, свободно ли место куда монтировать, и неважно под какой буквой подцепилась флешка!

#!/bin/bash
for m1 in $( ls /dev/sd*[0-9]* )
do 
if df -h | grep /mnt/usb1
then
echo "busy"
break
else
sudo mount $m1 /mnt/usb1
label=`lsblk -o mountpoint,label| grep /mnt/usb1|awk '{print $2}'`
frees=`du -sm --exclude='.Trash*' /mnt/usb1| awk '{print $1}'`
echo "label#"$label";asize#"$frees
break
fi
done

Из себя это скрипт выпускает строку с данным по размеру данных и метке флешки!

sda1u.sh - это скрипт просто размонтирует флешку после нажатия кнопки

#!/bin/bash
sudo umount /mnt/usb1
echo "label#no usb flash;asize#0"

sda2m.sh - этот скрипт монтирует вторую флешку

#!/bin/bash
if df -h | grep /mnt/usb2
then
echo "Busy"
else	
sdam=`df -h | grep usb1 | awk '{print $1}'`
for m1 in $( ls /dev/sd*[0-9]* )
do
if [ $m1 != $sdam ] 
then	
sudo mount $m1 /mnt/usb2
fi
done
fi

sda2s.sh - за ним идет скрипт который дает информацию о доступном месте и метке флешки

#!/bin/bash
m1=`df -h | grep /mnt/usb2|awk '{print $1}'`
label=`lsblk -o mountpoint,label| grep /mnt/usb2|awk '{print $2}'`
frees=`df -m|grep $m1 | awk '{print $4}'`
echo "label#"$label";asize#"$frees

Скрипт разделен специально

sda2u.sh - этот скрипт просто размонтирует флешку после нажатия кнопки

#!/bin/bash
sudo umount /mnt/usb2
echo "label#no usb flash;asize#0"

Хорошо что для размонтирования нужно знать только имя папки, а не устройства

Далее идут кирпичи отвечающие за копирование
sdacopy.sh - по нажатии кнопки, смотрит есть ли флешки, и начинает копировать в новую папку с именем даты начала копирования.

#!/bin/bash
if df -h | grep /mnt/usb1
then
if df -h | grep /mnt/usb2
then
pathnew=`date +"%Y%m%d%H%M%S"`
echo "pathonusb#"$pathnew
sudo mkdir /mnt/usb2/$pathnew
#sudo cp -rf /mnt/usb1/*  /mnt/usb2/$pathnew
sudo rsync -av  --exclude=".\Tra*" /mnt/usb1/* /mnt/usb2/$pathnew
fi
fi

sdaspeed.sh - чудесный скрипт, рисует прогресс копирования. Следит за изменением размера занятого места на флешке, знает размер данных которые надо скопировать. Но все раво это только для визуализации

#!/bin/bash

fsize=`du -s --exclude='.Trash*' /mnt/usb1| awk '{print $1}'`
frees=`df -k | grep /mnt/usb2 | awk '{print $3}'`
fres=0
ndelay=0
echo $fres
while [ $fres -lt 100 ]; do
fresold=$fres
frees2=`df -k | grep /mnt/usb2 | awk '{print $3}'`
fres=`echo "(100*($frees2-$frees))/$fsize" | bc`

if [ $fres -gt 100 ]
then
fres=100
fi

if [ $fres -eq $fresold ]
then
let ndelay++
if [ $ndelay -gt 500 ]
then	
fres=100
fi
else
ndelay=0	
fi

echo $fres
done

И скрипт sda2sup.sh который обновляет совобдное место на второй флешке, запускает вместе с sdaspeed.sh

#!/bin/bash
m1=`df -h | grep /mnt/usb2|awk '{print $1}'`
frees=`df -m|grep $m1 | awk '{print $4}'`
echo "asize#"$frees

И совсем последний скрипт sdatemp.sh с одной команды, для показа температуры малинки

#!/bin/bash
vcgencmd measure_temp

Как работает дубликатор флешок
Заходим пока по адрессу http://111.222.33.44:1880/ui/

1. Вставили первую флешку в один из синих разъемов - нажали в USB OUT кнопку MOUNT - она сработает не моментально, подождите. И не надо жать сразу после втыкания флешки, она не сразу в системе появляется
2. Вставили вторую флешку в один из синих разъемов - нажали в USB IN кнопку MOUNT
3. Потом когда все флешки появились нажимаете в COPY кнопку START COPY

И видите такую картинку

Когда дошло до 100% копиравание точно завершено!

Подключаемся к USB дубликатору по Wi-Fi
А все для этого уже есть!

Подключаемся к сети itcooky
Идем по адресу 10.100.10.1:1880/ui
И видим наш интерфейсик, можем копировать:

Уф раз такая веселуха пошла, надо закрыть админку Node-Red паролем!
Ставим
npm install bcryptjs
Идем в
cd /home/pi/.node-red
Генерируем краказябру своего пароля коммандой
node -e "console.log(require('bcryptjs').hashSync(process.argv[1], 8));" your-password-here
И в файле settings.js
vi /home/pi/.node-red/settings.js
находим строки и расскомментируем должно быть вот так, со своей краказяброй вместо пароля

adminAuth: {
    sessionExpiryTime: 86400,
    type: "credentials",
    users: [{
        username: "admin",
        password: "$2a$08$ToLl/u9QXxbIWcP2Xjsul.fTgujmnDjVLAgyOwpxNtIRU7TWr.XBu",
        permissions: "*"
    }]
},

Перезапускаем node-Red
sudo service nodered restart
И заходим под своим паролем, логин admin


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *