Skip to content
This repository has been archived by the owner on Nov 6, 2019. It is now read-only.

Thingsboard #30

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 102 additions & 87 deletions src/sensors/i2c.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,102 +2,117 @@

import io # used to create file streams
import fcntl # used to access I2C parameters like addresses

import time # used for sleep delay and timestamps
import string # helps parse strings

import requests # used to make requests to server
import paho.mqtt.client as mqtt
import requests # used to make requests to server
import json

read_count = 0

class AtlasI2C:
long_timeout = 1.5 # the timeout needed to query readings and 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 = 97 # the default address for the sensor
current_addr = default_address

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)
self.current_addr = addr

def write(self, cmd):
# appends the null character and sends the string over I2C
cmd += "\00"
self.file_write.write(cmd)

def read(self, num_of_bytes=31):
global read_count
print("read count: " + str(read_count))
# 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
response = filter(lambda x: x != '\x00', res) # remove the null characters to get the response

if ord(response[0]) == 1: # if the response isn't 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:]))
reading = ''.join(char_list)

if (read_count >= 1):
payload = {}
payload['reading'] = reading
payload['location'] = 'TANK 1'
requests.post('https://vv-dio-service-staging.herokuapp.com/api/v1/do/readings', data=payload)

read_count += 1
# NOTE: having to change the MSB to 0 is a glitch in the raspberry pi, and you shouldn't have to do this!
return "Command succeeded " + reading # convert the char list to a string and returns it
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)
THINGSBOARD_HOST = 'demo.thingsboard.io'
ACCESS_TOKEN = 'DtQvVu5pNtW4AGHcMJJw'
read_count = 0

return self.read()
client = mqtt.Client()

def close(self):
self.file_read.close()
self.file_write.close()
# Set access token
client.username_pw_set(ACCESS_TOKEN)
# Connect to ThingsBoard using default MQTT port and 60 seconds keepalive interval
client.connect(THINGSBOARD_HOST, 1883, 60)
client.loop_start()

def list_i2c_devices(self):
prev_addr = self.current_addr # save the current address so we can restore it after
i2c_devices = []
for i in range(0, 128):
try:
self.set_i2c_address(i)
self.read()
i2c_devices.append(i)
except IOError:
pass
self.set_i2c_address(prev_addr) # restore the address we were using
return i2c_devices

class AtlasI2C:
long_timeout = 1.5 # the timeout needed to query readings and 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 = 97 # the default address for the sensor
current_addr = default_address

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)
self.current_addr = addr

def write(self, cmd):
# appends the null character and sends the string over I2C
cmd += "\00"
self.file_write.write(cmd)

def read(self, num_of_bytes=31):
global read_count
#global ubi_var
print("read count: " + str(read_count))
# 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
response = filter(lambda x: x != '\x00', res) # remove the null characters to get the response

if ord(response[0]) == 1: # if the response isn't 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:]))
reading = ''.join(char_list)

if (read_count >= 1):
payload = {}
payload['reading'] = reading
payload['location'] = 'TANK 1'
payload['Type'] = 0
client.publish('v1/devices/me/telemetry', json.dumps(payload), 1)
requests.post('https://vv-dio-service-staging.herokuapp.com/api/v1/do/readings', data = payload)

read_count += 1
# NOTE: having to change the MSB to 0 is a glitch in the raspberry pi, and you shouldn't have to do this!
return "Command succeeded " + reading # convert the char list to a string and returns it
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 list_i2c_devices(self):
prev_addr = self.current_addr # save the current address so we can restore it after
i2c_devices = []
for i in range (0,128):
try:
self.set_i2c_address(i)
self.read()
i2c_devices.append(i)
except IOError:
pass
self.set_i2c_address(prev_addr) # restore the address we were using
return i2c_devices

def main():
device = AtlasI2C() # creates the I2C port object, specify the address or bus if necessary
Expand Down