Kivy Python — функция обратного вызова с частичным

Я хочу «вытащить» некоторые значения из моего Arduino в kivy на Raspberry, который подключен через беспроводной модуль NRF24. Я использую эту библиотеку с оболочка Python

В чистом Python код работает хорошо, и теперь я хочу интегрировать его в Kivy.

Для этого я сделал две функции внутри zimmerwetter.py:

Один для настройки радиоустройства и возвращает объект радио (должен быть запущен после запуска приложения):

def radiosetup():
    radio = RF24(RPI_BPLUS_GPIO_J8_22, RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ)

    # doing setup stuff...

    return radio

и еще одна функция, которая отправляет запрос на Arduino, который предоставляет некоторые данные об окружающей среде (температура, влажность и т. д.).

def getenviroment(self,radio):

    millis = lambda: int(round(time.time() * 1000))
    # send command
    send_payload = 'getdata'
    # First, stop listening so we can talk.

    radio.stopListening()

    # Take the time, and send it.  This will block until complete
    print 'Now sending length ', len(send_payload), ' ... ',
    radio.write(send_payload[:len(send_payload)])

    a = datetime.datetime.now()

    # Now, continue listening
    radio.startListening()

    # Wait here until we get a response, or timeout
    started_waiting_at = millis()
    timeout = False
    while (not radio.available()) and (not timeout):
        if (millis() - started_waiting_at) > 1000:
            timeout = True

    # Describe the results
    if timeout:
        b = datetime.datetime.now()
        #      print(b - a)
        print 'failed, response timed out.'
    else:
        # Grab the response, compare, and send to debugging spew
        length = radio.getDynamicPayloadSize()
        receive_payload = []
        receive_payload = radio.read(length)

        print 'got response size=', length
        print struct.unpack("bbbbhbbbb", ''.join(chr(c) for c in receive_payload))
        b = datetime.datetime.now()
        print(b - a)
        return receive_payload

Функция getenviroment должна вызываться позже каждые x секунд из приложения kivy, частичная функция используется, как предложено в модуль часов kivy

from zimmerwetter import *

class PyowmApp(App):
    def build(self):
        radio = radiosetup()
        Clock.schedule_interval(partial(getenviroment,radio), 10)

Ошибка:

   File "/home/pi/pyscripts/pyowm/zimmerwetter.py", line 83, in getenviroment
     radio.stopListening()
 AttributeError: 'float' object has no attribute 'stopListening'

Мне интересно, почему возвращается объект с плавающей запятой, когда я печатаю объект радио с помощью help(radio), он возвращает class RF24(Boost.Python.instance) и существует функция stoplistening().


person Triscus    schedule 03.05.2016    source источник


Ответы (2)


Функция, вызываемая Clock.schedule_interval, получит dt в качестве аргумента после тех, что были переданы через partial. Подпись для вашей функции getenviroment(self,radio), поэтому radio будет назначено self, а dt будет назначено radio.

Вместо этого используйте lambda:

Clock.schedule_once(lambda dt: self.getenviroment(radio), 10)
person zeeMonkeez    schedule 03.05.2016
comment
изменение оператора на Clock.schedule_once(lambda dt: getenviroment(radio), 10) и удаление аргумента self из функции тоже работает (функция не объявлена ​​​​в области приложения) - person Triscus; 03.05.2016
comment
@Triscus, в вопросе не указано, где определяется getenviroment, поэтому я предположил, что PyownApp. Замените self правильным экземпляром класса, который имеет getenvironment. Или рассмотрите возможность изменения параметра self. - person zeeMonkeez; 03.05.2016
comment
Функции не были определены внутри класса, только с оператором def. Думаю, мне пора привыкнуть к ООП, спасибо за вдохновение - person Triscus; 03.05.2016
comment
@Triscus, это прекрасно, но в этом случае первый аргумент getenvironment не должен быть self ... - person zeeMonkeez; 03.05.2016

Я обнаружил это сам, изменив оператор расписания на

Clock.schedule_interval(partial(getenviroment,radio=radio), 10)

сделал трюк.

person Triscus    schedule 03.05.2016
comment
Это работает, но не очень ясно: здесь происходит то, что через partial позиционный аргумент, переданный schedule_interval (dt), назначается первому аргументу в getenvironment (self). self в дальнейшем не используется, так что проблем нет. Затем radio назначается по имени с ожидаемым значением. Таким образом, если бы self действительно имело какое-то значение, этот подход не работал бы и приводил к неожиданным результатам/ошибкам. Просто подумал, что я указываю на это… - person zeeMonkeez; 04.05.2016