So I have the two pieces working, the MQTT sample code can post bogus data to the dashboard (Example-01-SendData.py from the Cayenne GitHub page) and I can read the temperature off the I2C connected Atlas Scientific PT-1000 ultra low temp probe. However, I’m trying to slim it down and combine the two and I can read off the PT-1000 every 5 seconds just fine, but the posting of data to the MQTT gateway doesn’t seem to want to play. It thinks it’s posting for about a minute with the device “online” but then goes offline without ever displaying any data.
Here’s the Python code:
#!/usr/bin/env python
import cayenne.client
import time
import io # used to create file streams
import fcntl # used to access I2C parameters like addresses
# Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
# setup for Brian Chee Cayenne account
MQTT_USERNAME = "myusername"
MQTT_PASSWORD = "mypassword"
MQTT_CLIENT_ID = "myclientID"
delay=5
client = cayenne.client.CayenneMQTTClient()
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# For a secure connection use port 8883 when calling client.begin:
# client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID, port=8883)
class atlas_i2c:
long_timeout = 1.5 # the timeout needed to query readings & calibrations
short_timeout = .5 # timeout for regular commands
default_bus = 1 # the default bus for I2C on the newer Raspberry Pis,
# certain older boards use bus 0
default_address = 102 # the default address for the Temperature sensor
def __init__(self, address=default_address, bus=default_bus):
# open two file streams, one for reading and one for writing
# the specific I2C channel is selected with bus
# it is usually 1, except for older revisions where its 0
# wb and rb indicate binary read and write
self.file_read = io.open("/dev/i2c-" + str(bus), "rb", buffering=0)
self.file_write = io.open("/dev/i2c-" + str(bus), "wb", buffering=0)
# initializes I2C to either a user specified or default address
self.set_i2c_address(address)
def set_i2c_address(self, addr):
# set the I2C communications to the slave specified by the address
# The commands for I2C dev using the ioctl functions are specified in
# the i2c-dev.h file from i2c-tools
I2C_SLAVE = 0x703
fcntl.ioctl(self.file_read, I2C_SLAVE, addr)
fcntl.ioctl(self.file_write, I2C_SLAVE, addr)
def write(self, string):
# appends the null character and sends the string over I2C
string += "\00"
self.file_write.write(string)
def read(self, num_of_bytes=31):
# reads a specified number of bytes from I2C,
# then parses and displays the result
res = self.file_read.read(num_of_bytes) # read from the board
# remove the null characters to get the response
response = filter(lambda x: x != '\x00', res)
if(ord(response[0]) == 1): # if the response isnt an error
# change MSB to 0 for all received characters except the first
# and get a list of characters
char_list = map(lambda x: chr(ord(x) & ~0x80), list(response[1:]))
# NOTE: having to change the MSB to 0 is a glitch in the
# raspberry pi, and you shouldn't have to do this!
# convert the char list to a string and returns it
return "Command succeeded " + ''.join(char_list)
else:
return "Error " + str(ord(response[0]))
def query(self, string):
# write a command to the board, wait the correct timeout,
# and read the response
self.write(string)
# the read and calibration commands require a longer timeout
if((string.upper().startswith("R")) or
(string.upper().startswith("CAL"))):
time.sleep(self.long_timeout)
elif((string.upper().startswith("SLEEP"))):
return "sleep mode"
else:
time.sleep(self.short_timeout)
return self.read()
def close(self):
self.file_read.close()
self.file_write.close()
def main():
device = atlas_i2c(102) # creates the I2C port object, specify the address
# or bus if necessary
i=0
timestamp = 0
# put this in just to push some data to the dashboard, but it never arrives
client.celsiusWrite(1,22.345)
while True:
i= device.query("R")
client.celsiusWrite(1,i)
print "My Temp in C: "+i
time.sleep(delay)
if __name__ == '__main__':
main()
SOrry to be dense but why didn’t the first datapoint post and do you have a link to documentation on how client.loop() works? I already have a while loop going and it’s mostly working since it reads from the I2C sensor every 5 seconds…why do I need the client.loop() if I have a while loop going?
Okie dokie…this seems to now work…gonna add a bit more to make it more bullet proof and add some code to display the temp on an LCD. Then this is going onto a -100C freezer.
#!/usr/bin/env python
import cayenne.client
import time
import io # used to create file streams
import fcntl # used to access I2C parameters like addresses
# Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
# setup for Brian Chee Cayenne account
MQTT_USERNAME = "Insert MQTT_USERNAME HERE"
MQTT_PASSWORD = "Insert MQTT_PASSWORD HERE"
MQTT_CLIENT_ID = "Insert MQTT_CLIENT_ID HERE"
delay=5
client = cayenne.client.CayenneMQTTClient()
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)
# For a secure connection use port 8883 when calling client.begin:
# client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID, port=8883)
class atlas_i2c:
long_timeout = 1.5 # the timeout needed to query readings & calibrations
short_timeout = .5 # timeout for regular commands
default_bus = 1 # the default bus for I2C on the newer Raspberry Pis,
# certain older boards use bus 0
default_address = 102 # the default address for the Temperature sensor
def __init__(self, address=default_address, bus=default_bus):
# open two file streams, one for reading and one for writing
# the specific I2C channel is selected with bus
# it is usually 1, except for older revisions where its 0
# wb and rb indicate binary read and write
self.file_read = io.open("/dev/i2c-" + str(bus), "rb", buffering=0)
self.file_write = io.open("/dev/i2c-" + str(bus), "wb", buffering=0)
# initializes I2C to either a user specified or default address
self.set_i2c_address(address)
def set_i2c_address(self, addr):
# set the I2C communications to the slave specified by the address
# The commands for I2C dev using the ioctl functions are specified in
# the i2c-dev.h file from i2c-tools
I2C_SLAVE = 0x703
fcntl.ioctl(self.file_read, I2C_SLAVE, addr)
fcntl.ioctl(self.file_write, I2C_SLAVE, addr)
def write(self, string):
# appends the null character and sends the string over I2C
string += "\00"
self.file_write.write(string)
def read(self, num_of_bytes=31):
# reads a specified number of bytes from I2C,
# then parses and displays the result
res = self.file_read.read(num_of_bytes) # read from the board
# remove the null characters to get the response
response = filter(lambda x: x != '\x00', res)
if(ord(response[0]) == 1): # if the response isnt an error
# change MSB to 0 for all received characters except the first
# and get a list of characters
char_list = map(lambda x: chr(ord(x) & ~0x80), list(response[1:]))
# NOTE: having to change the MSB to 0 is a glitch in the
# raspberry pi, and you shouldn't have to do this!
# convert the char list to a string and returns it
return ''.join(char_list)
else:
return "Error " + str(ord(response[0]))
def query(self, string):
# write a command to the board, wait the correct timeout,
# and read the response
self.write(string)
# the read and calibration commands require a longer timeout
if((string.upper().startswith("R")) or
(string.upper().startswith("CAL"))):
time.sleep(self.long_timeout)
elif((string.upper().startswith("SLEEP"))):
return "sleep mode"
else:
time.sleep(self.short_timeout)
return self.read()
def close(self):
self.file_read.close()
self.file_write.close()
def main():
device = atlas_i2c(102) # creates the I2C port object, specify the address
# or bus if necessary
i=0
timestamp = 0
while True:
client.celsiusWrite(1,device.query("R"))
client.loop()
time.sleep(delay)
if __name__ == '__main__':
main()
Ok now one more question…when I look at the data stream…I get two observations for each period… where am I writing to the MQTT gateway twice? (ignore this question)…
How long does the data stick around? Is there a way to use something like WGET to grab the dataset and store it someplace that won’t go away?
Added this line to the /etc/rc.local file:
/home/pi/start-atlas.sh &
start-atlas.sh is this:
#!/bin/sh
sleep 10
sudo /usr/bin/python2 /home/pi/minimal.py &
This then starts up the python2 script that harvests the temperature (-200C to +850C) off the I2C interface and then pushes the result every five seconds to the MQTT Cayenne gateway.