308 lines
9.7 KiB
Python
308 lines
9.7 KiB
Python
#!/opt/homebrew/bin/python3
|
|
# -*- coding:utf-8 -*-
|
|
|
|
import os, subprocess, psutil
|
|
from influxdb_client import InfluxDBClient, Point
|
|
from influxdb_client.client.write_api import SYNCHRONOUS
|
|
from grafana import grafana
|
|
import threading
|
|
import json
|
|
from logs import log
|
|
|
|
class InfluxDB():
|
|
def __init__(self):
|
|
self.reset()
|
|
|
|
def setConfig(self, conf):
|
|
self.username = 'username' in conf and conf['username'] or ""
|
|
self.password = 'password' in conf and conf['password'] or ""
|
|
self.host = 'host' in conf and conf['host'] or "127.0.0.1"
|
|
self.port = 'port' in conf and conf['port'] or 8086
|
|
self.token = 'token' in conf and conf['token'] or ""
|
|
print(f'InfluxDB config: {self.token}')
|
|
self.org = 'org' in conf and conf['org'] or ""
|
|
self.bucketName = 'bucket' in conf and conf['bucket'] or ""
|
|
print(f'InfluxDB config: {conf}')
|
|
|
|
def reset(self):
|
|
self.client = None
|
|
self.query_api = None
|
|
self.write_api = None
|
|
self.buckets_api = None
|
|
self.influxServerName = 'influxd.exe'
|
|
self.influxServerDir = os.path.dirname(__file__)
|
|
self.influxServer = os.path.join(self.influxServerDir, self.influxServerName)
|
|
|
|
def checkInfluxd(self, name):
|
|
for p in psutil.process_iter(attrs=['name']):
|
|
if p.name() == name:
|
|
return p.pid
|
|
return None
|
|
|
|
def wait_for_process(self, process):
|
|
stdout, stderr = process.communicate()
|
|
# 处理进程的输出
|
|
|
|
def openService(self):
|
|
try:
|
|
if self.checkInfluxd(self.influxServerName):
|
|
return
|
|
process = subprocess.Popen(
|
|
self.influxServer,
|
|
creationflags=subprocess.CREATE_NO_WINDOW,
|
|
stdout=subprocess.DEVNULL,
|
|
stderr=subprocess.DEVNULL
|
|
)
|
|
# 创建线程来等待进程完成
|
|
thread = threading.Thread(target=self.wait_for_process, args=(process,))
|
|
thread.start()
|
|
except Exception as e:
|
|
log.error(e)
|
|
|
|
def openClient(self):
|
|
try:
|
|
if self.token == "":
|
|
self.client = InfluxDBClient(
|
|
url=f'{self.host}:{self.port}',
|
|
username=self.username,
|
|
password=self.password,
|
|
org=self.org,
|
|
timeout=200
|
|
)
|
|
else:
|
|
print("token:", self.token)
|
|
self.client = InfluxDBClient(
|
|
url=f'{self.host}:{self.port}',
|
|
token=self.token,
|
|
timeout=200
|
|
)
|
|
self.query_api = self.client.query_api()
|
|
self.write_api = self.client.write_api(write_options=SYNCHRONOUS)
|
|
self.buckets_api = self.client.buckets_api()
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
def closeService(self):
|
|
try:
|
|
pid = self.checkInfluxd(self.influxServerName)
|
|
if pid:
|
|
psutil.Process(pid).terminate()
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
def closeClient(self):
|
|
try:
|
|
if not self.client:
|
|
return
|
|
if not self.client.ping():
|
|
self.client.close()
|
|
return
|
|
except Exception as e:
|
|
print(e)
|
|
|
|
def open(self):
|
|
try:
|
|
self.reset()
|
|
if self.host == '127.0.0.1' or self.host == 'localhost':
|
|
self.openService()
|
|
self.openClient()
|
|
except Exception as e:
|
|
print(e)
|
|
self.reset()
|
|
|
|
def close(self):
|
|
try:
|
|
if self.host == '127.0.0.1' or self.host == 'localhost':
|
|
self.closeService()
|
|
self.closeClient()
|
|
except Exception as e:
|
|
print(e)
|
|
self.reset()
|
|
|
|
def setBucket(self, _bucketName = None):
|
|
if not _bucketName:
|
|
return
|
|
self.bucketName = _bucketName
|
|
grafana.setBucket(self.bucketName)
|
|
|
|
def query(self, q):
|
|
d = dict()
|
|
try:
|
|
if not self.client or not self.query_api or not self.client.ping():
|
|
self.open()
|
|
tables = self.query_api.query(query=q)
|
|
tables = tables.to_json()
|
|
d = json.loads(tables)
|
|
return d
|
|
except Exception as error:
|
|
log.error(error)
|
|
return None
|
|
|
|
def write(self, measurement, field = None, value = 0, unit = None):
|
|
try:
|
|
if not field:
|
|
return False
|
|
|
|
if not self.client or not self.write_api or not self.client.ping():
|
|
self.open()
|
|
|
|
if unit:
|
|
_field = f'{field} {unit}'
|
|
else:
|
|
_field = field
|
|
|
|
point = Point(measurement).field(_field, value)
|
|
|
|
return self.write_api.write(bucket=self.bucketName, org=self.org, record=point)
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False
|
|
|
|
def write_points(self, data_points ):
|
|
try:
|
|
if len(data_points) <= 0:
|
|
return False
|
|
|
|
if not self.client or not self.write_api or not self.client.ping():
|
|
self.open()
|
|
|
|
self.write_api.write(bucket=self.bucketName, org=self.org, record=data_points)
|
|
|
|
return True
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False
|
|
|
|
def writeHistory(self, measurement, field = None, value = 0, time = None, unit = None):
|
|
try:
|
|
if not field or not time:
|
|
return False
|
|
|
|
if not self.client or not self.write_api or not self.client.ping():
|
|
self.open()
|
|
|
|
if unit:
|
|
_field = f'{field} {unit}'
|
|
else:
|
|
_field = field
|
|
|
|
point = Point(measurement).field(_field, value).time(time)
|
|
|
|
self.write_api.write(bucket=self.bucketName, org=self.org, record=point)
|
|
return True
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False
|
|
|
|
def writeFromDict(self, pointDict = None):
|
|
try:
|
|
if not pointDict:
|
|
return False
|
|
|
|
if not self.client or not self.write_api or not self.client.ping():
|
|
self.open()
|
|
|
|
point = Point.from_dict(pointDict)
|
|
|
|
self.write_api.write(bucket=self.bucketName, org=self.org, record=point)
|
|
return True
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False
|
|
|
|
def create(self, _bucketName):
|
|
try:
|
|
if not self.client or not self.buckets_api or not self.client.ping():
|
|
self.open()
|
|
|
|
self.setBucket(_bucketName)
|
|
buckets = self.buckets_api.find_buckets().buckets
|
|
|
|
for bucket in buckets:
|
|
if bucket.name == _bucketName:
|
|
return False, _bucketName
|
|
print("create bucket ", _bucketName)
|
|
self.buckets_api.create_bucket(bucket_name=_bucketName, org=self.org)
|
|
|
|
return True, _bucketName
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False, None
|
|
|
|
def delete(self, _bucketName):
|
|
try:
|
|
if not self.client or not self.buckets_api:
|
|
log.fatal('client fatal')
|
|
return False, None
|
|
|
|
buckets = self.buckets_api.find_buckets().buckets
|
|
|
|
for bucket in buckets:
|
|
if bucket.name == _bucketName:
|
|
self.buckets_api.delete_bucket(bucket)
|
|
return True, _bucketName
|
|
|
|
return False, _bucketName
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False, _bucketName
|
|
|
|
def queryField(self):
|
|
try:
|
|
q = f'''
|
|
from(bucket: "{self.bucketName}")
|
|
|> range(start: 0)
|
|
|> group(columns: ["_measurement"])
|
|
|> distinct(column: "_field")
|
|
'''
|
|
|
|
result = self.query(q)
|
|
if not result:
|
|
return True, None
|
|
|
|
temp = dict()
|
|
for r in result:
|
|
k = r['_measurement']
|
|
v = r['_value']
|
|
if k not in temp:
|
|
temp.setdefault(k,[])
|
|
temp[k].append(v)
|
|
return True, temp
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False, None
|
|
|
|
def queryData(self, json_str):
|
|
try:
|
|
json_dict = json.loads(json_str)
|
|
|
|
filter_measurement = f'''r["_measurement"] == "{json_dict['measurement'][0]}"'''
|
|
for mea in json_dict['measurement'][1:]:
|
|
filter_measurement += f''' or r["_measurement"] == "{mea}"'''
|
|
|
|
filter_field = f'''r["_field"] == "{json_dict['field'][0]}"'''
|
|
for field in json_dict['field'][1:]:
|
|
filter_field += f''' or r["_field"] == "{field}"'''
|
|
|
|
q = f'''
|
|
from(bucket: "{self.bucketName}")
|
|
|> range(start: {json_dict['start']},stop: {json_dict['stop']})
|
|
|> filter(fn: (r) => {filter_measurement})
|
|
|> filter(fn: (r) => {filter_field})
|
|
|> aggregateWindow(every: 10s, fn: mean, createEmpty: false)
|
|
|> yield(name: "mean")
|
|
'''
|
|
data = self.query(q)
|
|
return True, data
|
|
except Exception as error:
|
|
log.error(error)
|
|
return False, None
|
|
|
|
def run(self):
|
|
try:
|
|
self.open()
|
|
except Exception as e:
|
|
log.error( e)
|
|
self.reset()
|
|
|
|
influxdb = InfluxDB() |