2017-01-10 4 views
1

Я использую жемчужину WiringPi. Этот блок кода работает, как ожидалось:Невозможно запустить метод несколько раз

pinNumber = 7 
io = WiringPi::GPIO.new do |gpio| 
    gpio.pin_mode(pinNumber, WiringPi::INPUT) 
end 

pin_state = io.digital_read(pinNumber) 
return pin_state 

Однако, когда я прилагаю это метод, так что я могу сделать вызов, используя Sinatra, я получаю следующее сообщение об ошибке при попытке обновить:

wiringPiSetup *: Вы должны вызывать это только один раз для запуска программы. Это фатальная ошибка. Исправьте свой код.

Зачем это нужно работать только один раз, и какое наилучшее решение? В конечном итоге pin_state нужно извлекать каждый раз, когда я перехожу к корневому URL.

Вот полный код:

require 'wiringpi' 
require 'sinatra' 

def getstate() 
    pinNumber = 7 
    io = WiringPi::GPIO.new do |gpio| 
     gpio.pin_mode(pinNumber, WiringPi::INPUT) 
    end  

    pin_state = io.digital_read(pinNumber) 
    return pin_state 
end 

get '/' do 
    getstate() 
end 

ответ

1
pinNumber = 7 

def io 
    @io ||= begin 
     WiringPi::GPIO.new do |gpio| 
      gpio.pin_mode(pinNumber, WiringPi::INPUT) 
     end 
    end 
end 

def getstate() 
    pin_state = io.digital_read(pinNumber) 
    return pin_state 
end 

get '/' do 
    getstate() end 

Инициализировать API раз, когда ваш запуск приложения (за пределы метода GetState()). Вы инициализируете API несколько раз, таким образом, ошибку.

+0

Спасибо, но, к сожалению, когда я двигаюсь, что часть кода вне метода, я получаю «неопределенная локальная переменная или метод' ИО»для #», когда я перейти к URL в первый раз. –

+0

@AaronThomas вам нужно кэшировать объект 'io' вне метода. Инициализируйте объект и сохраните его в переменной, а затем используйте переменную внутри метода getstate. Переместите часть, находящуюся в блоке 'do .. end', в тело метода getstate. – zetetic

+0

@zetetic Я не буду следовать - не могли бы вы привести пример того, что вы имеете в виду? –

2

После создания вашего экземпляра GPIO вы можете совершать повторные вызовы, чтобы считывать с него контакты. Однако ваш код создает новый экземпляр для каждого вызова.

require 'wiringpi' 
require 'sinatra/base' 

class MyApp < Sinatra::Base 
    InputPin = 7 

    IO = WiringPi::GPIO.new do |gpio| 
    gpio.pin_mode(InputPin, WiringPi::INPUT) 
    end  

    def get_state(pin_number = MyApp::InputPin) 
    MyApp::IO.digital_read(pin_number) 
    end 

    get '/' do 
    get_state 
    end 
end 
+0

Это демонстрирует хорошее использование идиом Ruby. Постоянное значение InputPin реализовано как ... константа! – zetetic

+0

Выполнение этого дает мне ошибку 404, даже если я заменил 'get_state' на« hello world ». возможно, какой-то другой шаблон? –

+0

@AaronThomas Вам нужно использовать 'sinatra/base' для модульного приложения вместо' sinatra', который предназначен для приложений верхнего уровня. Кроме того, вам может потребоваться настроить способ доступа к методу 'get_state' с этим в зависимости от области действия. Синатра делает несколько прыжков с обручем, что становится запутанным. Если вы сомневаетесь, [проверьте документы] (http://www.sinatrarb.com/intro.html). – coreyward