» »

Zaznavanje Arduina priklopljenega preko USB v Linuxu

Zaznavanje Arduina priklopljenega preko USB v Linuxu

poweroff ::

Imam dva Arduinota, ki ju na RaspberrPi povezujem preko USB kabla. Rad bi, da bi takoj, ko Arduino povežem preko USB, Raspberry to zaznal in mi nekam zabeležil, da je naprava povezana. Ko pa kabel potegnem ven, pa da spet to zazna in zabeleži event.

Načeloma lahko periodično poganjam lsusb, ampak to nekako ni to. Opcija je tudi, da poženem udevadm info --name=/dev/ttyUSB1 in dobim info o priključenih napravi. Torej tukaj bi rad, da ko vtaknem v računalnik USB z Arduinotom, mi v neko datoteko (npr. TXT) napiše da je naprava povezana (to datoteko lahko potem pokažem na webu), hkrati pa sproži še nek ukaz recimo python zazeni.py /dev/ttyUSB0

Ko pa naprava izgine, pa spet: v datoteki izbriše napravo ter recimo ubije tisti proces.

Druga stvar je pa, da bi rad, da mi loči različne Arduinote (npr. tole je prva naprava, tole druga, itd.). Tukaj vidim problem, ker imajo v lsusb izpisu vsi isti ID...
sudo poweroff

dreta ::

Pomoje najlazje z expect.

specing ::

udev RUN=... v rules.d

poweroff ::

Hmm, udevadm info -n /dev/ttyUSB0 mi pravi:

N: ttyUSB0
...
E: ID_MODEL_ID=7523
...
E: ID_SERIAL=1a86_USB2.0-SerialE: ID_TYPE=generic
...
E: ID_VENDOR=1a86

Torej v /etc/udev/rules.d dam 90-bluesensor.rules z naslednjo vsebino:

KERNEL=="ttyUSB?", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{serial}=="1a86_USB2.0-Serial", SYMLINK+="BlueSensor0", RUN+="python /home/pi/sensordata/bluesensor-server.py 0"

Potem pa še:
udevadm control --reload-rules

Ampak se ne zgodi nič... any idea?
sudo poweroff

Brane22 ::

Ne morem it zdaj v detajle, ampak:

- glede odziva na nastanek naprave je načeloma več poti. Lahko recimo poslušaš na dbusu dogodke ( mislim da to počne udisks za flashe, kartice itd) in ragiraš na dodajanje prave naprave. Lahko za to izkoristiš udev( ki je del systemd na tozadevnih sistemih) in v pravilu zapišeš,d a ob dodajanju/odvzemu deviceov z določenimi lastnostmi pač požene tvoj programček. Lhako verjetno tudi s kakim notify mehanizmomo nadzoruješ mapo, kjer naj bi bili ti dodani/brisani in jo ob spremembah poskeniraš itd. Nekako najbolj ustrezen se zdi udev mehanizem.

- enako je z imeni naprav. Ponastavi rulse in ti jih bo stvar lahko poimenovala kot želiš, vejretno tudi na osnovi serijske številke ali česa petega.

BTW: udevadm monitor

Nato poglej kaj se dogaja ob od/všteku.
On a journey of life I chose a psycho path...

Zgodovina sprememb…

  • spremenilo: Brane22 ()

Brane22 ::

PS: Jebo vas pajton. A ti tud avtomehankar auspuh zaflika s hanzaplastom ?
On a journey of life I chose a psycho path...

poweroff ::

Hehe, kaj imate vsi proti Pitonu? A grize? 8-) (no, malo heca mora biti)

Anyway:
udevadm monitor

Pravi tole:

monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
KERNEL - the kernel uevent

KERNEL[4391.724038] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2 (usb)
KERNEL[4391.725298] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0 (usb)
KERNEL[4391.726029] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0 (usb-serial)
KERNEL[4391.730896] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0 (tty)
UDEV [4391.744234] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2 (usb)
UDEV [4392.772422] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0 (usb)
UDEV [4392.775924] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0 (usb-serial)
UDEV [4392.794287] add /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0 (tty)
sudo poweroff

Brane22 ::

udevadm info --attribute-walk /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0

Bi ti moral nekako zlistat vse lastnosti naprave, kot tudi njenih staršev, na osnovi katerih potem lahko trigeriraš svoj rule.

Z njim potem lahko določiš mapo, imena naprav, kako naj se generirajo, eventualno štartaš kak programček itd.
On a journey of life I chose a psycho path...

Brane22 ::

Pa glede programov, ki se izvajajo v rulih - naj bi bili hipni.

To ni plac za simulacije črnih lukenj. Tak programček blokira cel udev mehanizem, dokler ne zaključi.

Če je potrebno kaj bistvenega procesiranja, lahko uvedeš v rule,d a stvar naredi recimo kak link v neki mapi, ki jo nadzoruješ z notifyjem in reagiraš ustrezno.

Ali pa greš glede tega prek dbus protokola.
On a journey of life I chose a psycho path...

poweroff ::

Torej:
udevadm info --attribute-walk /devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2/1-1.2:1.0/ttyUSB0/tty/ttyUSB0
Unknown device, absolute path in /dev/ or /sys expected.

Aha, glede programa, ki se izvede v ruleu je pa stvar v tem, da je to program, ki začne brati podatke iz senzorja in jih pošilja na web socket... Skratka, idej aje, da senzor priklopim začne samodejno pošiljati podatke na web.
sudo poweroff

Brane22 ::

OK, torej mu daj namesto dolge poti ime naprave v /dev
On a journey of life I chose a psycho path...

poweroff ::

Huh, to pa izpiše vraga in pol:
https://pastebin.com/7ucXeVXv
sudo poweroff

poweroff ::

Hmm, po restartu mi naredi ustrezno napravo:

ls /dev/BlueSensor0
/dev/BlueSensor0

Lahko tudi berem iz nje in podatki so pravi.

Ne požene pa skripte (zaradi moje napake)

Syslog namreč pravi:

un 25 21:59:50 raspberrypi kernel: [ 865.105625] ch341 1-1.3:1.0: ch341-uart converter detected
Jun 25 21:59:50 raspberrypi kernel: [ 865.109897] usb 1-1.3: ch341-uart converter now attached to ttyUSB0
Jun 25 21:59:50 raspberrypi systemd-udevd[17562]: failed to execute '/lib/udev/mtp-probe' 'mtp-probe /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.3 1 6': No such file or directory
Jun 25 21:59:51 raspberrypi systemd-udevd[17572]: failed to execute '/lib/udev/python' 'python /home/pi/sensorgraph/bluesensor-server.py 0': No such file or directory


V /etc/udev/rules.d/90-bluesensor.rules sem namreč imel napačno pot do Pitona:

KERNEL=="ttyUSB?", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", ATTRS{serial}=="1a86_USB2.0-Serial", SYMLINK+="BlueSensor0", RUN+="python /home/pi/sensordata/bluesensor-server.py 0"

No, zdaj sem to popravil in sicer takole:

KERNEL=="ttyUSB?", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="BlueSensor?", RUN+="/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py ?"

Ampak seveda ne dela... problem je naslednji:

Ko vključim prvo napravo, dobi ID /dev/ttyUSB0
Zdaj bi moral udev narediti /dev/BlueSensor0 in pognati skripto "/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 0"

Ko pa vključim drugo napravo, ki dobi ID /dev/ttyUSB1, bi moral udev narediti /dev/BlueSensor1 in pognati skripto "/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 1"

Kako bi pa to dosegel?
sudo poweroff

poweroff ::

OK, napredek.

V /etc/udev/rules.d/90-bluesensor.rules sem dal tole:

KERNEL=="ttyUSB0", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="BlueSensor0", RUN+="/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 0"
KERNEL=="ttyUSB1", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="BlueSensor1", RUN+="/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 1"


Zdaj mi naredi ustrezne symlinke /dev/BlueSenzor0, 1,... ko vklapljam in izklapljam naprave.

Recimo dam notri napravo 1 in naredi /dev/BlueSenzor0. Nato napravo 2 in naredi /dev/BlueSenzor1. Nato napravo 1 dam ven, ostane samo /dev/BlueSenzor1. Nato še to napravo ven, izginejo vsi, nato to isto napravo nazaj notri in spet dobim /dev/BlueSenzor0.

To je sicer načeloma OK, bi pa rad, da bi isto napravo lahko vedno dobil z istim imenom... ampak očitno to ne bo šlo, ker imajo naprave isti ID.

Vseeno je pa problem, da mi ne zažene RUN+ ukaza.

Syslog mi javi tole:

Vtaknem napravo notri:
Jun 25 22:17:30 raspberrypi kernel: [ 376.007502] usb 1-1.5: new full-speed USB device number 7 using dwc_otg
Jun 25 22:17:30 raspberrypi kernel: [ 376.140665] usb 1-1.5: New USB device found, idVendor=1a86, idProduct=7523
Jun 25 22:17:30 raspberrypi kernel: [ 376.140680] usb 1-1.5: New USB device strings: Mfr=0, Product=2, SerialNumber=0
Jun 25 22:17:30 raspberrypi kernel: [ 376.140688] usb 1-1.5: Product: USB2.0-Serial
Jun 25 22:17:30 raspberrypi kernel: [ 376.143048] ch341 1-1.5:1.0: ch341-uart converter detected
Jun 25 22:17:30 raspberrypi kernel: [ 376.147280] usb 1-1.5: ch341-uart converter now attached to ttyUSB0
Jun 25 22:17:30 raspberrypi systemd-udevd[1203]: failed to execute '/lib/udev/mtp-probe' 'mtp-probe /sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.5 1 7': No such file or directory

Čez nekaj časa se zgodi timeout:

Jun 25 22:18:02 raspberrypi systemd-udevd[1202]: timeout '/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 0'
Jun 25 22:18:02 raspberrypi rsyslogd-2007: action 'action 17' suspended, next retry is Sun Jun 25 22:18:32 2017 [try http://www.rsyslog.com/e/2007 ]
Jun 25 22:18:03 raspberrypi systemd-udevd[1202]: timeout: killing '/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 0' [1213]
Jun 25 22:18:03 raspberrypi systemd-udevd[1202]: '/usr/bin/python /home/pi/sensorgraph/bluesensor-server.py 0' [1213] terminated by signal 9 (Killed)
sudo poweroff

poweroff ::

Huh, rešil.

Udev mi naredi napravo /dev/BlueSensorX.

Supervisor mi pa poganja proces za branje iz te naprave. Če naprave ni, proces exitne, ampak ga Supervisor restarta.
sudo poweroff

AndrejO ::

Ahem. udev ti je ukaz čisto lepo zagnal ... in nato čakal, da se bo ukaz izvršil do konca.

To mi smrdi na to, da pričakuješ, da bo bluesensor-server.py stregel v ospredju. No-go z udev, ker so to programi, ki naj bi nekaj zagnali in nato zaključili s svojim izvajanjem. Spravi zadevo, da bo delo nadaljevala v ozadju ali pa kako drugače sporoči strežniku, da naj začne opravljati svoje delo.

poweroff ::

Hočeš reči, da bi lahko naredil Supervisor vnos, ki bi ga zagnal udev?

Recimo nekaj v stilu:
[program:bluesensor0]
command = python /home/pi/sensorgraph/bluesensor-server.py 0
autostart=false
autorestart=true

Se pravi autostart je OFF, se pa zadeva restarta če gre kaj narobe...
udev bi potem rekel: 2sudo supervisorctl start bluesensor0"

Edino potem bi moral zagotoviti, da ko udev zazna, da naprave ni več, da reče "sudo supervisorctl stop bluesensor0"... to je mogoče?
sudo poweroff

AndrejO ::

Sicer nisem mislil točno tega, ampak s stisnjenimi zobmi (systemd namreč preziram), bom rekel "da".

Poglej man systemd.device in notri poišči TAG+=systemd in SYSTEMD_WANTS.

v udevd.conf boš pa potreboval 'blah, blah, blah, TAG+="systemd", ENV{SYSTEMD_WANTS}="device-attach.service"'

Mehanizem delovanja je potem sledeč:
- udevd: zazna napravo in naredi link, ipd ...
- systemd: zazna, da je udevd dodal napravo.
- systemd: ker ima naprava TAG systemd, bo systemd naredil .device enoto/datoteko za to napravo.
- systemd: ker ima naprava SYSTEMD_WANTS, bo systemd v novonastalo enoto vtaknil Wants=...
- systemd: ker ima novonastala enota Wants=... preden se aktivira, bo systemd aktiviral, kar je tam našteto (torej to, kar si vpisal, da naj se zažene).

E voila.

V obratnem vrstnem redu pa:
- udevd: zazna umik naprave.
- systemd: zazna, da je udevd umaknil napravo in zato ustavi/deaktivira .device enoto.
- systemd: ko je enota ustavljena, systemd ustavi tudi ostale enote, ki več niso zahtevane.

V /etc/systemd/system/mojeservis.service pa vtakneš nekaj minimalističnega:
[Unit]
Description=Moj super-duper Python servis.

[Service]
ExecStart=python /home/pi/sensorgraph/bluesensor-server.py 0
WorkingDirectory=/home/pi/sensorgraph
StandardOutput=syslog
StandardError=syslog
User=foo
Group=bar

Zgodovina sprememb…

  • spremenil: AndrejO ()

BigWhale ::

Jaz bi najbrz kar svoj daemon napisal.

Najbolj glupa varianta.
while True:
    try:
        open('/dev/ttyUSB0')
        read_stuff()
    except IOError:
       # print('Not ready')
       pass
    time.sleep(1)


Imas pa potem se inotify in podobne reci, kjer lahko poganjas funkcije, ko se nek event zgodi.

Vpletanje udev in supervisorja se meni zdi kompliciranje. Saj udev ze naredi svoje, ko ustvari USB device.

Na Arduino strani pa naredi nekaj v tem stilu:
Serial.print("###ID: Dnevna soba$$$");
Serial.print(sensor_data);

Naj naprava sama pove kaj je zaena naprava in kaksne podatke posilja, potem pa na RPi to ustrezno obdelas.

Zgodovina sprememb…

  • spremenil: BigWhale ()

poweroff ::

Ja, v bistvu bi lahko naredil tudi tako, da on bere podatke iz vseh USB naprav in preverja ali je pravi Vendor ID... oziroma verjetno bi bilo najbolje, da kar prebere podatke in če ugotovi, da je dobil valid JSON, ki vsebuje tudi opis naprave, podatke pošlje na websocket... sicer pa na websocket pošilja "device not ready" ali nekaj takega...

V tem primeru ne bi rabil udeva, Supervisor pa vseeno.
sudo poweroff

BigWhale ::

Supervisor imas pac zato, da skrbi, da tvoj service laufa. To je cist ok. Ampak udev ze v startu poskrbi, da nastane USB device, k vtaknes not napravo.

mojster_joni ::

a dela od tud out of the box


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

Programiranje Baofeng BF-V9

Oddelek: Elektrotehnika in elektronika
183919 (2435) hipertija
»

Arduino informacije na spletno stran

Oddelek: Programiranje
5812 (734) d4vid
»

Linux/KDE - shell scripta

Oddelek: Programiranje
13933 (778) Icematxyz
»

Ubuntu

Oddelek: Operacijski sistemi
302972 (321) Tear_DR0P
»

c++, linux in hardware

Oddelek: Programiranje
61007 (904) CCfly

Več podobnih tem