Last active
August 10, 2020 00:36
-
-
Save garystafford/1a8da165f15bc576add48735c285ed8b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import sys | |
import time | |
from argparse import ArgumentParser | |
from bluepy import btle # linux only (no mac) | |
from colr import color as colr | |
# BLE IoT Sensor Demo | |
# Author: Gary Stafford | |
# Reference: https://elinux.org/RPi_Bluetooth_LE | |
# Requirements: python3 -m pip install --user -r requirements.txt | |
# To Run: python3 ./rasppi_ble_receiver.py d1:aa:89:0c:ee:82 <- MAC address - change me! | |
def main(): | |
# get args | |
args = get_args() | |
print("Connecting...") | |
nano_sense = btle.Peripheral(args.mac_address) | |
print("Discovering Services...") | |
_ = nano_sense.services | |
environmental_sensing_service = nano_sense.getServiceByUUID("181A") | |
print("Discovering Characteristics...") | |
_ = environmental_sensing_service.getCharacteristics() | |
while True: | |
print("\n") | |
read_temperature(environmental_sensing_service) | |
read_humidity(environmental_sensing_service) | |
read_pressure(environmental_sensing_service) | |
read_color(environmental_sensing_service) | |
# time.sleep(2) # transmission frequency set on IoT device | |
def byte_array_to_int(value): | |
# Raw data is hexstring of int values, as a series of bytes, in little endian byte order | |
# values are converted from bytes -> bytearray -> int | |
# e.g., b'\xb8\x08\x00\x00' -> bytearray(b'\xb8\x08\x00\x00') -> 2232 | |
# print(f"{sys._getframe().f_code.co_name}: {value}") | |
value = bytearray(value) | |
value = int.from_bytes(value, byteorder="little") | |
return value | |
def split_color_str_to_array(value): | |
# e.g., b'2660,2059,1787,4097\x00' -> 2660,2059,1787,4097 -> | |
# [2660, 2059, 1787, 4097] -> 166.0,128.0,111.0,255.0 | |
# print(f"{sys._getframe().f_code.co_name}: {value}") | |
# remove extra bit on end ('\x00') | |
value = value[0:-1] | |
# split r, g, b, a values into array of 16-bit ints | |
values = list(map(int, value.split(","))) | |
# convert from 16-bit ints (2^16 or 0-65535) to 8-bit ints (2^8 or 0-255) | |
# values[:] = [int(v) % 256 for v in values] | |
# actual sensor is reading values are from 0 - 4097 | |
print(f"12-bit Color values (r,g,b,a): {values}") | |
values[:] = [round(int(v) / (4097 / 255), 0) for v in values] | |
return values | |
def byte_array_to_char(value): | |
# e.g., b'2660,2058,1787,4097\x00' -> 2659,2058,1785,4097 | |
value = value.decode("utf-8") | |
return value | |
def decimal_exponent_two(value): | |
# e.g., 2350 -> 23.5 | |
return value / 100 | |
def decimal_exponent_one(value): | |
# e.g., 988343 -> 98834.3 | |
return value / 10 | |
def pascals_to_kilopascals(value): | |
# 1 Kilopascal (kPa) is equal to 1000 pascals (Pa) | |
# to convert kPa to pascal, multiply the kPa value by 1000 | |
# 98834.3 -> 98.8343 | |
return value / 1000 | |
def celsius_to_fahrenheit(value): | |
return (value * 1.8) + 32 | |
def read_color(service): | |
color_char = service.getCharacteristics("936b6a25-e503-4f7c-9349-bcc76c22b8c3")[0] | |
color = color_char.read() | |
color = byte_array_to_char(color) | |
color = split_color_str_to_array(color) | |
print(f" 8-bit Color values (r,g,b,a): {color[0]},{color[1]},{color[2]},{color[3]}") | |
print("RGB Color") | |
print(colr('\t\t', fore=(127, 127, 127), back=(color[0], color[1], color[2]))) | |
print("Light Intensity") | |
print(colr('\t\t', fore=(127, 127, 127), back=(color[3], color[3], color[3]))) | |
def read_pressure(service): | |
pressure_char = service.getCharacteristics("2A6D")[0] | |
pressure = pressure_char.read() | |
pressure = byte_array_to_int(pressure) | |
pressure = decimal_exponent_one(pressure) | |
pressure = pascals_to_kilopascals(pressure) | |
print(f"Barometric Pressure: {round(pressure, 2)} kPa") | |
def read_humidity(service): | |
humidity_char = service.getCharacteristics("2A6F")[0] | |
humidity = humidity_char.read() | |
humidity = byte_array_to_int(humidity) | |
humidity = decimal_exponent_two(humidity) | |
print(f"Humidity: {round(humidity, 2)}%") | |
def read_temperature(service): | |
temperature_char = service.getCharacteristics("2A6E")[0] | |
temperature = temperature_char.read() | |
temperature = byte_array_to_int(temperature) | |
temperature = decimal_exponent_two(temperature) | |
temperature = celsius_to_fahrenheit(temperature) | |
print(f"Temperature: {round(temperature, 2)}°F") | |
def get_args(): | |
arg_parser = ArgumentParser(description="BLE IoT Sensor Demo") | |
arg_parser.add_argument('mac_address', help="MAC address of device to connect") | |
args = arg_parser.parse_args() | |
return args | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment