#!/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()