"""
ldr.py

Wyświetlanie danych analogowych z Arduino przy użyciu Pythona (matplotlib)

Autor: Mahesh Venkitachalam
Strona WWW: electronut.in
"""

import serial, argparse
from collections import deque

import matplotlib.pyplot as plt 
import matplotlib.animation as animation

    
# klasa tworzenia wykresu
class AnalogPlot:
  # konstruktor
  def __init__(self, strPort, maxLen):
      # otwarcie portu szeregowego
      self.ser = serial.Serial(strPort, 9600)

      self.a0Vals = deque([0.0]*maxLen)
      self.a1Vals = deque([0.0]*maxLen)
      self.maxLen = maxLen

  # dodawanie danych
  def add(self, data):
      assert(len(data) == 2)
      self.addToDeq(self.a0Vals, data[0])
      self.addToDeq(self.a1Vals, data[1])

  # dodawanie do deque, usuwanie najstarszej wartości
  def addToDeq(self, buf, val):
      buf.pop()
      buf.appendleft(val)

  # aktualizacja wykresu
  def update(self, frameNum, a0, a1):
      try:
          line = self.ser.readline()
          data = [float(val) for val in line.split()]
          # wyświetlanie danych
          if(len(data) == 2):
              self.add(data)
              a0.set_data(range(self.maxLen), self.a0Vals)
              a1.set_data(range(self.maxLen), self.a1Vals)
      except:
          pass

      return a0, a1

  # czyszczenie
  def close(self):
      # zamknięcie portu szeregowego
      self.ser.flush()
      self.ser.close()    

# funkcja main()
def main():
  # tworzenie parsera
  parser = argparse.ArgumentParser(description="LDR serial")
  # dodawanie oczekiwanych argumentów
  parser.add_argument('--port', dest='port', required=True)
  parser.add_argument('--N', dest='maxLen', required=False)

  # parsowanie args
  args = parser.parse_args()
  
  #strPort = '/dev/tty.usbserial-A7006Yqh'
  strPort = args.port

  print('odczytywanie z portu szeregowego %s...' % strPort)

  # parametry wykresu
  maxLen = 100
  if args.maxLen:
      maxLen = int(args.maxLen)

  # tworzenie obiektu wykresu
  analogPlot = AnalogPlot(strPort, maxLen)

  print('wykreślanie danych...')

  # konfigurowanie animacji
  fig = plt.figure()
  ax = plt.axes(xlim=(0, maxLen), ylim=(0, 1023))
  a0, = ax.plot([], [])
  a1, = ax.plot([], [])
  anim = animation.FuncAnimation(fig, analogPlot.update, 
                                 fargs=(a0, a1), 
                                 interval=20)

  # pokazanie wykresu
  plt.show()
  
  # czyszczenie
  analogPlot.close()

  print('wychodzenie z programu.')
  

# wywołanie main
if __name__ == '__main__':
  main()
