Jump to content

AutoFactory instance has no_call_method


Recommended Posts

I have been following a devicehive tutorial to make a temperature sensor, everything is working as expected up until making the thing update itself temps and relay them into my client. 

 

The script (raspi_led_thermo.py):

#/usr/bin/env python

# @author astaff
#
# This sample is to demonstrate DeviceHive Python library
# Connect LED to PIN11 of the board and 1-wire sensor to GPIO4 board PIN #7,
# use pins #1 (3v3) or #2 (5v) for power and pin #6 for ground
#
# (C) DataArt Apps, 2012
# Distributed under MIT license
#

import sys
import os
import time
from time import sleep

try :
    import RPi.GPIO as GPIO
except ImportError:
    class FakeGPIO(object):
        OUT = 'OUTPUT BCM.GPIO17'
        BOARD = 'BOARD'
        def __init__(self):
            print 'Fake gpio initialized'
        def setmode(self, value):
            print 'Set mode {0}.'.format(value)
        def setup(self, io, mode):
            print 'Set gpio {0}; Mode: {1};'.format(io, mode)
        def output(self, io, vlaue):
            print 'Set gpio {0}; Value: {1};'.format(io, vlaue)
    GPIO = FakeGPIO()

sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from zope.interface import implements
from twisted.python import log
from twisted.internet import reactor, task

import devicehive
import devicehive.auto


# change it to match your address for 1-wire sensor
_W1_FILENAME='/sys/bus/w1/devices/28-000004bc15aa/w1_slave'
if not os.path.exists(_W1_FILENAME) :
    _W1_FILENAME = '/dev/null'

# Board's pin #11 (GPIO17)
_LED_PIN=11

# API URL (register for free playground at http://beta2.devicehive.com/playground
_API_URL = 'http://nn1269.pg.devicehive.com/api/'

#
# for easier reading, this class holds all registration information for DeviceHive
#
class RasPiConfig(object):
    
    implements(devicehive.interfaces.IDeviceInfo)
    
    @property
    def id(self):
        return '9f33566e-1f8f-11e2-8979-c42c030dd6a5'
    
    @property
    def key(self):
        return 'device-key'
    
    @property
    def name(self):
        return 'Device1'
    
    @property
    def status(self):
        return 'Online'
    
    @property
    def network(self):
        return devicehive.Network(key = 'Netname', name = 'Netname', descr = 'RasPi/Py LED/w1 sample')
    
    @property
    def device_class(self):
        return devicehive.DeviceClass(name = 'Class1', version = '1.0', is_permanent = False)
    
    @property
    def equipment(self):
        return [devicehive.Equipment(name = 'LED', code = 'LED', type = 'Controllable LED'), devicehive.Equipment(name = 'THERMO', code = 'temp', type = 'TempSensor')]

#
# This class handles DeviceHive API calls for our device
#
class RasPiApp(object):
    
    implements(devicehive.interfaces.IProtoHandler)
    
    def __init__(self, led, sensor):
        super(RasPiApp, self).__init__()
        self.connected = False
        self.notifs = []
        self.info = RasPiConfig()
        self.led = led
        self.sensor = sensor
    
    def on_apimeta(self, websocket_server, server_time):
        log.msg('on_apimeta')
    
    def on_connected(self):
        lc = task.LoopingCall(self.sensor.get_temp, self)
        lc.start(1)
        
        log.msg('Connected to devicehive server.')
        self.connected = True
        for onotif in self.notifs :
            self.factory.notify(onotif['notification'], onotif['parameters'], device_id = self.info.id, device_key = self.info.key)
        self.notifs = []
        def on_subscribe(result) :
            self.factory.subscribe(self.info.id, self.info.key)
        def on_failed(reason) :
            log.err('Failed to save device {0}. Reason: {1}.'.format(self.info, reason))
        self.factory.device_save(self.info).addCallbacks(on_subscribe, on_failed)
    
    def on_connection_failed(self, reason) :
        pass
    
    def on_closing_connection(self):
        pass
    
    def on_failure(self, device_id, reason):
        pass
    
    def do_short_command(self, finished, equipment = None, state = 0):
        log.msg('Setting {0} equipment to {1}'.format(equipment, state))
        if equipment == 'LED' :
            if int(state) == 0 :
                self.led.set_off()
            else:
                self.led.set_on()
        # upon completion post the result back
        self.factory.notify('equipment', {'state': state, 'equipment': 'LED'}, device_id = self.info.id, device_key = self.info.key)
        finished.callback(devicehive.CommandResult('Completed'))
    
    def on_command(self, device_id, command, finished):
        # Expecting command as 'UpdateState' and parameters as {"equipment" : "LED", "state" : "0"}
        if command.command == 'UpdateLedState' :
            self.do_short_command(finished,  **command.parameters)
        else :
            finished.errback()
        # end do_command
    
    def notify(self, notif, **params):
        if self.connected :
            self.factory(notif, params, device_id = self.info.id, device_key = self.info.key)
        else :
            self.notifs.append({'notification': notif, 'parameters': params})


#
# Temperature sensor wrapper. Gets temperature readings form file, parses them
# and notifies the services is the difference is greater than a certain threshold
#
class TempSensor(object):
    def __init__(self, file_name):
        self.file_name = file_name
        self.last_temp = 0
        self.last_good_temp = 0
    
    # internal, get temperature readings from device and check CRC
    def _get_temp(self):
        with open(self.file_name) as f:
            content = f.readlines()
            for line in content:
                # sometimes CRC is bad, so we will return last known good temp
                if line.find('crc=')>=0 and line.find('NO')>=0:
                    return self.last_good_temp
                p = line.find('t=')
                if p >= 0:
                    self.last_good_temp = float(line[p+2:])/1000.0
                    return self.last_good_temp
        return 0.0

    # check temperature, if greater than threshold, notify
    def get_temp(self, dev):
        temp = self._get_temp()
        if abs(temp - self.last_temp) > 0.2:
            log.msg('Temperature {0} -> {1}'.format(self.last_temp, temp))
            dev.notify('equipment', temperature = temp, equipment = "temp")
            self.last_temp = temp

#
# Wrapper from LED connected to RasPi
#
class LedDevice(object):
    def __init__(self, pin):
        # We are using board PIN numbering (as opposed to chip's numbers)
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(pin, GPIO.OUT)

    def blink(self, count):
        for i in range(count):
            GPIO.output(_LED_PIN,True)
            sleep(0.2)
            GPIO.output(_LED_PIN,False)
            sleep(0.2)

    def set_on(self):
        GPIO.output(_LED_PIN, True)

    def set_off(self):
        GPIO.output(_LED_PIN, False)

#
# main
#
if __name__ == '__main__' :
    log.startLogging(sys.stdout)
    
    led = LedDevice(_LED_PIN)
    # Blink on start to ensure device is working
    led.blink(3)

    # create temp sensor and queue it to check for temperature in a separate thread
    tempSensor = TempSensor(_W1_FILENAME)
    
    # create a delegate to handle commands
    device = RasPiApp(led, tempSensor)
    led_factory = devicehive.auto.AutoFactory(device)
    reactor.connectDeviceHive(_API_URL, led_factory)   
    
    # off we go!
    reactor.run()

Using my API URL is sends off the data and on changing the temp it should update itself and notify me, this at the minute just records the 1st temp when the log is started and nothing more. The L.E.D on/off works fine as a consolation prize. 

 

 

Before i go through the logs and main errors, i wanted to post the working code of the thermal sensor using commands to manually update/refresh it (just incase any of you were thinking there's a fault with this): 

root@raspberrypi:/home/pi/devicehive/python/examples# cat /sys/bus/w1/devices/28-000004bc15aa/w1_slave 
44 01 4b 46 7f ff 0c 10 a9 : crc=a9 YES
44 01 4b 46 7f ff 0c 10 a9 t=20250
root@raspberrypi:/home/pi/devicehive/python/examples# cat /sys/bus/w1/devices/28-000004bc15aa/w1_slave 
6f 01 4b 46 7f ff 01 10 67 : crc=67 YES
6f 01 4b 46 7f ff 01 10 67 t=22937
root@raspberrypi:/home/pi/devicehive/python/examples# cat /sys/bus/w1/devices/28-000004bc15aa/w1_slave 
85 01 4b 46 7f ff 0b 10 5f : crc=5f YES
85 01 4b 46 7f ff 0b 10 5f t=24312
root@raspberrypi:/home/pi/devicehive/python/examples# 

I was pinching the sensor supplying warmth and reloading the command, which you can see works well like that but not automatically? 

 

t= "temp in binary"

 

 

Now the error im getting when running raspi_led_thermo.py to log temps: 

root@raspberrypi:/home/pi/devicehive/python/examples# sudo python raspi_led_thermo.py 
2013-06-23 13:39:03+0100 [-] Log opened.
2013-06-23 13:39:03+0100 [-] raspi_led_thermo.py:197: exceptions.RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
2013-06-23 13:39:04+0100 [-] Starting factory <devicehive.auto.AutoFactory instance at 0x13ead50>
2013-06-23 13:39:05+0100 [AutoProtocol,client] The call to "/info" api has finished successfully.
2013-06-23 13:39:05+0100 [AutoProtocol,client] on_apimeta
2013-06-23 13:39:05+0100 [AutoProtocol,client] WebSocket protocol has been selected. URL: http://nn1269.pg.devicehive.com:8010/; HOST: nn1269.pg.devicehive.com; PORT: 8010;
2013-06-23 13:39:05+0100 [AutoProtocol,client] Starting factory <devicehive.device.ws.WebSocketFactory instance at 0x17452d8>
2013-06-23 13:39:05+0100 [AutoProtocol,client] Stopping factory <devicehive.auto.AutoFactory instance at 0x13ead50>
2013-06-23 13:39:06+0100 [WebSocketDeviceHiveProtocol,client] Temperature 0 -> 20.187
2013-06-23 13:39:06+0100 [WebSocketDeviceHiveProtocol,client] Connected to devicehive server.
2013-06-23 13:39:06+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "notification/insert", "notification": {"notification": "equipment", "parameters": {"equipment": "temp", "temperature": 20.187}}, "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 1}
2013-06-23 13:39:06+0100 [WebSocketDeviceHiveProtocol,client] device_save <__main__.RasPiConfig object at 0x172ed70>
2013-06-23 13:39:06+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "device/save", "device": {"status": "Online", "name": "Device1", "equipment": [{"code": "LED", "type": "Controllable LED", "name": "LED"}, {"code": "temp", "type": "TempSensor", "name": "THERMO"}], "deviceClass": {"version": "1.0", "is_permanent": false, "name": "Class1"}, "key": "device-key", "network": {"name": "Netname", "key": "Netname", "description": "RasPi/Py LED/w1 sample"}}, "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 2}
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"notification/insert","status":"success","requestId":1,"notification":{"id":65,"timestamp":"2013-06-23T12:39:07.094000"}}.
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"notification/insert","status":"success","requestId":1,"notification":{"id":65,"timestamp":"2013-06-23T12:39:07.094000"}}.
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"device/save","status":"success","requestId":2}.
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"device/save","status":"success","requestId":2}.
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Subscribe device 9f33566e-1f8f-11e2-8979-c42c030dd6a5.
2013-06-23 13:39:07+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "command/subscribe", "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 3}
2013-06-23 13:39:08+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"command/subscribe","status":"success","requestId":3}.
2013-06-23 13:39:08+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"command/subscribe","status":"success","requestId":3}.
2013-06-23 13:39:45+0100 [-] Temperature 20.187 -> 20.437
2013-06-23 13:39:45+0100 [-] Unhandled error in Deferred:
2013-06-23 13:39:45+0100 [-] Unhandled Error
	Traceback (most recent call last):
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1169, in run
	    self.mainLoop()
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1178, in mainLoop
	    self.runUntilCurrent()
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 800, in runUntilCurrent
	    call.func(*call.args, **call.kw)
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/task.py", line 215, in __call__
	    d = defer.maybeDeferred(self.f, *self.a, **self.kw)
	--- <exception caught here> ---
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 134, in maybeDeferred
	    result = f(*args, **kw)
	  File "raspi_led_thermo.py", line 187, in get_temp
	    dev.notify('equipment', temperature = temp, equipment = "temp")
	  File "raspi_led_thermo.py", line 153, in notify
	    self.factory(AutoFactory, notif, params, device_id = self.info.id, device_key = self.info.key)
	exceptions.NameError: global name 'AutoFactory' is not defined
	
^C2013-06-23 13:40:35+0100 [-] Received SIGINT, shutting down.
2013-06-23 13:40:35+0100 [WebSocketDeviceHiveProtocol,client] Stopping factory <devicehive.device.ws.WebSocketFactory instance at 0x17452d8>
2013-06-23 13:40:35+0100 [-] Main loop terminated.
root@raspberrypi:/home/pi/devicehive/python/examples# sudo python raspi_led_thermo.py 
2013-06-23 16:18:52+0100 [-] Log opened.
2013-06-23 16:18:52+0100 [-] raspi_led_thermo.py:197: exceptions.RuntimeWarning: This channel is already in use, continuing anyway.  Use GPIO.setwarnings(False) to disable warnings.
2013-06-23 16:18:54+0100 [-] Starting factory <devicehive.auto.AutoFactory instance at 0xddbd50>
2013-06-23 16:18:54+0100 [AutoProtocol,client] The call to "/info" api has finished successfully.
2013-06-23 16:18:54+0100 [AutoProtocol,client] on_apimeta
2013-06-23 16:18:54+0100 [AutoProtocol,client] WebSocket protocol has been selected. URL: http://nn1269.pg.devicehive.com:8010/; HOST: nn1269.pg.devicehive.com; PORT: 8010;
2013-06-23 16:18:54+0100 [AutoProtocol,client] Starting factory <devicehive.device.ws.WebSocketFactory instance at 0x11342d8>
2013-06-23 16:18:54+0100 [AutoProtocol,client] Stopping factory <devicehive.auto.AutoFactory instance at 0xddbd50>
2013-06-23 16:18:56+0100 [WebSocketDeviceHiveProtocol,client] Temperature 0 -> 20.437
2013-06-23 16:18:56+0100 [WebSocketDeviceHiveProtocol,client] Connected to devicehive server.
2013-06-23 16:18:56+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "notification/insert", "notification": {"notification": "equipment", "parameters": {"equipment": "temp", "temperature": 20.437}}, "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 1}
2013-06-23 16:18:56+0100 [WebSocketDeviceHiveProtocol,client] device_save <__main__.RasPiConfig object at 0x111dd70>
2013-06-23 16:18:56+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "device/save", "device": {"status": "Online", "name": "Device1", "equipment": [{"code": "LED", "type": "Controllable LED", "name": "LED"}, {"code": "temp", "type": "TempSensor", "name": "THERMO"}], "deviceClass": {"version": "1.0", "is_permanent": false, "name": "Class1"}, "key": "device-key", "network": {"name": "Netname", "key": "Netname", "description": "RasPi/Py LED/w1 sample"}}, "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 2}
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"notification/insert","status":"success","requestId":1,"notification":{"id":67,"timestamp":"2013-06-23T15:18:56.722000"}}.
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"notification/insert","status":"success","requestId":1,"notification":{"id":67,"timestamp":"2013-06-23T15:18:56.722000"}}.
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"device/save","status":"success","requestId":2}.
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"device/save","status":"success","requestId":2}.
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Subscribe device 9f33566e-1f8f-11e2-8979-c42c030dd6a5.
2013-06-23 16:18:57+0100 [WebSocketDeviceHiveProtocol,client] Sending websocket text frame. Payload: {"action": "command/subscribe", "deviceKey": "device-key", "deviceId": "9f33566e-1f8f-11e2-8979-c42c030dd6a5", "requestId": 3}
2013-06-23 16:18:58+0100 [WebSocketDeviceHiveProtocol,client] Websocket frame (1) has been received. Frame data: {"action":"command/subscribe","status":"success","requestId":3}.
2013-06-23 16:18:58+0100 [WebSocketDeviceHiveProtocol,client] Websocket message has been received {"action":"command/subscribe","status":"success","requestId":3}.
2013-06-23 16:19:22+0100 [-] Temperature 20.437 -> 20.687
2013-06-23 16:19:22+0100 [-] Unhandled error in Deferred:
2013-06-23 16:19:22+0100 [-] Unhandled Error
	Traceback (most recent call last):
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1169, in run
	    self.mainLoop()
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 1178, in mainLoop
	    self.runUntilCurrent()
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/base.py", line 800, in runUntilCurrent
	    call.func(*call.args, **call.kw)
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/task.py", line 215, in __call__
	    d = defer.maybeDeferred(self.f, *self.a, **self.kw)
	--- <exception caught here> ---
	  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 134, in maybeDeferred
	    result = f(*args, **kw)
	  File "raspi_led_thermo.py", line 187, in get_temp
	    dev.notify('equipment', temperature = temp, equipment = "temp")
	  File "raspi_led_thermo.py", line 153, in notify
	    self.factory(notif, params, device_id = self.info.id, device_key = self.info.key)
	exceptions.AttributeError: AutoFactory instance has no __call__ method

It has no call method. I tried to add AutoFactory to call it in: notify self.factory but then it said that it wasn't defined, couldn't see correctly where to define AutoFactory so i revoked those changes. I need some help completing this as im no expert i just want a temp sensor for my fish tank. Could somebody tell me how to change this file so it works right please? 

 

If i have missed something that might help, please let me know. I have tried to include what i think it needed to resolve the issue. 

Link to comment
Share on other sites

I found the following URL: 

 

http://twistedmatrix.com/documents/13.0.0/api/twisted.internet.protocol.ReconnectingClientFactory.html

 

Un-fortunately it doesn't mean much to me. It does state to make sure it starts but that Factory and not AutoFactory: 

 

Method doStart Make sure startFactory is called. Method doStop Make sure stopFactory is called.
Link to comment
Share on other sites

Just found this: http://docs.python.org/2/library/sqlite3.html

 

To use the module, you must first create a Connection object that represents the database. Here the data will be stored in the example.db file:

 

 

Its stops and starts here:

 

2013-06-23 13:39:05+0100 [AutoProtocol,client] Starting factory <devicehive.device.ws.WebSocketFactory instance at 0x17452d8>
2013-06-23 13:39:05+0100 [AutoProtocol,client] Stopping factory <devicehive.auto.AutoFactory instance at 0x13ead50>

 

 

Could somebody point me in the right direction to create the connection object? Or am i barking up the wrong proccess-tree??

Link to comment
Share on other sites

  • 3 months later...

There is a bug in line 153:
 

There was an error in the sample code:
if self.connected :
self.factory(notif, params, device_id = self.info.id, device_key = self.info.key)

The changed version:
if self.connected :
self.factory.notify(notif, params, device_id = self.info.id, device_key = self.info.key)

solution is described in git:
https://github.com/devicehive/devicehive-python/pull/2


 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.