"""Driver for ipp"""

import threading
import sys
from device_base import deviceBase
from Channel import PLCChannel
from utilities import get_public_ip_address
from maps import *
import time
import logging

_ = None

# LOGGING SETUP
from logging.handlers import RotatingFileHandler

log_formatter = logging.Formatter('%(asctime)s %(levelname)s %(funcName)s(%(lineno)d) %(message)s')
logFile = './ipp.log'
my_handler = RotatingFileHandler(logFile, mode='a', maxBytes=500*1024, backupCount=2, encoding=None, delay=0)
my_handler.setFormatter(log_formatter)
my_handler.setLevel(logging.INFO)
logger = logging.getLogger('ipp')
logger.setLevel(logging.INFO)
logger.addHandler(my_handler)

console_out = logging.StreamHandler(sys.stdout)
console_out.setFormatter(log_formatter)
logger.addHandler(console_out)

logger.info("ipp startup")

# GLOBAL VARIABLES
WATCHDOG_SEND_PERIOD = 3600  # Seconds, the longest amount of time before sending the watchdog status
PLC_IP_ADDRESS = "10.20.4.5"
CHANNELS = [
    PLCChannel(PLC_IP_ADDRESS, 'alarmdhpressure', 'alarm_DHPressure', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'alarmdhtemperature', 'alarm_DHTemperature', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'alarme300', 'alarm_E300', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'alarmtubingpressure', 'alarm_TubingPressure', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'automode', 'Auto_Mode', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'cfgcflasetting', 'cfg_C_FLASetting', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgcleartripcountafter', 'cfg_ClearTripCountAfter', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgdhsensordisttointake', 'cfg_DHSensorDistToIntake', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfggfgroundfaultinhibittime', 'cfg_GF_GroundFaultInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfggfgroundfaulttripdelay', 'cfg_GF_GroundFaultTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfggfgroundfaulttriplevel', 'cfg_GF_GroundFaultTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfggfgroundfaultwarningdelay', 'cfg_GF_GroundFaultWarningDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfggfgroundfaultwarninglevel', 'cfg_GF_GroundFaultWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgictprimary', 'cfg_I_CTPrimary', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgictsecondary', 'cfg_I_CTSecondary', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgicurrentimbalanceinhibittim', 'cfg_I_CurrentImbalanceInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgicurrentimbalancetripdelay', 'cfg_I_CurrentImbalanceTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgicurrentimbalancetriplevel', 'cfg_I_CurrentImbalanceTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgicurrentimbalancewarninglev', 'cfg_I_CurrentImbalanceWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgijaminhibittime', 'cfg_I_JamInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgijamtripdelay', 'cfg_I_JamTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgijamtriplevel', 'cfg_I_JamTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgijamwarninglevel', 'cfg_I_JamWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgilinelossinhibittime', 'cfg_I_LineLossInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgilinelosstripdelay', 'cfg_I_LineLossTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiovercurrentinhibittime', 'cfg_I_OvercurrentInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiovercurrenttripdelay', 'cfg_I_OvercurrentTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiovercurrenttriplevel', 'cfg_I_OvercurrentTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiovercurrentwarninglevel', 'cfg_I_OvercurrentWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgistallenabledtime', 'cfg_I_StallEnabledTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgistalltriplevel', 'cfg_I_StallTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiundercurrentinhibittime', 'cfg_I_UndercurrentInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiundercurrenttripdelay', 'cfg_I_UndercurrentTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiundercurrenttriplevel', 'cfg_I_UndercurrentTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiundercurrentwarninglevel', 'cfg_I_UndercurrentWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiunderloadinhibittime', 'cfg_I_UnderloadInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiunderloadtripdelay', 'cfg_I_UnderloadTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiunderloadtriplevel', 'cfg_I_UnderloadTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgiunderloadwarninglevel', 'cfg_I_UnderloadWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgoverloadtripcountlimit', 'cfg_OverloadTripCountLimit', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgplphaselossinhibittime', 'cfg_PL_PhaseLossInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgplphaselosstripdelay', 'cfg_PL_PhaseLossTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgread', 'cfg_READ', 'REAL', 0.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgspecificgravity', 'cfg_SpecificGravity', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtcuolresetlevel', 'cfg_TCU_OLResetLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtcuolwarninglevel', 'cfg_TCU_OLWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtcutripclass', 'cfg_TCU_TripClass', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtimermodeenabled', 'cfg_TimerModeEnabled', 'REAL', 0.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtimerruntime', 'cfg_TimerRunTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtimerwaittime', 'cfg_TimerWaitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgtripcountlimit', 'cfg_TripCountLimit', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvoverfrequencyinhibittime', 'cfg_V_OverfrequencyInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvoverfrequencytripdelay', 'cfg_V_OverfrequencyTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvoverfrequencytriplevel', 'cfg_V_OverfrequencyTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvoverfrequencywarninglevel', 'cfg_V_OverfrequencyWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvovervoltageinhibittime', 'cfg_V_OvervoltageInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvovervoltagetripdelay', 'cfg_V_OvervoltageTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvovervoltagetriplevel', 'cfg_V_OvervoltageTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvovervoltagewarninglevel', 'cfg_V_OvervoltageWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvphaserotationinhibittime', 'cfg_V_PhaseRotationInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvphaserotationtriptype', 'cfg_V_PhaseRotationTripType', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvptprimary', 'cfg_V_PTPrimary', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvptsecondary', 'cfg_V_PTSecondary', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvunderfrequencyinhibittime', 'cfg_V_UnderfrequencyInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvunderfrequencytripdelay', 'cfg_V_UnderfrequencyTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvunderfrequencytriplevel', 'cfg_V_UnderfrequencyTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvunderfrequencywarninglevel', 'cfg_V_UnderfrequencyWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvundervoltageinhibittime', 'cfg_V_UndervoltageInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvundervoltagetripdelay', 'cfg_V_UndervoltageTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvundervoltagetriplevel', 'cfg_V_UndervoltageTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvundervoltagewarninglevel', 'cfg_V_UndervoltageWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvvoltageimbalanceinhibittim', 'cfg_V_VoltageImbalanceInhibitTime', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvvoltageimbalancetripdelay', 'cfg_V_VoltageImbalanceTripDelay', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvvoltageimbalancetriplevel', 'cfg_V_VoltageImbalanceTripLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvvoltageimbalancewarninglev', 'cfg_V_VoltageImbalanceWarningLevel', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgvvoltagemode', 'cfg_V_VoltageMode', 'REAL', 1.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'cfgwrite', 'cfg_WRITE', 'REAL', 0.0, 86400, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'contactorstatus', 'Contactor_Status', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'devicestatus', 'Device_Status_INT', 'STRING', 0.0, 3600, plc_type='Micro800', map_=map_device_status),
    PLCChannel(PLC_IP_ADDRESS, 'dhdownholestatusint', 'DH_DownholeStatus_INT', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhfluidlevel', 'DH_Fluid_Level', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhintakepressure', 'DH_IntakePressure', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhintaketemperature', 'DH_IntakeTemperature', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhmaxintakepressureforever', 'DH_MaxIntakePressure_Forever', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhmaxintakepressurestartup', 'DH_MaxIntakePressure_Startup', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhmaxintaketemperatureforever', 'DH_MaxIntakeTemperature_Forever', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhmaxintaketemperaturestartup', 'DH_MaxIntakeTemperature_Startup', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhnumchannels', 'DH_NumChannels', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhpsirating', 'DH_PSIRating', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhtooltype', 'DH_ToolType', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'dhtoolvoltage', 'DH_ToolVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'downholetoolenabled', 'Downhole_Tool_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'downtimetimeparameter', 'Downtime_Time_Parameter', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'downtimetimeparameterol', 'Downtime_Time_Parameter_OL', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'e300averagecurrent', 'E300_AverageCurrent', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300averagellvoltage', 'E300_AverageLLVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300averagelnvoltage', 'E300_AverageLNVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300kwh', 'E300_kWh', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300kwhregen', 'E300_kWh_Regen', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1apparentpower', 'E300_L1ApparentPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1current', 'E300_L1Current', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1l2voltage', 'E300_L1L2Voltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1nvoltage', 'E300_L1NVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1reactivepower', 'E300_L1ReactivePower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1realpower', 'E300_L1RealPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l1truepowerfactor', 'E300_L1TruePowerFactor', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2apparentpower', 'E300_L2ApparentPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2current', 'E300_L2Current', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2l3voltage', 'E300_L2L3Voltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2nvoltage', 'E300_L2NVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2reactivepower', 'E300_L2ReactivePower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2realpower', 'E300_L2RealPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l2truepowerfactor', 'E300_L2TruePowerFactor', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3apparentpower', 'E300_L3ApparentPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3current', 'E300_L3Current', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3l1voltage', 'E300_L3L1Voltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3nvoltage', 'E300_L3NVoltage', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3reactivepower', 'E300_L3ReactivePower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3realpower', 'E300_L3RealPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300l3truepowerfactor', 'E300_L3TruePowerFactor', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300linefrequency', 'E300_LineFrequency', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300percentcurrentunbalance', 'E300_PercentCurrentUnbalance', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300percentvoltageunbalance', 'E300_PercentVoltageUnbalance', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300threephasetruepowerfactor', 'E300_ThreePhaseTruePowerFactor', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300totalapparentpower', 'E300_TotalApparentPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300totalreactivepower', 'E300_TotalReactivePower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'e300totalrealpower', 'E300_TotalRealPower', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'flowrate', 'Flowrate', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'flowtoday', 'Flow_Today', 'REAL', 100.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'flowyesterday', 'Flow_Yesterday', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'handmode', 'Hand_Mode', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'overloadtrip', 'OverloadTrip', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'pressurealarmdelay', 'Pressure_Alarm_Delay', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressurealarmstartupdelay', 'Pressure_Alarm_Startup_Delay', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressureeumax', 'Pressure_EU_Max', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressureeumin', 'Pressure_EU_Min', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressurehi', 'Pressure_Hi', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'pressurehisp', 'Pressure_Hi_SP', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressurein', 'Pressure_In', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'pressurelo', 'Pressure_Lo', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'pressurelosp', 'Pressure_Lo_SP', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressureok', 'Pressure_OK', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'pressureshutdown', 'Pressure_Shutdown', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressureshutdownenabled', 'Pressure_Shutdown_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressurestartup', 'Pressure_Startup', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressurestartupenabled', 'Pressure_Startup_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressureswitchenabled', 'Pressure_Switch_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'pressuretransducerenabled', 'Pressure_Transducer_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'rpmode', 'RP_Mode', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'rppressure', 'RP_Pressure', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'rptemperature', 'RP_Temperature', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'rptrip', 'RP_Trip', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'rptubingpressure', 'RP_TubingPressure', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'runpermissive', 'Run_Permissive', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'spmode', 'SP_Mode', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'sppressure', 'SP_Pressure', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'sptemperature', 'SP_Temperature', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'sptrip', 'SP_Trip', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'spvoltage', 'SP_Voltage', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'startbutton', 'Start_Button', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'startcommand', 'Start_Command', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'startpermissive', 'Start_Permissive', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'stopcommand', 'Stop_Command', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tempshutdown', 'Temp_Shutdown', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tempshutdownenabled', 'Temp_Shutdown_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tempstartup', 'Temp_Startup', 'REAL', 1.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tempstartupenabled', 'Temp_Startup_Enabled', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'testmode', 'Test_Mode', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledicurrentimbalance', 'TripEnabled_I_CurrentImbalance', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledigroundfault', 'TripEnabled_I_GroundFault', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledijam', 'TripEnabled_I_Jam', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledilineloss', 'TripEnabled_I_LineLoss', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablediovercurrent', 'TripEnabled_I_Overcurrent', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledioverload', 'TripEnabled_I_Overload', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablediphaseloss', 'TripEnabled_I_PhaseLoss', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenabledistall', 'TripEnabled_I_Stall', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablediundercurrent', 'TripEnabled_I_Undercurrent', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablediunderload', 'TripEnabled_I_Underload', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevoverfrequency', 'TripEnable_V_Overfrequency', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevovervoltage', 'TripEnable_V_Overvoltage', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevphaserotation', 'TripEnable_V_PhaseRotation', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevunderfrequency', 'TripEnable_V_Underfrequency', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevundervoltage', 'TripEnable_V_Undervoltage', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripenablevvoltageunbalance', 'TripEnable_V_VoltageUnbalance', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripresetcmd', 'TripResetCmd', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'tripstatus', 'TripStatus', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'tripstatuscontrolint', 'TripStatusControl_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_control),
    PLCChannel(PLC_IP_ADDRESS, 'tripstatuscurrentint', 'TripStatusCurrent_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_current),
    PLCChannel(PLC_IP_ADDRESS, 'tripstatuspowerint', 'TripStatusPower_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_power),
    PLCChannel(PLC_IP_ADDRESS, 'tripstatusvoltageint', 'TripStatusVoltage_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_voltage),
    PLCChannel(PLC_IP_ADDRESS, 'valoverloadtripcount', 'val_OverloadTripCount', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'valtripcount', 'val_TripCount', 'REAL', 1.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'voltageok', 'VoltageOK', 'REAL', 0.0, 3600, plc_type='Micro800'),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledicurrentimbalanc', 'WarningEnabled_I_CurrentImbalance', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledigroundfault', 'WarningEnabled_I_GroundFault', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledijam', 'WarningEnabled_I_Jam', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledilineloss', 'WarningEnabled_I_LineLoss', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablediovercurrent', 'WarningEnabled_I_Overcurrent', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledioverload', 'WarningEnabled_I_Overload', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablediphaseloss', 'WarningEnabled_I_PhaseLoss', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenabledistall', 'WarningEnabled_I_Stall', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablediundercurrent', 'WarningEnabled_I_Undercurrent', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablediunderload', 'WarningEnabled_I_Underload', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevoverfrequency', 'WarningEnable_V_Overfrequency', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevovervoltage', 'WarningEnable_V_Overvoltage', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevphaserotation', 'WarningEnable_V_PhaseRotation', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevunderfrequency', 'WarningEnable_V_Underfrequency', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevundervoltage', 'WarningEnable_V_Undervoltage', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningenablevvoltageunbalance', 'WarningEnable_V_VoltageUnbalance', 'REAL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningstatus', 'WarningStatus', 'BOOL', 0.0, 3600, plc_type='Micro800', write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningstatuscontrolint', 'WarningStatusControl_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_control, write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningstatuscurrentint', 'WarningStatusCurrent_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_current, write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningstatuspowerint', 'WarningStatusPower_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_power, write_enabled=True),
    PLCChannel(PLC_IP_ADDRESS, 'warningstatusvoltageint', 'WarningStatusVoltage_INT', 'STRING', 1.0, 3600, plc_type='Micro800', map_=map_e300_voltage, write_enabled=True)
]


class start(threading.Thread, deviceBase):
    """Start class required by Meshify."""

    def __init__(self, name=None, number=None, mac=None, Q=None, mcu=None, companyId=None, offset=None, mqtt=None, Nodes=None):
        """Initialize the driver."""
        threading.Thread.__init__(self)
        deviceBase.__init__(self, name=name, number=number, mac=mac, Q=Q, mcu=mcu, companyId=companyId, offset=offset, mqtt=mqtt, Nodes=Nodes)

        self.daemon = True
        self.version = "9"
        self.finished = threading.Event()
        self.forceSend = False
        threading.Thread.start(self)

    # this is a required function for all drivers, its goal is to upload some piece of data
    # about your device so it can be seen on the web
    def register(self):
        """Register the driver."""
        pass

    def run(self):
        """Actually run the driver."""
        wait_sec = 30
        for i in range(0, wait_sec):
            print("ipp driver will start in {} seconds".format(wait_sec - i))
            time.sleep(1)
        logger.info("BOOM! Starting ipp driver...")

        public_ip_address = get_public_ip_address()
        self.sendtodb('public_ip_address', public_ip_address, 0)

        send_loops = 0
        watchdog_loops = 0
        watchdog_check_after = 5000
        while True:
            if self.forceSend:
                logger.warning("FORCE SEND: TRUE")

            for c in CHANNELS:
                v = c.read()
                if c.check(v, self.forceSend):
                    self.sendtodb(c.mesh_name, c.value, 0)

            if self.forceSend:
                if send_loops > 2:
                    logger.warning("Turning off forceSend")
                    self.forceSend = False
                    send_loops = 0
                else:
                    send_loops += 1

            watchdog_loops += 1
            if (watchdog_loops >= watchdog_check_after):
                test_public_ip = get_public_ip_address()
                if not test_public_ip == public_ip_address:
                    self.sendtodb('public_ip_address', test_public_ip, 0)
                    public_ip_address = test_public_ip
                watchdog_loops = 0
            time.sleep(10)

    def ipp_sync(self, name, value):
        """Sync all data from the driver."""
        self.sendtodb("connected", "true", 0)
        return True
