#!/usr/bin/env python3

# This script is an adaption of the servo_demo.py script for the AIY voice HAT,
# optimized for the color recognition uing the Afafruit TCS34725 breakout 

import aiy.audio
import aiy.cloudspeech
import aiy.voicehat

#from gpiozero import LED     # could be helpful for an external LED on servo-port
#from gpiozero import Button  # could be helpful for an external button on servo-port

import time
import smbus
bus = smbus.SMBus(1)

import colorsys

def hue2color(hue):   # color interpretation based on the calculated hue values

 if ((hue> 12) and (hue< 26)): # i.e. between 12° and 40°. All settings may require optimization
     color="orange"
     return color
    
 elif ((hue> 25) and (hue< 70)):
     color="yellow"
     return color
    
 elif ((hue> 69) and (hue< 165)):
     color="green"
     return color
     
 elif ((hue> 164) and (hue< 195)): # 180 +/- 15
     color="cyan" 
     return color
    
 elif ((hue> 194) and (hue< 270)):
     color="blue" 
     return color
    
 elif ((hue> 269) and (hue< 320)):
     color="magenta" 
     return color
    
 elif ((hue> 319) or (hue< 20)):
     color="red" 
     return color
    
 else: print ("something went wrong")


def tcs34725(): # measurement and interpretation. 

# The measurement is performed by the Bradspi TCS34725 script: 
# https://bradsrpi.blogspot.com/2013/05/tcs34725-rgb-color-sensor-raspberry-pi.html

 bus.write_byte(0x29,0x80|0x12)
 ver = bus.read_byte(0x29)
 # version # should be 0x44
 if ver == 0x44:
  print ("Device found\n")
  bus.write_byte(0x29, 0x80|0x00) # 0x00 = ENABLE register
  bus.write_byte(0x29, 0x01|0x02) # 0x01 = Power on, 0x02 RGB sensors enabled
  bus.write_byte(0x29, 0x80|0x14) # Reading results start register 14, LSB then MSB

  data = bus.read_i2c_block_data(0x29, 0)
  clear = clear = data[1] << 8 | data[0]
  red = data[3] << 8 | data[2]
  green = data[5] << 8 | data[4]
  blue = data[7] << 8 | data[6]
  crgb = "Absolute counts: C: %s, R: %s, G: %s, B: %s\n" % (clear, red, green, blue)
  print (crgb)
  time.sleep(1)

 else: 
  print ("Device not found\n")

# normalization and transformation of the measured RGBW values

 col=""

# Maximum values Normalization factors, must be defined experimentally
# e.g. vs. a white sheet of paper. Check and correct from time to time.
 max_bright = 5750 
 max_red = 1930
 max_green = 2095
 max_blue = 1980

# Background/Minimum values normalization factors, must be defined experimentally 
# e.g. vs. black sheet of paper. Check and correct from time to time.
 min_bright = 750
 min_red = 340
 min_green = 245
 min_blue = 225

# normalized values, between 0 and 1
 rel_bright = ((clear - min_bright)/(max_bright - min_bright)) 
 rel_red = ((red - min_red)/(max_red - min_red))
 rel_green = ((green - min_green)/(max_green - min_green))
 rel_blue = ((blue - min_blue)/(max_blue - min_blue))

 hsv_col = colorsys.rgb_to_hsv(rel_red, rel_green, rel_blue)
 hue = hsv_col[0]*359

 if rel_bright > 0.9: col = "white"    # if very bright -> white
 elif rel_bright < 0.1: col = "black"  # if very dark -> black
 else: col = hue2color(hue)            # color selection by hue values

 # print("relative values bright, red, green, blue:") 
 # print (rel_bright, rel_red, rel_green, rel_blue) 
 # print("HSV values  (hue, saturation, value):", hsv_col)
 # print ("hue in ° ",hue)

 return [col, rel_bright, rel_red, rel_green, rel_blue, hue]


def main():

 button = aiy.voicehat.get_button()   # change Button status
 led = aiy.voicehat.get_led()         # change Button-LED status

 aiy.audio.get_recorder().start()
 
 # buttoni= Button(5)     # distance sensor or other external button, connected to servo3/GPIO 05

 aiy.audio.say("Hello!", lang="en-GB", volume=50, pitch=100)  # volume and pitch require November 2017 revision of audio.py and _tty.py driver!
 aiy.audio.say("To start, move the sensor above the object. Then press the blue button", lang="en-GB", volume=50, pitch = 100)
 print("To activate color measurement  place sensor above object, then press the blue button")

 while True:

    led.set_state(aiy.voicehat.LED.ON)
    button.wait_for_press() # for external button, replace button by buttoni
    led.set_state(aiy.voicehat.LED.BLINK)
    aiy.audio.say("Measuring", lang="en-GB", volume=50, pitch = 100) 

    result = tcs34725()  # evokes measurement and interpretation 

    col = result[0]                     # color, as text
    hue = str(int(result[5]))           # hue in °, as text
    r_red = str(int(result[2]*255))     # R value, as text
    r_green = str(int(result[3]*255))   # G value, as text
    r_blue = str(int(result[4]*255))    # B value, as text
    r_bright = str(int(result[1]*100))  # W value, as text

    led.set_state(aiy.voicehat.LED.OFF)

    if col == "white" or col=="black":
        bright = ""
    elif (result[1] >0.69): #brightness/lightness of color
        bright ="light"     
    elif (result[1] <0.25):
        bright ="dark"
    else :
        bright ="medium"

    # communiating the results    

    color_text =("The color of the object is " + bright + " " + col)
    print (color_text)
    aiy.audio.say(color_text, lang="en-GB", volume=75, pitch=100)
   
    hue_text = ("The hue value is "+ hue+ " degrees")
    print (hue_text)
    aiy.audio.say(hue_text, lang="en-GB", volume=75, pitch = 100)


             
if __name__ == '__main__':
 main()
