#region import libraries

import socket
import time
from datetime import datetime
import pandas as pd
import os
import logging
import influxdb_client
from influxdb_client.client.influxdb_client import InfluxDBClient
from influxdb_client.client.write_api import SYNCHRONOUS, WriteApi
from pyModbusTCP.client import ModbusClient

#endregion

# Update interval in seconds
update_interval = 30

# Tell the computer from where to read data
ip = "0.0.0.0"
port = 5005

# InfluxDB settings
BUCKET = "Data_FerDy"
ORG    = "QF"
TOKEN  = "hm_S3eCnpU72215MwHyDYljHpvw7bxtxtRhEJmUkeBTa1wEJsGv02kZF1jwaMJ2Jeo-gY-57kOQEDTP8bOc0Fg=="
URL    = "http://smartlab.physi.uni-heidelberg.de:8086/"


#region define functions 
def init_influxdb(url: str, token: str, org: str):
    """initiate influxDB client"""
    client = influxdb_client.InfluxDBClient(
        url=url,
        token=token,
        org=org)
    write_api = client.write_api(write_options=SYNCHRONOUS)
    print('InfluxDB client and influx write_API started.')
    return client, write_api

def write_data_to_influxDB(influx_client: InfluxDBClient, write_api: WriteApi, record):
    """check if influxDB is alive and write data to influxDB, else start influxDB client"""
    try:
        # check if influxDB is ready
        influx_client.ping()
        # write data points
        write_api.write(bucket=BUCKET, org=ORG, record=record)
        print('Data written to influxDB.')
    except:
        print('InfluxDB ping not successful. InfluxDB cannot be reached.')
        try:
            # try to open the influx DB client and write API
            influx_client, write_api = init_influxdb(URL, TOKEN, ORG)
        except Exception as e:
            print('Error with InfluxDB: {}'.format(e))
            print('Data not written.')
            time.sleep(10)
    return influx_client, write_api

def setup_logger(logName):

    # creat logger
    log_dir = "logs"
    os.makedirs(log_dir, exist_ok=True)

    # setup logging
    log_file = os.path.join(log_dir, f"%s - {datetime.now():%Y-%m-%d}.log" %logName)
    logging.basicConfig(
        filename=log_file,
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(message)s",
        encoding="utf-8"
    )

    # sync output to termianl
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    logging.getLogger().addHandler(console)

    # example
    logging.info("Logger set up complete")
#endregion 

def read_temp (ip, port, influx_client, write_api):
    with socket.socket (socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind ((ip, port))
        s.listen()
       # print ("Listening")
        conn, addr = s.accept()
        with conn:
            data = conn.recv (1024)
            return data.decode().strip()
            

            


if __name__ == "__main__":
    influx_client, write_api = init_influxdb(URL, TOKEN, ORG)
    setup_logger ("PhillipsDeskTemp.")
    logging.info ("Reading the temperature on Phillip's desk")
    
    while 1:
        T = read_temp (ip, port, influx_client, write_api)
        if (T is not None and T != "test"):
            T = float (T)
            p1 = influxdb_client.Point ("Office").tag("Table", "Phillip's").field ("temp_on_desk", T)
            influx_client, write_api = write_data_to_influxDB (influx_client, write_api, p1)
        time.sleep (update_interval)