doushuo 1 settimana fa
parent
commit
a2e2c78ee0

+ 235 - 0
.idea/workspace.xml

@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AutoImportSettings">
+    <option name="autoReloadType" value="SELECTIVE" />
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="3e6cd0d0-7b4f-422b-83c1-22f99846827d" name="Changes" comment="" />
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="Dockerfile" />
+        <option value="Python Script" />
+      </list>
+    </option>
+  </component>
+  <component name="FlaskConsoleOptions" custom-start-script="import sys&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;from flask.cli import ScriptInfo&#10;locals().update(ScriptInfo(create_app=None).load_app().make_shell_context())&#10;print(&quot;Python %s on %s\nApp: %s [%s]\nInstance: %s&quot; % (sys.version, sys.platform, app.import_name, app.env, app.instance_path))">
+    <envs>
+      <env key="FLASK_APP" value="app" />
+    </envs>
+    <option name="myCustomStartScript" value="import sys&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;from flask.cli import ScriptInfo&#10;locals().update(ScriptInfo(create_app=None).load_app().make_shell_context())&#10;print(&quot;Python %s on %s\nApp: %s [%s]\nInstance: %s&quot; % (sys.version, sys.platform, app.import_name, app.env, app.instance_path))" />
+    <option name="myEnvs">
+      <map>
+        <entry key="FLASK_APP" value="app" />
+      </map>
+    </option>
+  </component>
+  <component name="ProjectColorInfo">{
+  &quot;associatedIndex&quot;: 1
+}</component>
+  <component name="ProjectId" id="2lu2bjDtEtuEDExDqzNMF6a0ti6" />
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent">{
+  &quot;keyToString&quot;: {
+    &quot;Flask server.Flask (quality_server.py).executor&quot;: &quot;Run&quot;,
+    &quot;Python.Flask_water_server.executor&quot;: &quot;Debug&quot;,
+    &quot;Python.auto_test.executor&quot;: &quot;Run&quot;,
+    &quot;Python.getData.executor&quot;: &quot;Run&quot;,
+    &quot;Python.readDataRealtimeData.executor&quot;: &quot;Debug&quot;,
+    &quot;Python.water_quality_server.executor&quot;: &quot;Run&quot;,
+    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
+    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
+    &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
+    &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
+    &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
+    &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
+    &quot;settings.editor.selected.configurable&quot;: &quot;http.proxy&quot;,
+    &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
+  }
+}</component>
+  <component name="RunManager" selected="Python.readDataRealtimeData">
+    <configuration name="Flask_water_server" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
+      <module name="water_quality_server" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <envs>
+        <env name="PYTHONUNBUFFERED" value="1" />
+      </envs>
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="IS_MODULE_SDK" value="true" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="SCRIPT_NAME" value="$PROJECT_DIR$/Flask_water_server.py" />
+      <option name="PARAMETERS" value="" />
+      <option name="SHOW_COMMAND_LINE" value="false" />
+      <option name="EMULATE_TERMINAL" value="false" />
+      <option name="MODULE_MODE" value="false" />
+      <option name="REDIRECT_INPUT" value="false" />
+      <option name="INPUT_FILE" value="" />
+      <method v="2" />
+    </configuration>
+    <configuration name="auto_test" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
+      <module name="water_quality_server" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <envs>
+        <env name="PYTHONUNBUFFERED" value="1" />
+      </envs>
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="IS_MODULE_SDK" value="true" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="SCRIPT_NAME" value="$PROJECT_DIR$/auto_test.py" />
+      <option name="PARAMETERS" value="" />
+      <option name="SHOW_COMMAND_LINE" value="false" />
+      <option name="EMULATE_TERMINAL" value="false" />
+      <option name="MODULE_MODE" value="false" />
+      <option name="REDIRECT_INPUT" value="false" />
+      <option name="INPUT_FILE" value="" />
+      <method v="2" />
+    </configuration>
+    <configuration name="getData" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
+      <module name="water_quality_server" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <envs>
+        <env name="PYTHONUNBUFFERED" value="1" />
+      </envs>
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="IS_MODULE_SDK" value="true" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="SCRIPT_NAME" value="$PROJECT_DIR$/getData.py" />
+      <option name="PARAMETERS" value="" />
+      <option name="SHOW_COMMAND_LINE" value="false" />
+      <option name="EMULATE_TERMINAL" value="false" />
+      <option name="MODULE_MODE" value="false" />
+      <option name="REDIRECT_INPUT" value="false" />
+      <option name="INPUT_FILE" value="" />
+      <method v="2" />
+    </configuration>
+    <configuration name="readDataRealtimeData" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
+      <module name="water_quality_server" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <envs>
+        <env name="PYTHONUNBUFFERED" value="1" />
+      </envs>
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
+      <option name="IS_MODULE_SDK" value="true" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="SCRIPT_NAME" value="$PROJECT_DIR$/readDataRealtimeData.py" />
+      <option name="PARAMETERS" value="" />
+      <option name="SHOW_COMMAND_LINE" value="false" />
+      <option name="EMULATE_TERMINAL" value="false" />
+      <option name="MODULE_MODE" value="false" />
+      <option name="REDIRECT_INPUT" value="false" />
+      <option name="INPUT_FILE" value="" />
+      <method v="2" />
+    </configuration>
+    <configuration name="water_quality_server" type="PythonConfigurationType" factoryName="Python">
+      <module name="water_quality_server" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <envs>
+        <env name="PYTHONUNBUFFERED" value="1" />
+      </envs>
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="" />
+      <option name="IS_MODULE_SDK" value="false" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="SCRIPT_NAME" value="$PROJECT_DIR$/quality_server.py" />
+      <option name="PARAMETERS" value="" />
+      <option name="SHOW_COMMAND_LINE" value="false" />
+      <option name="EMULATE_TERMINAL" value="false" />
+      <option name="MODULE_MODE" value="false" />
+      <option name="REDIRECT_INPUT" value="false" />
+      <option name="INPUT_FILE" value="" />
+      <method v="2" />
+    </configuration>
+    <configuration name="Flask (quality_server.py)" type="Python.FlaskServer" temporary="true" nameIsGenerated="true">
+      <module name="water_quality_server" />
+      <option name="target" value="$PROJECT_DIR$/quality_server.py" />
+      <option name="targetType" value="PATH" />
+      <option name="ENV_FILES" value="" />
+      <option name="INTERPRETER_OPTIONS" value="" />
+      <option name="PARENT_ENVS" value="true" />
+      <option name="SDK_HOME" value="" />
+      <option name="WORKING_DIRECTORY" value="" />
+      <option name="IS_MODULE_SDK" value="true" />
+      <option name="ADD_CONTENT_ROOTS" value="true" />
+      <option name="ADD_SOURCE_ROOTS" value="true" />
+      <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
+      <option name="launchJavascriptDebuger" value="false" />
+      <method v="2" />
+    </configuration>
+    <recent_temporary>
+      <list>
+        <item itemvalue="Python.readDataRealtimeData" />
+        <item itemvalue="Python.auto_test" />
+        <item itemvalue="Flask server.Flask (quality_server.py)" />
+        <item itemvalue="Python.Flask_water_server" />
+        <item itemvalue="Python.getData" />
+      </list>
+    </recent_temporary>
+  </component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="bundled-js-predefined-1d06a55b98c1-74d2a5396914-JavaScript-PY-241.14494.241" />
+        <option value="bundled-python-sdk-0509580d9d50-28c9f5db9ffe-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-241.14494.241" />
+      </set>
+    </attachedChunks>
+  </component>
+  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="3e6cd0d0-7b4f-422b-83c1-22f99846827d" name="Changes" comment="" />
+      <created>1726015713966</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1726015713966</updated>
+      <workItem from="1726015715232" duration="2811000" />
+      <workItem from="1726018728438" duration="5000" />
+      <workItem from="1726018755261" duration="23000" />
+      <workItem from="1726018932175" duration="8935000" />
+      <workItem from="1726032348460" duration="9182000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="3" />
+  </component>
+  <component name="com.intellij.coverage.CoverageDataManagerImpl">
+    <SUITE FILE_PATH="coverage/water_quality_server$water_quality_server.coverage" NAME="water_quality_server Coverage Results" MODIFIED="1726038262910" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
+    <SUITE FILE_PATH="coverage/water_quality_server$getData.coverage" NAME="getData Coverage Results" MODIFIED="1726024124109" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
+    <SUITE FILE_PATH="coverage/water_quality_server$auto_test.coverage" NAME="auto_test Coverage Results" MODIFIED="1726039663979" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
+    <SUITE FILE_PATH="coverage/water_quality_server$Flask_water_server.coverage" NAME="Flask_water_server Coverage Results" MODIFIED="1726033473666" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
+    <SUITE FILE_PATH="coverage/water_quality_server$Flask__quality_server_py_.coverage" NAME="Flask (quality_server.py) Coverage Results" MODIFIED="1726037955859" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="" />
+    <SUITE FILE_PATH="coverage/water_quality_server$readDataRealtimeData.coverage" NAME="readDataRealtimeData Coverage Results" MODIFIED="1726040124924" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="false" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
+  </component>
+</project>

+ 18 - 0
Dockerfile

@@ -0,0 +1,18 @@
+# 使用官方的 Python 镜像作为基础镜像
+FROM python:3.7
+
+# 设置工作目录
+WORKDIR /app
+
+# 复制当前目录下的所有文件到容器的工作目录
+COPY . /app
+
+# 安装依赖
+
+RUN pip install --no-cache-dir -r requirements.txt
+
+# 暴露端口
+EXPOSE 8087
+
+# 定义启动命令
+CMD ["python", "quality_server.py"]

+ 60 - 0
Flask_water_server.py

@@ -0,0 +1,60 @@
+import psycopg2
+
+import PGDB_Read
+import requests
+import json
+from writeDataToRealtimeData import upsert_realtime_data
+
+
+def calc_water_quality():
+    nm_values = (
+        'lfgawqyq_plc3_Tag17',
+        'lfgawqyq_plc3_Tag22',
+        'lfgawqyq_plc3_Tag20',
+        'lfgawqyq_plc10_Tag45',
+        'lfgawqyq_plc10_Tag43',
+        'lfgawqyq_plc10_Tag52',
+        'lfgawqyq_plc10_Tag50',
+        'lfgawqyq_plc10_Tag51',
+        'lfgawqyq_plc10_Tag53',
+    )
+
+    # 连接到数据库
+    with open('db_params.json', 'r') as f:
+        db_params = json.load(f)
+        db_params = db_params['test']
+
+    # 建立连接
+    conn = psycopg2.connect(**db_params)
+    cursor = conn.cursor()
+    json_data = PGDB_Read.query_database(cursor, nm_values)
+    print(json_data)
+
+    # 目标 URL
+    url = 'http://localhost:8087/water_quality'
+
+    # 发送 POST 请求
+    response = requests.post(url, data=json_data, headers={'Content-Type': 'application/json'})
+
+    # 打印响应内容
+    result = response.json()
+
+    write_data_list = [
+        'lfgawqyq_plc11_Tag23',
+        'lfgawqyq_plc11_Tag124',
+        'lfgawqyq_plc11_Tag25',
+        'lfgawqyq_plc11_Tag122',
+        'lfgawqyq_xn_cscod',
+        'lfgawqyq_xn_cstn',
+    ]
+
+    # 使用字典推导式将标签和值对应起来
+    data_mapping = {tag: value for tag, value in zip(write_data_list, result)}
+
+    # 打印结果字典
+    upsert_realtime_data(cursor, data_mapping)
+    # 关闭游标和连接
+    cursor.close()
+    conn.close()
+    return json.dumps(data_mapping)
+

+ 52 - 0
PGDB_Read.py

@@ -0,0 +1,52 @@
+import json
+import psycopg2
+
+
+
+
+def query_database(cursor,nm_values):
+
+
+
+    try:
+
+
+        # 要查询的 nm 值列表
+
+
+        # 参数化查询
+        query = """
+            SELECT 
+                nm, v
+            FROM realtimedata
+            WHERE nm IN %s;
+        """
+
+        # 执行 SQL 查询,传递一个元组作为 IN 子句的参数
+        cursor.execute(query, (tuple(nm_values),))
+
+
+
+        # 获取查询结果
+        results = cursor.fetchall()
+        #json_str = results = json.dumps(results)
+        # 将列表转换为字典
+        # 构建字典,根据值的类型转换为 int 或 float
+        result_dict = {row[0]: float(row[1]) if '.' in row[1] else int(row[1]) for row in results}
+
+        # 将字典转换为 JSON 字符串
+        json_str = json.dumps(result_dict, ensure_ascii=False, indent=4)
+
+        # 打印 JSON 字符串
+
+        print("数据库连接已关闭")
+        return json_str
+
+
+    except psycopg2.Error as e:
+        print("数据库操作出错")
+        print("错误详情:", e)
+
+
+
+

BIN
__pycache__/Flask_water_server.cpython-37.pyc


BIN
__pycache__/PGDB_Read.cpython-37.pyc


BIN
__pycache__/quality_server.cpython-37.pyc


BIN
__pycache__/startup_request.cpython-37.pyc


BIN
__pycache__/writeDataToRealtimeData.cpython-37.pyc


BIN
cod_20240910.pk


+ 28 - 0
config.ini

@@ -0,0 +1,28 @@
+[config]
+port=8087
+
+cod_model=cod_20240910
+tn_model=tn_20240910
+
+in_flow=lfgawqyq_plc3_Tag17
+out_flow=lfgawqyq_plc10_Tag40
+in_tn=lfgawqyq_plc3_Tag22
+in_cod=lfgawqyq_plc3_Tag20
+
+n1_dose=lfgawqyq_plc11_Tag23
+s1_dose=lfgawqyq_plc11_Tag124
+n2_dose=lfgawqyq_plc11_Tag25
+s2_dose=lfgawqyq_plc11_Tag122
+
+n1_nh4=lfgawqyq_plc10_Tag50
+n2_nh4=lfgawqyq_plc10_Tag52
+s1_nh4=lfgawqyq_plc10_Tag51
+s2_nh4=lfgawqyq_plc10_Tag53
+
+out_tn=lfgawqyq_plc10_Tag45
+out_cod=lfgawqyq_plc10_Tag43
+out_cod_predict=lfgawqyq_xn_cscod
+out_tn_predict=lfgawqyq_xn_cstn
+
+logpath=
+filename=water_quality.log

+ 13 - 0
db_params.json

@@ -0,0 +1,13 @@
+{"test":{
+    "database": "drug",
+    "user": "postgres",
+    "password": "jkauto@123",
+    "host": "103.85.171.27",
+    "port": "10087"
+},
+    "online":{"database": "postgres",
+    "user": "postgres",
+    "password": "aEaxnt4Y&^cMQ",
+    "host": "60.10.64.231",
+    "port": "10086"}
+}

+ 49 - 0
getData.py

@@ -0,0 +1,49 @@
+import json
+
+import psycopg2
+
+import PGDB_Read as PGDB
+from datetime import datetime
+point = 'nm'
+value = 'v'
+
+nm_values = (
+    'lfgawqyq_plc3_Tag22', 'lfgawqyq_plc3_Tag20',
+    'lfgawqyq_plc10_Tag45', 'lfgawqyq_plc10_Tag43',
+    'lfgawqyq_plc3_Tag17', 'lfgawqyq_plc10_Tag40'
+ )
+# 连接到数据库
+with open('db_params.json', 'r') as f:
+ db_params = json.load(f)
+ db_params = db_params['test']
+
+# 建立连接
+conn = psycopg2.connect(**db_params)
+cursor = conn.cursor()
+data = PGDB.query_database(cursor,nm_values)
+
+# 关闭游标和连接
+cursor.close()
+conn.close()
+format_data={}
+format_data['in']= data
+now = datetime.now()
+format_data['time']=now.strftime("%Y-%m-%d %H:%M")
+print(format_data)
+#输出
+# {
+#     'in': {
+#         'lfgawqyq_plc10_Tag45': '11.4345',
+#         'lfgawqyq_plc3_Tag22': '25.5208',
+#         'lfgawqyq_plc10_Tag40': '129.8828',
+#         'lfgawqyq_plc10_Tag43': '5.0528',
+#         'lfgawqyq_plc3_Tag20': '16.2399',
+#         'lfgawqyq_plc3_Tag17': '106.3368'
+#     },
+#     'time': '2024-09-10 11:51'
+# }
+
+
+
+
+

+ 341 - 0
quality_server.py

@@ -0,0 +1,341 @@
+#!/usr/bin/python37
+# coding: utf-8
+
+
+"""
+@version: 1.0
+@software: PyCharm
+@file: quality_server.py
+@time: 2024/9/10 12:18
+"""
+import threading
+from sched import scheduler
+
+import numpy as np
+import pandas as pd
+import os
+import time
+import json
+import pickle
+import configparser
+from decimal import Decimal
+
+from PIL import ImageFile
+
+
+ImageFile.LOAD_TRUNCATED_IMAGES = True
+import Flask_water_server
+
+from flask import Flask, request, jsonify
+from flask_cors import CORS
+from gevent import pywsgi, monkey
+monkey.patch_all()
+
+import logging
+np.set_printoptions(threshold = 1000000000, linewidth=1245)
+
+
+
+class Logger:
+    def __init__(self,loggername, logpath, filename):
+
+        self.logger = logging.getLogger(loggername)
+        self.logger.setLevel(logging.INFO)
+        log_path = logpath # 指定文件输出路径,logs是个文件夹,要加上/
+        logname = log_path + filename
+        self.fh = logging.FileHandler(logname, encoding = 'utf-8')
+        self.fh.setLevel(logging.INFO)
+
+        self.ch = logging.StreamHandler()
+        self.ch.setLevel(logging.INFO)
+
+        formatter = logging.Formatter('%(asctime)s-%(name)s-%(levelname)s-%(message)s')
+        self.fh.setFormatter(formatter)
+        self.ch.setFormatter(formatter)
+
+        self.logger.addHandler(self.fh)
+        self.logger.addHandler(self.ch)
+
+
+    def get_log(self):
+        return self.logger
+
+    def get_fh(self):
+        return self.fh
+
+    def log_clear(self):
+        self.logger.handlers.clear()
+
+
+class Tool:
+    def set_precision(num, digit):
+        precision_str = '{:.%d' % (digit) + 'f}'
+        dec_val = precision_str.format(Decimal(num))
+        return float(dec_val)
+
+
+    def mean_absolute_percentage_error(y_true, y_pred):
+        y_true, y_pred = np.array(y_true), np.array(y_pred)
+        return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
+
+
+    def month_of_year(ts):
+        #     ts = str(ts)
+        t = time.strptime(ts, "%Y-%m-%d %H:%M")
+        tm_mon = t.tm_mon
+        return tm_mon
+
+
+    def day_of_month(ts):
+        #     ts = str(ts)
+        t = time.strptime(ts, "%Y-%m-%d %H:%M")
+        tm_mday = t.tm_mday
+        return tm_mday
+
+    def hour_of_day(ts):
+        t = time.strptime(ts, "%Y-%m-%d %H:%M")
+        tm_hour = t.tm_hour
+        return tm_hour
+
+    def min_of_hour(ts):
+        t = time.strptime(ts, "%Y-%m-%d %H:%M")
+        tm_min = t.tm_min
+
+        return tm_min
+
+    def five_min_of_hour(ts):
+        t = time.strptime(ts, "%d/%m/%Y %H:%M:%S")
+        tm_min = t.tm_min
+        if tm_min % 5 == 0:
+            return 1
+        else:
+            return 0
+
+    def day_of_week(ts):
+        t = time.strptime(ts, "%Y-%m-%d %H:%M")
+        tm_day = t.tm_wday
+        return tm_day
+
+    def week_of_year(day):
+        week = int((day - 1) / 7) + 1
+        return week
+
+    def time_str(str):
+        return str[:-3]
+
+    def time_format(ts):
+        t = time.strptime(ts, "%d/%m/%Y %H:%M")
+        tm_year = t.tm_year
+        tm_month = t.tm_mon
+        tm_day = t.tm_mday
+        tm_hour = t.tm_hour
+        tm_min = t.tm_min
+
+        return '%s-%s-%s %s:%s' %(tm_year, tm_month, tm_day, tm_hour, tm_min)
+
+
+    def map_season(month):
+        # print(month)
+        month = int(month)
+        if month >= 12 or month <= 2:
+            value = 1
+        if month >= 3 and month <= 5:
+            value = 2
+        if month >= 6 and month <= 8:
+            value = 3
+        else:
+            value = 4
+
+        return value
+
+    def map_weather(stat):
+        # print(month)
+
+        if stat =='晴':
+            value = 1
+        if stat =='阴':
+            value = 2
+        if stat =='小雨':
+            value = 3
+        if stat =='中雨':
+            value = 4
+        if stat =='大雨':
+            value = 5
+        if stat =='暴雨':
+            value = 6
+        if stat =='阵雨':
+            value = 7
+        if stat =='多云':
+            value = 8
+        else:
+            value = 9
+
+        return value
+
+    def map_turbidity(turbidity):
+
+        turbidity = int(turbidity)
+        if turbidity >= 0 and turbidity < 10:
+            value = 1
+        if turbidity >= 10 and turbidity <20:
+            value = 2
+        if turbidity >= 20 and turbidity < 50:
+            value = 3
+        else:
+            value = 4
+
+        return value
+
+    def mean_absolute_percentage_error(y_true, y_pred):
+        y_true, y_pred = np.array(y_true), np.array(y_pred)
+        return np.mean(np.abs((y_true - y_pred) / y_true)) * 100
+
+    def model_load(path, id):
+        path_id = ''.join([path, id, '.pk'])
+        with open(path_id, 'rb') as f:
+            obj = pickle.load(f)
+
+        return obj
+
+    def dose_cal(in_flow, nh4, coef):
+        dose_value = in_flow * (4.58 * (nh4 * coef - 6) + 1.15 * 1.8 * (1 + 2.17)) / 1000 / 38 / 0.5 * 100 + 160
+        return dose_value/4
+
+
+class TN_model:
+    def __init__(self, clf):
+        self.clf = clf
+
+    def mypredict(self, jsonData):
+        try:
+            # data = json.loads(jsonData)
+            data = jsonData
+            in_flow = float(data['lfgawqyq_plc3_Tag17'])
+            in_tn = float(data['lfgawqyq_plc3_Tag22'])
+
+
+        except Exception as e:
+            logger.get_log().info("传入的json串不正确\n")
+
+        fe_tn = [in_flow, in_tn]
+
+        fe_tn = np.array(fe_tn).reshape(1, -1)
+
+        src_columns = ['in_flow', 'in_tn']
+
+        result = self.clf.predict(pd.DataFrame(fe_tn, columns=src_columns))
+
+        r = float(result[0])
+
+        r = Tool.set_precision(r, 3)
+
+        if r<0:
+            r=0
+
+        return r
+
+class COD_model:
+    def __init__(self, clf):
+        self.clf = clf
+
+    def mypredict(self, jsonData):
+        try:
+            # data = json.loads(jsonData)
+            data = jsonData
+            in_flow = float(data['lfgawqyq_plc3_Tag17'])
+            in_cod = float(data['lfgawqyq_plc3_Tag20'])
+
+        except Exception as e:
+            logger.get_log().info("传入的json串不正确\n")
+
+        fe_cod = [in_flow, in_cod]
+        fe_cod = np.array(fe_cod).reshape(1, -1)
+
+        src_columns = ['in_flow','in_cod']
+
+        result = self.clf.predict(pd.DataFrame(fe_cod, columns=src_columns))
+
+        r = float(result[0])
+
+        r = Tool.set_precision(r, 3)
+
+        if r<0:
+            r=0
+
+        return r
+
+
+app = Flask(__name__)
+@app.route('/<name>', methods=['POST'])
+def predict(name):
+    paths = ['water_quality']
+    ip = request.remote_addr
+    data = request.get_json()
+    data_json = data
+    # data_json = json.dumps(data)
+    logger.get_log().info('receive from %s = %s ' % (ip, data))
+
+    if str(name) in paths:
+        model_path = ""
+        obj_cod = Tool.model_load(model_path, cod_model)
+        obj_tn = Tool.model_load(model_path, tn_model)
+
+        result_cod = obj_cod.mypredict(data_json)
+        result_tn = obj_tn.mypredict(data_json)
+
+        in_flow = data_json['lfgawqyq_plc3_Tag17']
+        in_tn = data_json['lfgawqyq_plc3_Tag22']
+        in_cod = data_json['lfgawqyq_plc3_Tag20']
+
+        n1_nh4 = data_json['lfgawqyq_plc10_Tag50']
+        n2_nh4 = data_json['lfgawqyq_plc10_Tag52']
+        s1_nh4 = data_json['lfgawqyq_plc10_Tag51']
+        s2_nh4 = data_json['lfgawqyq_plc10_Tag53']
+
+        out_tn = data_json['lfgawqyq_plc10_Tag45']
+        out_cod = data_json['lfgawqyq_plc10_Tag43']
+
+        n1_dose = Tool.dose_cal(in_flow, n1_nh4, 0.9)
+        n2_dose = Tool.dose_cal(in_flow, n2_nh4, 0.95)
+        s1_dose = Tool.dose_cal(in_flow, s1_nh4, 0.9)
+        s2_dose = Tool.dose_cal(in_flow, s2_nh4, 0.95)
+
+        result=[Tool.set_precision(n1_dose, 3), Tool.set_precision(n2_dose, 3),
+                Tool.set_precision(3, s1_dose), Tool.set_precision(s2_dose, 3),
+                Tool.set_precision(result_cod, 3), Tool.set_precision(result_tn, 3)]
+
+        logger.get_log().info('return to %s = %s\n ' % (ip, result))
+
+        return jsonify(result)
+
+@app.route('/update_water_quality')
+def calc():
+    data = Flask_water_server.calc_water_quality()
+    print('calculate water quality')
+    return jsonify(data)
+@app.route('/')
+def home():
+    return 'Hello, World!'
+
+
+
+if __name__ == "__main__":
+    cf = configparser.ConfigParser()
+    parent_dir = os.path.dirname(os.path.abspath(__file__))
+    cf.read("config.ini")
+
+    server_port = cf.get("config", "port")
+    cod_model = cf.get("config", "cod_model")
+    tn_model = cf.get("config", "tn_model")
+
+    logpath = cf.get("config", "logpath")
+    logname = cf.get("config", "filename")
+
+    logger = Logger(__name__, logpath, logname)
+
+
+
+
+
+    logger.get_log().info("服务启动\n")
+    pywsgi.WSGIServer(('0.0.0.0', int(server_port)), app).serve_forever()

BIN
requirements.txt


+ 14 - 0
startup_request.py

@@ -0,0 +1,14 @@
+import threading
+import requests
+
+
+
+
+
+def auto_request():
+    url = 'http://localhost:8087/update_water_quality'
+    headers = {'Content-Type': 'application/json'}
+    response = requests.get(url)
+    print(response.text)
+    threading.Timer(15,auto_request).start()
+

+ 2 - 0
test_command

@@ -0,0 +1,2 @@
+curl -i -k -H "Content-type: application/json" -X POST -d '{"lfgawqyq_plc3_Tag17": 11, "Ifgawqyq_plc3_Tag22": 8.2, "Ifgawqyq_plc3_Tag20": 9, "Ifgawqyq_plc10_Tag45": 9, "lfgawqyq_plc10_Tag43": 9, "lfgawqyq_plc10_Tag50": 6, "lfgawqyq_plc10_Tag52": 9, "lfgawqyq_plc10_Tag51": 5, "lfgawqyq_plc10_Tag53": 9}' 127.0.0.1:8087/water_quality
+

BIN
tn_20240910.pk


+ 177 - 0
water_quality.log

@@ -0,0 +1,177 @@
+2024-09-11 09:22:05,561-__main__-INFO-服务启动
+
+2024-09-11 09:22:36,461-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'Ifgawqyq_plc3_Tag22': 8.2, 'Ifgawqyq_plc3_Tag20': 9, 'Ifgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 09:23:10,483-__main__-INFO-服务启动
+
+2024-09-11 09:23:13,482-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'Ifgawqyq_plc3_Tag22': 8.2, 'Ifgawqyq_plc3_Tag20': 9, 'Ifgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 09:23:13,985-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 09:28:40,829-__main__-INFO-服务启动
+
+2024-09-11 09:28:52,631-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'Ifgawqyq_plc3_Tag22': 8.2, 'Ifgawqyq_plc3_Tag20': 9, 'Ifgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 09:28:53,039-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 11:20:26,230-__main__-INFO-服务启动
+
+2024-09-11 11:21:17,359-__main__-INFO-服务启动
+
+2024-09-11 11:22:58,922-__main__-INFO-服务启动
+
+2024-09-11 11:24:01,042-__main__-INFO-服务启动
+
+2024-09-11 11:24:39,762-__main__-INFO-服务启动
+
+2024-09-11 11:24:49,763-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:24:52,587-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:25:09,859-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:25:09,869-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:25:34,178-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:25:34,186-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:00,773-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:00,782-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:08,516-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:08,524-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:12,767-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:12,775-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:20,175-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:20,185-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:29,939-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:29,949-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:35,247-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:35,262-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:26:38,756-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:26:38,773-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:27:04,369-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9, 'lfgawqyq_plc3_Tag22': 127.2063} 
+2024-09-11 11:27:04,377-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.681]
+ 
+2024-09-11 11:27:13,121-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:27:13,130-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:27:22,201-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag17': 1111, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:27:22,209-__main__-INFO-return to 127.0.0.1 = [63.652, 66.665, 3.0, 66.665, 4.82, 10.838]
+ 
+2024-09-11 11:27:30,366-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 11:27:30,374-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 11:32:22,371-__main__-INFO-服务启动
+
+2024-09-11 11:33:54,583-__main__-INFO-服务启动
+
+2024-09-11 11:37:34,674-__main__-INFO-服务启动
+
+2024-09-11 11:38:03,420-__main__-INFO-服务启动
+
+2024-09-11 13:27:07,579-__main__-INFO-服务启动
+
+2024-09-11 13:27:38,523-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:27:41,353-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:28:07,637-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:28:07,645-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:28:43,754-__main__-INFO-服务启动
+
+2024-09-11 13:28:48,791-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:28:49,092-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:31:00,788-__main__-INFO-服务启动
+
+2024-09-11 13:32:12,341-__main__-INFO-服务启动
+
+2024-09-11 13:35:07,599-__main__-INFO-服务启动
+
+2024-09-11 13:35:17,046-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:35:17,403-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:36:21,817-__main__-INFO-服务启动
+
+2024-09-11 13:45:30,107-__main__-INFO-服务启动
+
+2024-09-11 13:50:06,277-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:50:19,382-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:50:43,115-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:50:43,123-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:50:58,219-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:50:58,227-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:51:14,800-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:51:14,809-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:51:29,941-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:51:29,949-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:51:45,134-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:51:45,142-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:52:00,278-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 13:52:00,288-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 
+2024-09-11 13:54:18,579-__main__-INFO-服务启动
+
+2024-09-11 15:00:43,592-__main__-INFO-receive from  = {"lfgawqyq_plc11_Tag23": 40.234, "lfgawqyq_plc11_Tag124": 40.264, "lfgawqyq_plc11_Tag25": 3.0, "lfgawqyq_plc11_Tag122": 40.264, "lfgawqyq_xn_cscod": 4.689, "lfgawqyq_xn_cstn": 10.503} 
+2024-09-11 15:00:47,558-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:02:44,702-__main__-INFO-receive from  = "{\"lfgawqyq_plc11_Tag23\": 40.234, \"lfgawqyq_plc11_Tag124\": 40.264, \"lfgawqyq_plc11_Tag25\": 3.0, \"lfgawqyq_plc11_Tag122\": 40.264, \"lfgawqyq_xn_cscod\": 4.689, \"lfgawqyq_xn_cstn\": 10.503}" 
+2024-09-11 15:02:45,010-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:04:23,784-__main__-INFO-receive from  = {'lfgawqyq_plc11_Tag23': 40.234, 'lfgawqyq_plc11_Tag124': 40.264, 'lfgawqyq_plc11_Tag25': 3.0, 'lfgawqyq_plc11_Tag122': 40.264, 'lfgawqyq_xn_cscod': 4.689, 'lfgawqyq_xn_cstn': 10.503} 
+2024-09-11 15:04:24,077-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:06:07,345-__main__-INFO-服务启动
+
+2024-09-11 15:07:36,110-__main__-INFO-服务启动
+
+2024-09-11 15:13:02,475-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 8.2, 'lfgawqyq_plc3_Tag20': 9, 'lfgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 15:13:02,827-__main__-INFO-return to request.remote_addr = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 15:13:18,095-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 8.2, 'lfgawqyq_plc3_Tag20': 9, 'lfgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 15:13:18,399-__main__-INFO-return to request.remote_addr = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 15:13:26,894-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 8.2, 'lfgawqyq_plc3_Tag20': 9, 'lfgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 15:13:27,180-__main__-INFO-return to request.remote_addr = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 15:14:24,594-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc3_Tag22': 8.2, 'lfgawqyq_plc3_Tag20': 9, 'lfgawqyq_plc10_Tag45': 9, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 15:14:24,889-__main__-INFO-return to request.remote_addr = [40.234, 40.264, 3.0, 40.264, 4.765, 10.547]
+ 
+2024-09-11 15:15:09,120-__main__-INFO-receive from request.remote_addr = {"lfgawqyq_plc11_Tag23": 40.234, "lfgawqyq_plc11_Tag124": 40.264, "lfgawqyq_plc11_Tag25": 3.0, "lfgawqyq_plc11_Tag122": 40.264, "lfgawqyq_xn_cscod": 4.689, "lfgawqyq_xn_cstn": 10.503} 
+2024-09-11 15:15:09,402-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:15:45,782-__main__-INFO-receive from request.remote_addr = "{\"lfgawqyq_plc11_Tag23\": 40.234, \"lfgawqyq_plc11_Tag124\": 40.264, \"lfgawqyq_plc11_Tag25\": 3.0, \"lfgawqyq_plc11_Tag122\": 40.264, \"lfgawqyq_xn_cscod\": 4.689, \"lfgawqyq_xn_cstn\": 10.503}" 
+2024-09-11 15:15:46,084-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:17:30,898-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc11_Tag23': 40.234, 'lfgawqyq_plc11_Tag124': 40.264, 'lfgawqyq_plc11_Tag25': 3.0, 'lfgawqyq_plc11_Tag122': 40.264, 'lfgawqyq_xn_cscod': 4.689, 'lfgawqyq_xn_cstn': 10.503} 
+2024-09-11 15:17:31,226-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:23:14,574-__main__-INFO-receive from request.remote_addr = {"lfgawqyq_plc11_Tag23": 40.234, "lfgawqyq_plc11_Tag124": 40.264, "lfgawqyq_plc11_Tag25": 3.0, "lfgawqyq_plc11_Tag122": 40.264, "lfgawqyq_xn_cscod": 4.689, "lfgawqyq_xn_cstn": 10.503} 
+2024-09-11 15:23:14,857-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:23:27,529-__main__-INFO-receive from request.remote_addr = {"lfgawqyq_plc11_Tag23": 40.234, "lfgawqyq_plc11_Tag124": 40.264, "lfgawqyq_plc11_Tag25": 3.0, "lfgawqyq_plc11_Tag122": 40.264, "lfgawqyq_xn_cscod": 4.689, "lfgawqyq_xn_cstn": 10.503} 
+2024-09-11 15:23:27,832-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:23:57,628-__main__-INFO-receive from request.remote_addr = {"lfgawqyq_plc11_Tag23": 40.234, "lfgawqyq_plc11_Tag124": 40.264, "lfgawqyq_plc11_Tag25": 3.0, "lfgawqyq_plc11_Tag122": 40.264, "lfgawqyq_xn_cscod": 4.689, "lfgawqyq_xn_cstn": 10.503} 
+2024-09-11 15:23:57,907-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:25:34,652-__main__-INFO-receive from request.remote_addr = {'lfgawqyq_plc11_Tag23': 40.234, 'lfgawqyq_plc11_Tag124': 40.264, 'lfgawqyq_plc11_Tag25': 3.0, 'lfgawqyq_plc11_Tag122': 40.264, 'lfgawqyq_xn_cscod': 4.689, 'lfgawqyq_xn_cstn': 10.503} 
+2024-09-11 15:25:34,934-__main__-INFO-传入的json串不正确
+
+2024-09-11 15:37:23,543-__main__-INFO-服务启动
+
+2024-09-11 15:37:35,298-__main__-INFO-服务启动
+
+2024-09-11 15:39:37,462-__main__-INFO-服务启动
+
+2024-09-11 15:39:40,748-__main__-INFO-receive from 127.0.0.1 = {'lfgawqyq_plc3_Tag22': 27.2063, 'lfgawqyq_plc3_Tag20': 16.8547, 'lfgawqyq_plc3_Tag17': 11, 'lfgawqyq_plc10_Tag45': 10.5263, 'lfgawqyq_plc10_Tag43': 9, 'lfgawqyq_plc10_Tag50': 9, 'lfgawqyq_plc10_Tag52': 9, 'lfgawqyq_plc10_Tag51': 9, 'lfgawqyq_plc10_Tag53': 9} 
+2024-09-11 15:39:41,068-__main__-INFO-return to 127.0.0.1 = [40.234, 40.264, 3.0, 40.264, 4.689, 10.503]
+ 

+ 49 - 0
writeDataToRealtimeData.py

@@ -0,0 +1,49 @@
+import psycopg2
+import json
+
+def upsert_realtime_data(cursor, data):
+    # 遍历字典中的每个键值对
+    for column_name, value in data.items():
+        # 检查是否存在具有特定 nm 值的行
+        cursor.execute("""
+               SELECT 1 FROM realtimedata WHERE nm = %s
+           """, (column_name,))
+        print('check realtime data')
+        exists = cursor.fetchone()
+
+        if exists:
+            # 如果存在,更新该行
+            cursor.execute("""
+                   UPDATE realtimedata
+                   SET v = %s
+                   WHERE nm = %s
+               """, (value, column_name))
+            print('Upsert realtime data')
+        else:
+            # 如果不存在,插入新行
+            cursor.execute("""
+                   INSERT INTO realtimedata (nm, v)
+                   VALUES (%s, %s)
+               """, (column_name, value))
+            print('Insert realtime data')
+
+    # 提交事务
+    cursor.connection.commit()
+
+# 示例使用
+data = {
+    "lfgawqyq_plc3_Tag17": 11.111,
+    "Ifgawqyq_plc3_Tag22": 8.2333,
+    "Ifgawqyq_plc3_Tag20": 9.222,
+    "Ifgawqyq_plc10_Tag45": 9.333,
+    "lfgawqyq_plc10_Tag43": 9.444,
+    "lfgawqyq_plc10_Tag50": 9.555,
+    "lfgawqyq_plc10_Tag52": 9.556,
+    "lfgawqyq_plc10_Tag51": 9.777,
+    "lfgawqyq_plc10_Tag53": 9.888
+}
+
+#
+# # 调用函数
+# upsert_realtime_data(cursor, data)
+#

+ 1 - 0
运行及挂载文件 (2).txt

@@ -0,0 +1 @@
+docker run -v F:/Volume/flask_water_quality/db_params.json:/app/db_params.json -p 8087:8087 flask_water_quality