#!/usr/bin/env python3

from adc import ADS1115, ADCFilter
from settings import UR, WATER_TANK_CONFIG


class LinearInterpolation:
    """
    Interpolate a 1-D function.

    `x` and `y` are arrays of values used to approximate some function f: ``y = f(x)``.
    """

    def __init__(self, x, y):
        if len(x) != len(y):
            raise Exception('Arrays must have the same number of elements')
        if len(x) < 2:
            raise Exception('At least two points are required')
        self.x = x
        self.y = y

    def __call__(self, x_new):
        distances = [abs(v - x_new) for v in self.x]
        indexes = list(range(len(distances)))
        indexes.sort(key=distances.__getitem__)
        i1 = indexes[0]
        i2 = indexes[1]

        x1 = self.x[i1]
        x2 = self.x[i2]
        y1 = self.y[i1]
        y2 = self.y[i2]

        return y1 + (x_new - x1) / (x2 - x1) * (y2 - y1)


class PressureInterface:
    """
    MP3V5050DP pressure sensor interface.
    """

    # ADC data rate
    adc_sps = 64

    sensitivity = 54 * UR.mV / UR.kPa

    def __init__(self, i2c_busn, i2c_addr, adc_channel, adc_fsr, pressure_offset):
        self.adc = ADS1115(i2c_busn, i2c_addr)
        self.adc.config(adc_channel, adc_fsr, self.adc_sps)
        self.adc = ADCFilter(self.adc, samples_count=self.adc_sps)
        self.pressure_offset = pressure_offset

    def get_pressure_and_voltage(self):
        voltage = self.adc.get_voltage()
        pressure = voltage / self.sensitivity - self.pressure_offset
        return pressure, voltage

    def get_pressure(self):
        return self.get_pressure_and_voltage()[0]


class WaterTankInterface:
    """
    Complete water tank interface with calibration.
    """

    def __init__(self, config):
        pass

    def get_volume(self):
        return 0 * UR.L


def main():
    tank = WaterTankInterface(WATER_TANK_CONFIG)
    while True:
        try:
            volume = tank.get_volume()
            print('{:~5.1fP}'.format(volume.to('L')))
        except Exception as e:
            print(e)


if __name__ == '__main__':
    main()

@@ -920,25 +920,33 @@
 Pressure
-Interface
+SensorCalibration
 :%0A    %22%22
@@ -978,25 +978,27 @@
  sensor 
-interface
+calibration
 .%0A    %22%22
@@ -1004,46 +1004,8 @@
 %22%22%0A%0A
-    # ADC data rate%0A    adc_sps = 64%0A%0A
     
@@ -1066,114 +1066,489 @@
 lf, 
-i2c_busn, i2c_addr, adc_chann
+pressure_offset):%0A        self.pressure_offset = pressure_offset%0A%0A    def compute_pressure(s
 el
+f
 , 
-adc_fsr, pressure_offset):%0A        self.adc = ADS1115(i2c_busn, i2c_addr)
+voltage):%0A        return voltage / self.sensitivity - self.pressure_offset%0A%0A%0Aclass PressureSensorInterface:%0A    %22%22%22%0A    Complete MP3V5050DP pressure sensor interface with calibration.%0A    %22%22%22%0A%0A    def __init__(self, config):%0A        adc_sps = config%5B'adc'%5D%5B'sps'%5D%0A%0A        adc = ADS1115(%0A            i2c_busn=config%5B'adc'%5D%5B'i2c_busn'%5D,%0A            i2c_addr=config%5B'adc'%5D%5B'i2c_addr'%5D)%0A
 %0A   
@@ -1552,21 +1552,16 @@
         
-self.
 adc.conf
@@ -1567,35 +1567,109 @@
 fig(
-adc_channel, adc_fsr, self.
+%0A            channel=config%5B'adc'%5D%5B'channel'%5D,%0A            fsr=config%5B'adc'%5D%5B'fsr'%5D,%0A            sps=
 adc_
@@ -1665,32 +1665,33 @@
    sps=adc_sps)%0A
+%0A
         self.adc
@@ -1707,17 +1707,41 @@
 ter(
-self.adc,
+%0A            adc=adc,%0A           
  sam
@@ -1751,21 +1751,16 @@
 s_count=
-self.
 adc_sps)
@@ -1760,16 +1760,17 @@
 dc_sps)%0A
+%0A
         
@@ -1774,34 +1774,108 @@
    self.
-pressure_offset = 
+calibration = PressureSensorCalibration(%0A            pressure_offset=config%5B'calibration'%5D%5B'
 pressure
@@ -1873,32 +1873,35 @@
 'pressure_offset
+'%5D)
 %0A%0A    def get_pr
@@ -1990,57 +1990,50 @@
 e = 
-voltage / self.sensitivity - self.pressure_offset
+self.calibration.compute_pressure(voltage)
 %0A   

split the PressureInterface class