Dokumentace k RE8USB je zde http://www.selfcontrol.cz/navod_re8usb.htm
Že počítáč USB zařízení vidí, otestujeme pomocí
lsusb
Přidám uživatele do skupiny dialout, aby měl přístup k /dev/ttyUSB0 a skript tak nemusel běžet jako root.
adduser xsouku04 dialout
instalace ruby a potřebných knihoven pro ruby
aptitude install ruby aptitude install ruby-dev ruby-mkrf gem install serialport
#!/usr/bin/ruby #encoding: utf-8 require 'serialport' # Příklad ovládání RE8USB $port= SerialPort.new("/dev/ttyUSB0", 9600, 8, 1, SerialPort::NONE) $port.read_timeout=5000 # pokud nám nic nepošlou, čekáme maximálně 5 vteřin # vyhnu se tak nekonečnému "zaseknutí" programu pokud je někde chyba, nebo pokud # zařízení žádné události prostě neposílá. # Umožní mi to v mezičase změnit stav relátka - pokud by bylo třeba # Nastavení níže nebyl potřeba, ale jiné podobné aplikace jej používají, nechávám si jej tedy # v poznámce. #$port.sync = true def prectiOdpoved() buf="" begin precteny_znak=$port.getc if precteny_znak!=nil then buf+=precteny_znak end end while precteny_znak!=nil and precteny_znak!="*" # odpovědi končí znakem *, nil znamená, že došlo k timeoutu (něco je špatně) return buf end # poznámka pro Rubysty (nic důležitého): # Pokud bych nechtěl používat globální proměnou $port, mohl bych definovat funkci následovně: #x = Proc.new do #end #x.call # v tomto případě by byly uvnitř funkce přístupné i neglobální proměnné. $port.write("RESET=Ys") # chceme informaci o sepnutí i rozepnutí kontaktu puts prectiOdpoved() $port.write("RUN=1s") # chceme zasílat informace o změnách puts prectiOdpoved() while true do jaky_vstup= $port.getc if jaky_vstup!=nil # nil znamená, že RE8USB nic neposlalo a uplatnil se timeout if jaky_vstup>="1" and jaky_vstup<="8" then puts "vstup #{jaky_vstup} sepnut" $port.write("R#{jaky_vstup}=1s") # cvaknu relátkem a rozsvítím diodu elsif jaky_vstup>="A" and jaky_vstup<="H" puts "vstup #{jaky_vstup.getbyte(0)-64} rozpojen" # znak A má v ASCII číslo 64, tedy když odečteme 64 máme z ABCDEFGH obět čísla 12345678 $port.write("R#{jaky_vstup.getbyte(0)-64}=0s") # cvaknu relátkem a zhasnu diodu end end end #Možné logování: #puts Time.new.strftime("%Y-%m-%d %H:%M:%S")+" posláno:"+co_poslat
Příklad výstupu
ruby serialRead.rb L=Y* running* vstup 1 sepnut vstup 1 rozpojen vstup 3 sepnut vstup 3 rozpojen vstup 2 sepnut vstup 2 rozpojen
Podle obrázku 2a) jsem drátkem propojil vstup IN1 s GND a uvolnil. Poté to stejné IN3 a IN2. Program průběžně vypisoval informace výše a též rozsvítil/zhasnul ledku - vždy při změně stavu bylo slyšet cvaknutí relátka.
Další info na fóru http://forum.odorik.cz/viewtopic.php?f=33&t=3122&start=20#p24768
gem install sinatra
#!/usr/bin/ruby #encoding: utf-8 require 'sinatra' require 'serialport' # Příklad čtení stavu vstupů z USB30IN $port= SerialPort.new("/dev/ttyUSB0", 9600, 8, 1, SerialPort::NONE) $port.read_timeout=5000 # pokud nám nic nepošlou, čekáme maximálně 5 vteřin set :bind, '0.0.0.0' set :port, 80 def prectiOdpoved() buf="" begin precteny_znak=$port.getc if precteny_znak!=nil then buf+=precteny_znak end end while precteny_znak!=nil and precteny_znak!="*" $port.getc # cr $port.getc # lf # odpovědi končí znakem *, nil znamená, že došlo k timeoutu (něco je špatně) return buf end get '/' do # 'Hello world!' $port.write("?") # chceme informaci o sepnutí i rozepnutí kontaktu odpoved=prectiOdpoved() odpoved[0]=odpoved[31]="" vratime="<H2>Seznam rozpojených jističů</H2>" (0..30).each do |i| if odpoved[i]=="0" vratime+="#{i+1}," end end vratime[vratime.length-1]="" vratime end
Zálohovaný zdroj http://www.t-led.cz/ups-zdroj-12v-60w-s-nabijenim
Navíc si pak mohu i levně svítit. http://www.aliexpress.com/item/Tanbaby-LED-Strip-light-5630-DC12V-5M-300led-flexible-5730-bar-light-high-brightness-Non-waterproof/32429656371.html
Převést napětí z 12 V na 5 lze snadno a levně. http://www.aliexpress.com/item/DC-DC-Buck-Converter-7V-24V-12v-to-5V-3A-usb-output-Voltage-Step-down-Module/874433124.html Pokud napájíme něco jiného, co chce 5 V (třeba switch) lze použít tento adaptér. http://www.aliexpress.com/item/Waterproof-DC-Converter-12V-Step-Down-to-5V-3A-15W-Power-Supply-Module-Free-Shipping/32270465862.html
Pohybové čidlo - http://www.gme.cz/pohybove-cidlo-ls-818-3-p754-310
Siréna - http://www.gme.cz/sirenka-kpe-1600-p640-007
Čidlo na dveře a okna - http://www.aliexpress.com/item/Free-Shipping-5set-White-Wired-Spring-Recessed-Door-Window-Contact-Security-Magnetic-Reed-Switch-Alarm/32246347157.html
Přidavné relé? - http://www.aliexpress.com/item/Freeshipping-New-5V-2-Channel-Relay-Module-Shield-for-Arduino/1726504761.html
web.rb
#!/usr/bin/ruby #encoding: utf-8 require 'sinatra' set :bind, '0.0.0.0' set :port, 80 use Rack::Auth::Basic, "Restricted Area" do |username, password| username == 'prihl_jmeno' and password == 'heslo' end load '/root/selfcontrol/rele_definice.rb' get '/' do vratime="<H2>Vítejte</H2>\n" if lokalni_ip=/^192\.168\.2/.match(request.ip) vratime << "Přistupujete z lokální sítě ip" else vratime << "Přistupujete se vzdálené ip" end vratime<<" #{request.ip}<br>\n" # obrázky z kamer vratime<<" <img src='a.jpg'> <br>\n" vratime<<" <img src='b.jpg'> <br>\n" vratime<<" <img src='usb.jpg'> <br>\n" vratime<<"<form action='/' method='POST'>" vratime<<"<table><tr><th>jméno</th><th>stav</th><th>čas poslední změny</th></tr>\n" (Dir["/root/selfcontrol/stav/*"]+Dir["/root/selfcontrol/rele_aktualni_stav/*"]).each{ |f| if File.file?(f) and File.extname(f)!=".log" then vratime << "<tr><td>#{File.basename(f)}</td><td>#{stav=File.read(f)}</td> <td>#{File.mtime(f).strftime('%Y-%m-%d %H:%M:%S')} </td>" if f.include?("rele_aktualni_stav") then informace_o_rele=Rele_hash[File.basename(f)] opacny_stav=cislo_rele="" # jinak by promenne neprizili vynoreni z cyklu informace_o_rele.each do |key,value| if key==:cislo cislo_rele=value elsif key!=stav opacny_stav=key end end vratime << " <td> <button type='submit' name='operace' value='#{File.basename(f)}_#{opacny_stav}'>#{opacny_stav}</button> </td> </tr>\n" else vratime << "</tr>\n" end end } vratime<<"</table>\n" # vratime[vratime.length-1]="" # vratime end get '/a.jpg' do # d-link require 'open-uri' open('http://192.168.2.194/image.jpg').read end get '/b.jpg' do # edimax require 'open-uri' open('http://192.168.2.150/snapshot.jpg', :http_basic_authentication=>['admin','1234']).read end get '/usb.jpg' do `fswebcam -r 640x480 /root/selfcontrol/image.jpg` send_file "/root/selfcontrol/image.jpg" end get '/nagios' do "0,vsechno OK" # vracíme stavy 0 OK, 1 - warnink, 2 - critical , text bez háčků end post "/" do rele_cislo,rele_novy_stav=params[:operace].split('_') `/root/selfcontrol/rele.rb #{rele_cislo} #{rele_novy_stav}` sleep(0.75) redirect to('/') end
rele_definice.rb
#!/usr/bin/ruby #encoding: utf-8 Rele_hash = {"svetla"=>{:cislo=>1,"sviti"=>1,"nesviti"=>0}, "alarm"=>{:cislo=>2,"houka"=>1, "nehouka"=>0}, "zakaznici"=>{:cislo=>3,"on"=>0,"off"=> 1}, "obsluha"=>{:cislo=>4,"on"=>0,"off"=> 1}, "stoly"=>{:cislo=>5,"on"=>0,"off"=> 1}, "boiler"=>{:cislo=>6,"on"=>1,"off"=> 0}, "kuchyn"=>{:cislo=>7,"on"=>0,"off"=> 1}, "reklama"=>{:cislo=>8,"sviti"=>0,"nesviti"=>1}}
Jak povolit https v sinatře. - https://gist.github.com/TakahikoKawasaki/40ef0ab011b0a467bedf#file-sinatra-ssl-rb
Jak udělat aby webbrick poslouchal na všech adresách? :Host ⇒ '0.0.0.0' http://www.parorrey.com/blog/webmaster-tasks/configuring-webrick-to-serve-redmine-over-ssl-using-openssl-certificate/
https://github.com/plamoni/SiriProxy/issues/41 - aptitude install libssl-dev před gem install thin rele.rb
#!/usr/bin/ruby #encoding: utf-8 LOG_DIR="/root/selfcontrol/rele_aktualni_stav/" LOG_FILE="#{LOG_DIR}rele.log" require 'serialport' # Příklad ovládání RE8USB $port= SerialPort.new("/dev/ttyUSB0", 9600, 8, 1, SerialPort::NONE) $port.read_timeout=5000 # pokud nám nic nepošlou, čekáme maximálně 5 vteřin # vyhnu se tak nekonečnému "zaseknutí" programu pokud je někde chyba, nebo pokud # zařízení žádné události prostě neposílá. # Umožní mi to v mezičase změnit stav relátka - pokud by bylo třeba # Nastavení níže nebyl potřeba, ale jiné podobné aplikace jej používají, nechávám si jej tedy # v poznámce. #$port.sync = true def prectiOdpoved() buf="" begin precteny_znak=$port.getc if precteny_znak!=nil then buf+=precteny_znak end end while precteny_znak!=nil and precteny_znak!="*" # odpovědi končí znakem *, nil znamená, že došlo k timeoutu (něco je špatně) return buf end # poznámka pro Rubysty (nic důležitého): # Pokud bych nechtěl používat globální proměnou $port, mohl bych definovat funkci následovně: #x = Proc.new do #end #x.call # v tomto případě by byly uvnitř funkce přístupné i neglobální proměnné. def log(co) puts co File.open(LOG_FILE, 'a') { |file| file.puts(co) } end load '/root/selfcontrol/rele_definice.rb' rele_jmeno=ARGV[0] rele_jmeno_noveho_stavu=ARGV[1] if Rele_hash[rele_jmeno].nil? # chybné jméno relé log(Time.new.strftime("%Y-%m-%d %H:%M:%S")+" Nenalezeno jméno relé \"#{rele_jmeno}\". Očekávaná jména jsou: #{Rele_hash.keys}") exit else rele_cislo=Rele_hash[rele_jmeno][:cislo] end rele_novy_stav= Rele_hash[rele_jmeno][rele_jmeno_noveho_stavu] if rele_novy_stav.nil? log(Time.new.strftime("%Y-%m-%d %H:%M:%S")+" Nenalezeno jméno nového stavu v hashi rele_jmeno:#{rele_jmeno} rele_jmeno_noveho_stavu:#{rele_jmeno_noveho_stavu} očekávané stavy jsou: #{Rele_hash[rele_jmeno]}") exit end co_poslat="R#{rele_cislo}=#{rele_novy_stav}s" $port.write(co_poslat) # cvaknu relátkem File.open("#{LOG_DIR}#{rele_jmeno}", 'w') { |file| file.write(rele_jmeno_noveho_stavu) } log(Time.new.strftime("%Y-%m-%d %H:%M:%S")+" #{rele_jmeno} #{rele_jmeno_noveho_stavu} posláno: #{co_poslat} ")
cti_stav.rb
#!/usr/bin/ruby #encoding: utf-8 LOG_DIR="/root/selfcontrol/stav/" LOG_FILE="#{LOG_DIR}stav.log" require 'serialport' # Příklad ovládání RE8USB $port= SerialPort.new("/dev/ttyUSB0", 9600, 8, 1, SerialPort::NONE) $port.read_timeout=5000 # pokud nám nic nepošlou, čekáme maximálně 5 vteřin # vyhnu se tak nekonečnému "zaseknutí" programu pokud je někde chyba, nebo pokud # zařízení žádné události prostě neposílá. # Umožní mi to v mezičase změnit stav relátka - pokud by bylo třeba # Nastavení níže nebyl potřeba, ale jiné podobné aplikace jej používají, nechávám si jej tedy # v poznámce. #$port.sync = true def log(co) puts co File.open(LOG_FILE, 'a') { |file| file.puts(co) } end def prectiOdpoved() buf="" begin precteny_znak=$port.getc if precteny_znak!=nil then buf+=precteny_znak end end while precteny_znak!=nil and precteny_znak!="*" # odpovědi končí znakem *, nil znamená, že došlo k timeoutu (něco je špatně) return buf end # poznámka pro Rubysty (nic důležitého): # Pokud bych nechtěl používat globální proměnou $port, mohl bych definovat funkci následovně: #x = Proc.new do #end #x.call # v tomto případě by byly uvnitř funkce přístupné i neglobální proměnné. stav_hash={"3"=>["PIR_stoly","ok"], "C"=>["PIR_stoly","POHYB"], "7"=>["PIR_vstup","ok"], "G"=>["PIR_vstup","POHYB"], "1"=>["DVERE_mezi","zavreno"], "A"=>["DVERE_mezi","otevreno"], "2"=>["OKNO","zavreno"], "B"=>["OKNO","otevreno"], "6"=>["DVERE_vstup","zavreno"], "F"=>["DVERE_vstup","otevreno"], } $port.write("RESET=Ys") # chceme informaci o sepnutí i rozepnutí kontaktu puts prectiOdpoved() $port.write("RUN=1s") # chceme zasílat informace o změnách puts prectiOdpoved() while true do jaky_vstup= $port.getc if jaky_vstup!=nil # nil znamená, že RE8USB nic neposlalo a uplatnil se timeout if ! stav_hash[jaky_vstup].nil? File.open("#{LOG_DIR}#{stav_hash[jaky_vstup][0]}", 'w') { |file| file.write(stav_hash[jaky_vstup][1]) } udalost="#{stav_hash[jaky_vstup][0]}>#{stav_hash[jaky_vstup][1]}" else udalost=" popis události v hashi nenalezen " end if jaky_vstup>="1" and jaky_vstup<="8" then log(Time.new.strftime("%Y-%m-%d %H:%M:%S")+" vstup #{jaky_vstup} sepnut #{udalost}") # $port.write("R#{jaky_vstup}=1s") # cvaknu relátkem a rozsvítím diodu elsif jaky_vstup>="A" and jaky_vstup<="H" log(Time.new.strftime("%Y-%m-%d %H:%M:%S")+" vstup #{jaky_vstup.getbyte(0)-64} rozpojen #{udalost} ") # znak A má v ASCII číslo 64, tedy když odečteme 64 máme z ABCDEFGH obět čísla 12345678 # $port.write("R#{jaky_vstup.getbyte(0)-64}=0s") # cvaknu relátkem a zhasnu diodu end end end