liuxingchen 1 年之前
當前提交
e6fb522868

+ 73 - 0
001_h511/imageCapture/CPcapture.py

@@ -0,0 +1,73 @@
+# encoding: utf-8
+# This file create two thread, t1 capturing rstp video and save frame every interval, t2 read frame from database and
+# post to https server.
+import cv2
+import time
+import LogOut
+from mysqlDataBase import MysqldbOperational
+import configparser
+
+
+def capture_video(ipAddr, cameraName):
+    try:
+        rtspAddr = ipAddr
+        # print(rtspAddr)
+        cap = cv2.VideoCapture(rtspAddr)
+        cap.set(cv2.CAP_PROP_BUFFERSIZE, 0)
+        ret, image = cap.read()
+        while ret:
+            time.sleep(0.2)
+            cv2.imwrite('%s.jpg' % cameraName, image)
+            print('%s.jpg' % cameraName)
+            break
+    except Exception as e:
+        print('read %s error!' % ipAddr, cameraName)
+        _logger.error(e)
+        return e
+
+
+def read_camera_configuration():
+    list_camera = cameraSql.select('camera_configuration_table',
+                                   fields=["camera_name", "camera_ip", "camera_pass", "order_no", "camera_id"])
+    return list_camera
+
+
+def frequency_capture(frequency):
+    lastTime = 0
+    while True:
+        newTime = int(time.time())
+        time.sleep(1)
+        if lastTime + frequency <= newTime:
+            camera_list = read_camera_configuration()
+            for x in range(0, len(camera_list)):
+                capture_video(camera_list[x][1], camera_list[x][0])
+            lastTime = newTime
+
+
+if __name__ == '__main__':
+    time.sleep(10)
+    _logger = LogOut.Log('CPcapture')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的section标签
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+
+    # 获取特有配置项
+    section = "CPcapture"  # 读取的section标签
+    mysql_database = config.get(section, 'mysqlDatabase')
+
+    # 连接数据库
+    cameraSql = MysqldbOperational(host=mysql_host,
+                                   username=mysql_username,
+                                   password=mysql_password,
+                                   port=mysql_port,
+                                   database=mysql_database,
+                                   logger=_logger)
+    frequency_capture(20)

+ 200 - 0
001_h511/imageCapture/CPpost.py

@@ -0,0 +1,200 @@
+# This file create two thread, t1 capturing rstp video and save frame every interval, t2 read frame from database and post to https server.
+import configparser
+import time
+import pymysql
+import requests
+from requests_toolbelt.multipart.encoder import MultipartEncoder
+from mysqlDataBase import MysqldbOperational
+import LogOut
+import os
+
+
+def post(cameraList):
+    try:
+        headers = {
+            "Authorization": token,
+            "app-id": appId}
+        timestamp = time.strftime('%Y-%m-%d %H:%M:%S')
+        for x in range(0, len(cameraList)):
+            picture_name = '%s.jpg' % cameraList[x][0]
+            last_change_time = os.path.getmtime(picture_name)   # 最后一次修改时间
+            time_diff = (time.time()-last_change_time)/60       # 计算时间差(分钟)
+            if time_diff <= 60:
+                f = open(picture_name, 'rb')
+                img = f.read()
+                img = pymysql.Binary(img)
+                m = MultipartEncoder({'file': (picture_name, img, 'image/jpeg'),
+                                      "timestamp": str(timestamp),
+                                      "token": token,
+                                      "isImage": "1",
+                                      "cameraId": cameraList[x][4]})
+                headers["Content-Type"] = m.content_type
+                requests.urllib3.disable_warnings()
+                ret = requests.post('https://management.super-sight.com.cn:8000/system/api/v1/camera/add', headers=headers,
+                                    data=m, verify=False)
+                if ret.status_code == 200:
+                    print(timestamp, "post SUCCESS:", ret.text, ret.status_code)
+                else:
+                    print(timestamp, "post ERROR:", ret.text, ret.status_code)
+            else:
+                print(f"{timestamp}-[{picture_name}]: {int(time_diff/60)}小时未更新")
+    except Exception as e:
+        print(timestamp, "post ERROE", e)
+
+
+def post_extream(cameraList, startDate, endDate):
+    headers = {
+        "Authorization": token,
+        # 0cdf072c-7594-409d-a036-a5716d39b1f8",
+        "Content-Type": "application/json"}
+    for x in range(0, len(cameraList)):
+        data = {
+            "token": token,
+            "appId": appId,
+            "cameraId": cameraList[x][4],
+            "start": startDate,
+            "end": endDate
+        }
+        print(cameraList[x][4], startDate, endDate)
+        requests.urllib3.disable_warnings()
+        ret = requests.post('https://api.super-sight.com.cn:8000/system/v1/videoReceive/receiveVideoEmergency',
+                            headers=headers, json=data, verify=False)
+        if ret.status_code == 200:
+            print(ret.text, ret.status_code)
+        else:
+            print(ret.text, ret.status_code)
+
+
+
+def posterize_strategy():
+    lastTime = 0
+    lastTime1 = 0
+    lastTime2 = 0
+    while True:
+        time.sleep(1)
+        newTime = int(time.time())
+        timestamp = int(time.strftime('%H'))
+        timeNow = int(time.time())
+        if lastTime1 + 10 <= newTime:
+            camera_list = read_camera_configuration()
+            strategy_list = read_strategy()
+            modelKind = strategy_list[0][0]
+            posterizeKind = strategy_list[0][1]
+            posterizeStartDate = strategy_list[0][4]
+            posterizeEndDate = strategy_list[0][5]
+            posterizeUnit = strategy_list[0][2]
+            posterizeTime = strategy_list[0][3]
+            is_read()
+            lastTime1 = newTime
+        if int(modelKind) == 1:
+            if posterizeUnit == 'H':
+                _posterizeTime = posterizeTime * 60 * 60
+                if lastTime2 + _posterizeTime <= timeNow:
+                    startTime = timeNow
+                    endTime = timeNow + _posterizeTime
+                    post_extream(camera_list, startTime, endTime)
+                    lastTime2 = timeNow + 1
+            elif posterizeUnit == 'M':
+                _posterizeTime = posterizeTime * 60
+                if lastTime2 + _posterizeTime <= timeNow:
+                    startTime = timeNow
+                    endTime = timeNow + _posterizeTime
+                    post_extream(camera_list, startTime, endTime)
+                    lastTime2 = timeNow + 1
+            elif posterizeUnit == 'S':
+                _posterizeTime = posterizeTime
+                if lastTime2 + _posterizeTime <= timeNow:
+                    startTime = timeNow
+                    endTime = timeNow + _posterizeTime
+                    post_extream(camera_list, startTime, endTime)
+                    lastTime2 = timeNow + 1
+        elif int(modelKind) == 2:
+            if int(posterizeKind) == 1:
+                if posterizeUnit == 'H':
+                    _posterizeTime = posterizeTime * 60 * 60
+                    if lastTime + _posterizeTime <= newTime:
+                        post(camera_list)
+                        lastTime = newTime
+                elif posterizeUnit == 'M':
+                    _posterizeTime = posterizeTime * 60
+                    if lastTime + _posterizeTime <= newTime:
+                        print('---> post')
+                        post(camera_list)
+                        print('post down----')
+                        lastTime = newTime                       
+                elif posterizeUnit == 'S':
+                    _posterizeTime = posterizeTime
+                    if lastTime + _posterizeTime <= newTime:
+                        post(camera_list)
+                        lastTime = newTime
+            elif int(posterizeKind) == 2:
+                if timestamp >= int(posterizeStartDate) and timestamp <= int(posterizeEndDate):
+                    if posterizeUnit == 'H':
+                        _posterizeTime = posterizeTime * 60 * 60
+                        if lastTime + _posterizeTime <= newTime:
+                            post(camera_list)
+                            lastTime = newTime
+                    elif posterizeUnit == 'M':
+                        _posterizeTime = posterizeTime * 60
+                        if lastTime + _posterizeTime <= newTime:
+                            post(camera_list)
+                            lastTime = newTime
+                    elif posterizeUnit == 'S':
+                        _posterizeTime = posterizeTime
+                        if lastTime + _posterizeTime <= newTime:
+                            post(camera_list)
+                            lastTime = newTime
+            elif int(posterizeKind) == 3:
+                pass
+
+
+def read_camera_configuration():
+    list_camera = cameraSql.select('camera_configuration_table',
+                                   fields=["camera_name", "camera_ip", "camera_pass", "order_no", "camera_id"])
+    return list_camera
+
+
+def read_strategy():
+    list_strategy = cameraSql.select('camera_strategy_table',
+                                     fields=["model_kind", "posterize_kind", "posterize_unit", "posterize_time",
+                                             "posterize_start_date", "posterize_end_date"])
+    return list_strategy
+
+
+def is_read():
+    cond_dict = {"conf_type": 'camera_capture'}
+    params = {"is_read": "1"}
+    try:
+        cameraSql.update('camera_strategy_table', params, cond_dict)
+        return 'Success'
+    except:
+        return 'error'
+
+
+if __name__ == '__main__':
+    #time.sleep(10)
+    _logger = LogOut.Log('CPpost')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的section标签
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+    token = config.get(section, 'token')
+    appId = config.get(section, 'appId')
+    # 获取特有配置项
+    section = 'CPpost'
+    mysql_database = config.get(section, 'mysqlDatabase')
+
+    cameraSql = MysqldbOperational(host=mysql_host,
+                                   username=mysql_username,
+                                   password=mysql_password,
+                                   port=mysql_port,
+                                   database=mysql_database,
+                                   logger=_logger)
+    posterize_strategy()

+ 65 - 0
001_h511/imageCapture/LogOut.py

@@ -0,0 +1,65 @@
+import logging
+import time
+import os
+
+
+class Log(object):
+    def __init__(self, _pathName):
+        _pathName = _pathName + '-Log'
+        cur_path = os.path.dirname(os.path.realpath(__file__))
+        log_path = os.path.join(cur_path, _pathName)
+        # 如果不存在这个logs文件夹,就自动创建一个
+        if not os.path.exists(log_path): os.mkdir(log_path)
+        # 文件的命名
+        self.logname = os.path.join(log_path, '%s.log' % time.strftime('%Y_%m_%d'))
+        self.logger = logging.getLogger()
+        self.logger.setLevel(logging.DEBUG)
+        # 日志输出格式
+        self.formatter = logging.Formatter('[%(asctime)s]-%(levelname)s:%(message)s')
+
+    def __console(self, level, message):
+        # 创建一个FileHandler,用于写到本地
+        fh = logging.FileHandler(self.logname, 'a', encoding='utf-8')  # 这个是python3的
+        fh.setLevel(logging.DEBUG)
+        fh.setFormatter(self.formatter)
+        self.logger.addHandler(fh)
+
+        # 创建一个StreamHandler,用于输出到控制台
+        ch = logging.StreamHandler()
+        ch.setLevel(logging.DEBUG)
+        ch.setFormatter(self.formatter)
+        self.logger.addHandler(ch)
+
+        if level == 'info':
+            self.logger.info(message)
+        elif level == 'debug':
+            self.logger.debug(message)
+        elif level == 'warning':
+            self.logger.warning(message)
+        elif level == 'error':
+            self.logger.error(message)
+        # 这两行代码是为了避免日志输出重复问题
+        self.logger.removeHandler(ch)
+        self.logger.removeHandler(fh)
+        # 关闭打开的文件
+        fh.close()
+
+    def debug(self, message):
+        self.__console('debug', message)
+
+    def info(self, message):
+        self.__console('info', message)
+
+    def warning(self, message):
+        self.__console('warning', message)
+
+    def error(self, message):
+        self.__console('error', message)
+
+
+if __name__ == "__main__":
+    lo = Log('derviceName')
+    lo.info('this is info message!')
+    lo.debug('this is debug message!')
+    lo.warning('this is warning message!')
+    lo.error('this is error message!')

+ 103 - 0
001_h511/imageCapture/ca.crt

@@ -0,0 +1,103 @@
+-----BEGIN CERTIFICATE-----
+MIIGRDCCBSygAwIBAgIQf98imPqw+BdKunhXCK31NTANBgkqhkiG9w0BAQsFADCB
+jzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQD
+Ey5TZWN0aWdvIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB
+MB4XDTIxMDgwODAwMDAwMFoXDTIyMDkwODIzNTk1OVowHzEdMBsGA1UEAwwUKi5z
+dXBlci1zaWdodC5jb20uY24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCnJquNzsDlIvwR31PYCRbOx1SqAvX5tf6pobN8A60/J2AF0xSRTKCA74SdMfl/
+wLiTSVsadarw4JH47b4MNWe0FTuRZ3KGFQquy7W4CRVej+acqYl2zJyOOH/ErLiT
+YoKYJxJ101mGM4oxPcuYQpqT/l7MI3CTyWlEsi3jgrlofOS2Tab0YimTE+gN+9mY
+RHyCfDyxr6MLbtz9wSoDLhuuJQgkQn18ikgY3dD8oSPsnu0vVlYvMwPIhoBXElYA
+fsZM+F7J4ZtZ5EmEU0aX7BCo02KZYaHon/Ek9hmo3ekI/ptNPVvebWssY9LXw/Z8
+5BPRjpYLaCpxLQ2b1wPUT56XAgMBAAGjggMJMIIDBTAfBgNVHSMEGDAWgBSNjF7E
+VK2K4Xfpm/mbBeG4AY1h4TAdBgNVHQ4EFgQUbkGbbVnax8gBGaVLKUtnNum95YQw
+DgYDVR0PAQH/BAQDAgWgMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUH
+AwEGCCsGAQUFBwMCMEkGA1UdIARCMEAwNAYLKwYBBAGyMQECAgcwJTAjBggrBgEF
+BQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQIBMIGEBggrBgEF
+BQcBAQR4MHYwTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jcnQuc2VjdGlnby5jb20vU2Vj
+dGlnb1JTQURvbWFpblZhbGlkYXRpb25TZWN1cmVTZXJ2ZXJDQS5jcnQwIwYIKwYB
+BQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMDMGA1UdEQQsMCqCFCouc3Vw
+ZXItc2lnaHQuY29tLmNughJzdXBlci1zaWdodC5jb20uY24wggF9BgorBgEEAdZ5
+AgQCBIIBbQSCAWkBZwB2AEalVet1+pEgMLWiiWn0830RLEF0vv1JuIWr8vxw/m1H
+AAABeyQ9ql8AAAQDAEcwRQIgOPZKf+BULcLJJGuc09cjFvnpguLz66fbQNuEhO3l
+ApgCIQCQX8pj+yEAvc4ddr3Ce/TdDBEjZSOfTUs8z4AH/pNmHgB2AEHIyrHfIkZK
+EMahOglCh15OMYsbA+vrS8do8JBilgb2AAABeyQ9qi0AAAQDAEcwRQIhAN3JL9v/
+DwjcVqpX52UxvsWMJoBjX98x8m1YlkGmq4RIAiBgdHoTbjBx3pMuNN+puRgEajhu
+LNlN8hGKgyba/xTVfAB1ACl5vvCeOTkh8FZzn2Old+W+V32cYAr4+U1dJlwlXceE
+AAABeyQ9qgUAAAQDAEYwRAIgV3rxl8v9e0xocc+WAUMowGP0srgne7Ezq/xohMO/
+UxkCIAvVee+ehxq7mdPWKpaL/1kvbMQI3KNBXtA5yqGc/KevMA0GCSqGSIb3DQEB
+CwUAA4IBAQCQBoK7LyojUIjsSzhgBuKeyrM2bhE9m02Pl/zALig+GfuSM7Y+MEmF
+D0ucd1EeP8nt9Zq4LnE8x673BNHmMsHxhxmKFtcNf3JqOZ7oH7UZeq8Hig2tAKWj
+ct504OoZNabWiA+mtxCSkodYI0MzcEYLKqcIxHSq3YtlUbFBpGGHPJvGMb3p4reB
+LxTHZ522k2zabVBqlmDxSiDeHp89TcYZmA1VZ9Tu3i0lWqwMjf3q0HoS6UC5eNj1
+lyZ8RelRp1ABY45v3JePrU0AL6wYlbh2puD9ZQ7gajLY+EsMlx9NvTBnSSfgvo1c
+n08LwV14LxZckq8erpc7EiN0La5xTAPX
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIGEzCCA/ugAwIBAgIQfVtRJrR2uhHbdBYLvFMNpzANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTgx
+MTAyMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjCBjzELMAkGA1UEBhMCR0IxGzAZBgNV
+BAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UE
+ChMPU2VjdGlnbyBMaW1pdGVkMTcwNQYDVQQDEy5TZWN0aWdvIFJTQSBEb21haW4g
+VmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA1nMz1tc8INAA0hdFuNY+B6I/x0HuMjDJsGz99J/LEpgPLT+N
+TQEMgg8Xf2Iu6bhIefsWg06t1zIlk7cHv7lQP6lMw0Aq6Tn/2YHKHxYyQdqAJrkj
+eocgHuP/IJo8lURvh3UGkEC0MpMWCRAIIz7S3YcPb11RFGoKacVPAXJpz9OTTG0E
+oKMbgn6xmrntxZ7FN3ifmgg0+1YuWMQJDgZkW7w33PGfKGioVrCSo1yfu4iYCBsk
+Haswha6vsC6eep3BwEIc4gLw6uBK0u+QDrTBQBbwb4VCSmT3pDCg/r8uoydajotY
+uK3DGReEY+1vVv2Dy2A0xHS+5p3b4eTlygxfFQIDAQABo4IBbjCCAWowHwYDVR0j
+BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFI2MXsRUrYrhd+mb
++ZsF4bgBjWHhMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
+A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAbBgNVHSAEFDASMAYGBFUdIAAw
+CAYGZ4EMAQIBMFAGA1UdHwRJMEcwRaBDoEGGP2h0dHA6Ly9jcmwudXNlcnRydXN0
+LmNvbS9VU0VSVHJ1c3RSU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDB2Bggr
+BgEFBQcBAQRqMGgwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQudXNlcnRydXN0LmNv
+bS9VU0VSVHJ1c3RSU0FBZGRUcnVzdENBLmNydDAlBggrBgEFBQcwAYYZaHR0cDov
+L29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG9w0BAQwFAAOCAgEAMr9hvQ5Iw0/H
+ukdN+Jx4GQHcEx2Ab/zDcLRSmjEzmldS+zGea6TvVKqJjUAXaPgREHzSyrHxVYbH
+7rM2kYb2OVG/Rr8PoLq0935JxCo2F57kaDl6r5ROVm+yezu/Coa9zcV3HAO4OLGi
+H19+24rcRki2aArPsrW04jTkZ6k4Zgle0rj8nSg6F0AnwnJOKf0hPHzPE/uWLMUx
+RP0T7dWbqWlod3zu4f+k+TY4CFM5ooQ0nBnzvg6s1SQ36yOoeNDT5++SR2RiOSLv
+xvcRviKFxmZEJCaOEDKNyJOuB56DPi/Z+fVGjmO+wea03KbNIaiGCpXZLoUmGv38
+sbZXQm2V0TP2ORQGgkE49Y9Y3IBbpNV9lXj9p5v//cWoaasm56ekBYdbqbe4oyAL
+l6lFhd2zi+WJN44pDfwGF/Y4QA5C5BIG+3vzxhFoYt/jmPQT2BVPi7Fp2RBgvGQq
+6jG35LWjOhSbJuMLe/0CjraZwTiXWTb2qHSihrZe68Zk6s+go/lunrotEbaGmAhY
+LcmsJWTyXnW0OMGuf1pGg+pRyrbxmRE1a6Vqe8YAsOf4vmSyrcjC8azjUeqkk+B5
+yOGBQMkKW+ESPMFgKuOXwIlCypTPRpgSabuY0MLTDXJLR27lk8QyKGOHQ+SwMj4K
+00u/I5sUKUErmgQfky3xxzlIPK1aEn8=
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIIFgTCCBGmgAwIBAgIQOXJEOvkit1HX02wQ3TE1lTANBgkqhkiG9w0BAQwFADB7
+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYD
+VQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UE
+AwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTE5MDMxMjAwMDAwMFoXDTI4
+MTIzMTIzNTk1OVowgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5
+MRQwEgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBO
+ZXR3b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAgBJlFzYOw9sI
+s9CsVw127c0n00ytUINh4qogTQktZAnczomfzD2p7PbPwdzx07HWezcoEStH2jnG
+vDoZtF+mvX2do2NCtnbyqTsrkfjib9DsFiCQCT7i6HTJGLSR1GJk23+jBvGIGGqQ
+Ijy8/hPwhxR79uQfjtTkUcYRZ0YIUcuGFFQ/vDP+fmyc/xadGL1RjjWmp2bIcmfb
+IWax1Jt4A8BQOujM8Ny8nkz+rwWWNR9XWrf/zvk9tyy29lTdyOcSOk2uTIq3XJq0
+tyA9yn8iNK5+O2hmAUTnAU5GU5szYPeUvlM3kHND8zLDU+/bqv50TmnHa4xgk97E
+xwzf4TKuzJM7UXiVZ4vuPVb+DNBpDxsP8yUmazNt925H+nND5X4OpWaxKXwyhGNV
+icQNwZNUMBkTrNN9N6frXTpsNVzbQdcS2qlJC9/YgIoJk2KOtWbPJYjNhLixP6Q5
+D9kCnusSTJV882sFqV4Wg8y4Z+LoE53MW4LTTLPtW//e5XOsIzstAL81VXQJSdhJ
+WBp/kjbmUZIO8yZ9HE0XvMnsQybQv0FfQKlERPSZ51eHnlAfV1SoPv10Yy+xUGUJ
+5lhCLkMaTLTwJUdZ+gQek9QmRkpQgbLevni3/GcV4clXhB4PY9bpYrrWX1Uu6lzG
+KAgEJTm4Diup8kyXHAc/DVL17e8vgg8CAwEAAaOB8jCB7zAfBgNVHSMEGDAWgBSg
+EQojPpbxB+zirynvgqV/0DCktDAdBgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rID
+ZsswDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAG
+BgRVHSAAMEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuY29tb2RvY2EuY29t
+L0FBQUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDQGCCsGAQUFBwEBBCgwJjAkBggr
+BgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2RvY2EuY29tMA0GCSqGSIb3DQEBDAUA
+A4IBAQAYh1HcdCE9nIrgJ7cz0C7M7PDmy14R3iJvm3WOnnL+5Nb+qh+cli3vA0p+
+rvSNb3I8QzvAP+u431yqqcau8vzY7qN7Q/aGNnwU4M309z/+3ri0ivCRlv79Q2R+
+/czSAaF9ffgZGclCKxO/WIu6pKJmBHaIkU4MiRTOok3JMrO66BQavHHxW/BBC5gA
+CiIDEOUMsfnNkjcZ7Tvx5Dq2+UUTJnWvu6rvP3t3O9LEApE9GQDTF1w52z97GA1F
+zZOFli9d31kWTz9RvdVFGD/tSo7oBmF0Ixa1DVBzJ0RHfxBdiSprhTEUxOipakyA
+vGp4z7h/jnZymQyd/teRCBaho1+V
+-----END CERTIFICATE-----

+ 52 - 0
001_h511/imageCapture/config.ini

@@ -0,0 +1,52 @@
+[General]
+mysqlHost = localhost
+mysqlUsername = root
+mysqlPassword = R.!a@O&t9CjweWLSTr
+mysqlPort = 3306
+token = Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjY5ODE4MTksInVzZXJfbmFtZSI6IjEiLCJhdXRob3JpdGllcyI6WyJPUkdfMSIsIlJPTEVfMSIsIlVTRVJfMSIsIkRFUF9udWxsIl0sImp0aSI6ImEwYTk1YjQwLTBlYTAtNGVkMy04NzQ2LTcyNGYxMzE4OTZiZCIsImNsaWVudF9pZCI6InN5c3RlbS1jbGllbnQiLCJzY29wZSI6WyIqIl19.O_Yxqxo-RrEPY9l1zFQARazob-JMm0d1zW17sJ-3Kd-RPRcyDbEqFJghggel-M3aCQtVvj-wHjCxwdCDA0PUOoxOyNaZmcjgh27FGaCLw1Anwet3pC3cqtXN9mW5vsIOzvrwRThde345dK0p_qleE_ztE1wDmML_pJMCa9pORemu6DIB4Ctm8FgV5_lUQdAMXvBD_98-uXTMlIzmoRoypeM4Ykqu2Aa9n_av7B9ZPEA2ksqFHdm-FVn3Nfkg4Mzj1BEVzIEjSC5IU21TpHUDBcLSj0HPMCnyS21lxxcqt3JIxPtxa3eUlj678tCIeC2KVcucdeYzOQEGgNN5RE244g
+appId = 006
+
+[CPcapture]
+mysqlDatabase = camera_updata
+
+[CPpost]
+mysqlDatabase = camera_updata
+
+[iotServerMQTT]
+mysqlDatabase = centralized_control_db
+mqttHost = 219.146.135.163
+mqttPort = 8883
+mqttClientId = PUB_006
+mqttKey = 123456
+mqttUsername = marine
+mqttPassword = Neusoft123
+mqttTopic = hdbRecordV2
+mqttFrequency = 2
+
+[dataPackUp]
+mysqlDatabase = centralized_control_db
+
+[getconf]
+
+
+[api]
+mysqlDatabase = camera_updata
+
+[CPrecognizefish]
+mysqlDatabase = camera_updata
+
+[updateDeviceUploadPeriod]
+mysqlDatabase = test
+
+[biologyMonitor]
+mysqlHost = 192.168.1.53
+mysqlUsername = root
+mysqlPassword = 123456
+mysqlPort = 3306
+binocular_database = binocular_database
+sonar_database = sonar_database
+cageId = 1-006-002
+upperRange = 0-10
+middleRange = 10-20
+lowerRange = 20-30
+coefficient = 1

二進制
001_h511/imageCapture/configration_files/云平台导入海上平台摄像配置文件模板.xlsx


+ 370 - 0
001_h511/imageCapture/dataBase_api.py

@@ -0,0 +1,370 @@
+import pymysql
+import traceback
+import time
+import redis
+import LogOut
+#import mysql.connector
+#import MySQLdb 
+
+class Mysql:
+    _logger = LogOut.Log('mysql')
+    def __init__ (self,
+                  host   = '',
+                  user   = '',
+                  passwd = '',
+                  db     = '',
+                  port   = 3306,
+                  charset= 'utf8'
+                  ):
+        self.host   = host
+        self.user   = user
+        self.passwd = passwd
+        self.db     = db
+        self.port   = port
+        self.charset= charset
+        self.conn   = None
+        self._conn()  
+        
+    def _conn (self):
+        try:
+            self.conn = pymysql.connect(self.host, self.user, self.passwd, self.db, self.port,autocommit = True)
+            '''
+            self.conn = mysql.connector.connect(
+              host=self.host,
+              user=self.user,
+              passwd=self.passwd,
+              database=self.db
+            )
+            '''
+            '''
+            self.conn= MySQLdb.connect(
+                    host='127.0.0.1',
+                    port = 3306,
+                    user='root',
+                    passwd='zzZZ4144670..',
+                    db ='centralized_control_db',
+                    )
+            '''          
+                              
+            return True
+        except :
+            self._logger.error('in line 51:mysql connect is unsuccessful!')
+            return False
+
+    def _reConn (self,num = 28800,stime = 3): #重试连接总次数为1天,这里根据实际情况自己设置,如果服务器宕机1天都没发现就......
+        _number = 0
+        _status = True
+        while _status and _number <= num:
+            try:
+                self.conn.ping()       #cping 校验连接是否异常
+                _status = False
+            except:
+                self._logger.error('in line 62:mysql connect is unsuccessful!')
+                if self._conn()==True: #重新连接,成功退出
+                    _status = False
+                    break
+                _number +=1
+                time.sleep(stime)      #连接不成功,休眠3秒钟,继续循环,知道成功或重试次数结束
+                
+    def get_data_point(self,deviceName):
+        list = []
+        dict = {}
+        sql = "SELECT serial_number,io_point_name,address,read_function_code,write_function_code,data_type,offset,storage_type,protocol,dividend analytical_way \
+                FROM data_point_tbl where device_name = '%s'"%(deviceName)        
+        try:
+            self._reConn()            
+            self.cursor = self.conn.cursor() 
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                dict = {} 
+                dict['serialNumber'] = row[0]
+                dict['ioPointName'] = row[1]
+                dict['address'] = row[2]
+                dict['read_function_code'] = row[3]
+                dict['write_function_code'] = row[4]
+                dict['dataType'] = row[5]
+                dict['offset'] = row[6]
+                dict['storageType'] = row[7]
+                dict['protocol'] = row[8]
+                dict['dividend'] = row[9]
+                list.append(dict)
+            self.cursor.close()           
+            return list
+        except:
+            print(traceback.format_exc())
+            return False
+
+    def get_mqtt_point(self,deviceCode):
+        list = []
+        dict = {}
+        sql = "SELECT device_name,serial_number,storage_type,mqtt_code,low_limit,up_limit FROM data_point_tbl where device_code = '%s'"%(deviceCode)        
+        try:
+            self._reConn()            
+            self.cursor = self.conn.cursor() 
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                dict = {} 
+                dict['deviceName'] = row[0] 
+                dict['serialNumber'] = row[1]
+                dict['storageType'] = row[2]            
+                dict['mqttCode'] = row[3]
+                dict['lowLimit'] = row[4]
+                dict['upLimit'] = row[5]                                 
+                list.append(dict)
+            self.cursor.close()           
+            return list
+        except Exception as e:
+            print(e)
+            return False
+
+    def get_mqtt_devices(self):
+        list = []
+        sql = "SELECT DISTINCT device_code FROM data_point_tbl"      
+        try:
+            self._reConn()            
+            self.cursor = self.conn.cursor() 
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list.append(row[0])
+            self.cursor.close()           
+            return list
+        except:
+            print(traceback.format_exc())
+            return False
+			
+    def set_send_status(self,tableName,id,value):
+        sql = "UPDATE %s SET is_send = %s WHERE id = %s;"%(tableName,value,id)  
+        try:
+            self.cursor = self.conn.cursor()            
+            self.cursor.execute(sql)
+            # 提交到数据库执行
+            self.conn.commit()
+            self.cursor.close()
+        except Exception as e:
+            print(e)
+
+    def get_newest_data(self,tableName):
+        sql = "SELECT * FROM %s ORDER BY id DESC LIMIT 1;"%(tableName)
+        results = []      
+        try:
+            self.cursor = self.conn.cursor(cursor=pymysql.cursors.DictCursor) 
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()		
+            if len(results) > 0:          
+                return results[0]
+            else:
+                return results
+        except Exception as e:
+            print(e)
+            return None			
+ 
+    def get_rainfall_data(self):
+        list = []
+        sql = "SELECT c462, times FROM table_qxy WHERE times>='%s' limit 1"%(time.strftime("%Y-%m-%d 00:00:00", time.localtime()))   
+   
+        try:
+            self._reConn()            
+            self.cursor = self.conn.cursor() 
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list.append(row[0])
+            self.cursor.close()           
+            return list
+        except:
+            print(traceback.format_exc())
+            return False
+   
+    def create_point_table(self,list):
+        self.cursor = self.conn.cursor() 
+        for index in range(len(list)):
+            tableName = "table_"+str(list[index]['serialNumber'])
+            dataType = list[index]['storageType']
+            sql = "CREATE TABLE IF NOT EXISTS %s (times datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,data %s not null,INDEX (times)) \
+                ENGINE=InnoDB DEFAULT CHARSET=utf8;"%(tableName,dataType)
+            try:
+                self.cursor.execute(sql)
+            except:
+                print(traceback.format_exc())
+        self.cursor.close()
+
+    def create_delete_stale_data_event(self,eventName,tableName,day):
+        self.cursor = self.conn.cursor()
+        sql = "create event %s on SCHEDULE every 1 day do delete from %s where times<(CURRENT_TIMESTAMP() + INTERVAL -%s DAY);"%(eventName,tableName,day)
+        self.cursor.execute(sql)
+        self.cursor.close()    
+        
+    def create_many_column_table_NOTNULL(self,tableName,list):
+        self.cursor = self.conn.cursor() 
+        for index in range(len(list)):
+            dataType = list[index]['storageType']
+            columnName = "c"+str(list[index]['serialNumber'])
+            sql_c = "CREATE TABLE IF NOT EXISTS %s (times datetime NOT NULL,INDEX (times)) \
+                ENGINE=InnoDB DEFAULT CHARSET=utf8;"%(tableName)
+            sql_add = "ALTER TABLE %s ADD %s %s NOT NULL"%(tableName,columnName,dataType)    
+            try:
+                self.cursor.execute(sql_c)
+                self.cursor.execute(sql_add)
+            except:
+                print(traceback.format_exc())
+        self.cursor.close()
+        
+    def create_many_column_table(self,tableName,list):
+        self.cursor = self.conn.cursor() 
+        for index in range(len(list)):
+            dataType = list[index]['storageType']
+            columnName = "c"+str(list[index]['serialNumber'])
+            sql_c = "CREATE TABLE IF NOT EXISTS %s (times datetime NOT NULL,INDEX (times)) \
+                ENGINE=InnoDB DEFAULT CHARSET=utf8;"%(tableName)
+            sql_add = "ALTER TABLE %s ADD %s %s "%(tableName,columnName,dataType)    
+            try:
+                self.cursor.execute(sql_c)
+                self.cursor.execute(sql_add)
+            except:
+                print(traceback.format_exc())
+        self.cursor.close()                 
+              
+    def save_point_data(self,tableName,data):
+        sql = "INSERT INTO %s (data)VALUES(%s);"%(tableName,data)   
+        try:
+            self.cursor.execute(sql)
+            # 提交到数据库执行
+            self.conn.commit()
+        except:
+            # 如果发生错误则回滚
+            self.conn.rollback()
+    
+    def insert_column_many(self,tableName,timeNow,list):
+        try:       
+            self.cursor = self.conn.cursor()
+            sql = "INSERT INTO %s"%(tableName)
+            for index in range(len(list)):
+                if index == 0:
+                    columnName = "c"+str(list[index]['serialNumber'])
+                    sql = sql + "(times,"+columnName+"," 
+                elif index == len(list)-1:
+                    columnName = "c"+str(list[index]['serialNumber'])
+                    sql = sql + columnName+")"
+                else:
+                    columnName = "c"+str(list[index]['serialNumber'])
+                    sql = sql + columnName + ","  
+            
+            for index in range(len(list)):
+                if index == 0:
+                    data = "VALUE ('"+str(timeNow)+"'," + str(list[index]['data']) + ","
+                    sql = sql + data 
+                elif index == len(list)-1:
+                    data = str(list[index]['data']) + ")"
+                    sql = sql + data
+                else:
+                    data = str(list[index]['data']) + ","
+                    sql = sql + data
+            #print(sql) 
+            try:           
+                self.cursor.execute(sql)
+                # 提交到数据库执行
+                self.conn.commit()
+            except Exception as e:
+                # 如果发生错误则回滚
+                self.conn.rollback()
+                print(e)                 
+        except Exception as e:
+            self._reConn()         
+            print(e)        
+        else:    
+            self.cursor.close()      
+    
+    def onLineState_insert(self, point, name, state):
+        try:       
+            self.cursor = self.conn.cursor()
+            times = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(time.time())))
+            sql = "INSERT INTO table_connection_status(io_point, \
+                   driver_name, data_time, state) \
+                   VALUES ('%s', '%s',  '%s',  %s)" % \
+                   (point, name, times, state)
+            try:           
+                self.cursor.execute(sql)
+                # 提交到数据库执行
+                self.conn.commit()
+            except Exception as e:
+                # 如果发生错误则回滚
+                self.conn.rollback()
+                print(e)                 
+        except Exception as e:
+            self._reConn()         
+            print(e)        
+        else:    
+            self.cursor.close() 
+            
+    def close (self):
+        self.conn.close()
+        
+        
+class RedisCtr:
+    def __init__ (self, 
+                  _host   = '',
+                  _port   = 6379,
+                  _db     = '',
+                  _decode_responses=True):
+        self.host = _host
+        self.port = _port
+        self.db = _db
+        self.decode_responses = _decode_responses
+        self.r = None
+        self._conn()
+    def _conn(self):
+        self.r = redis.StrictRedis(host=self.host, port=self.port, db=self.db, decode_responses=self.decode_responses)
+    def redisSave(self, dataList):
+        try:
+            pipe = self.r.pipeline(transaction=True)
+            for index in range(len(dataList)):               
+                key = "c"+str(dataList[index]['serialNumber'])
+                data = dataList[index]['data']   
+                pipe.set(key,data)                                      
+            pipe.execute()     
+        except Exception as e:                 
+            return e               
+        else:
+            return True        
+         
+    def connectStatusRedisSave(self, key, data):
+        try:
+            pipe = self.r.pipeline(transaction=True)               
+            pipe.set(key,data)                                      
+            pipe.execute()     
+        except Exception as e:                 
+            return e               
+        else:
+            return True
+        
+    def readLastStatus(self, key):
+        try:
+            pipe = self.r.pipeline(transaction=True)
+            pipe.get(key)
+            result = pipe.execute()
+            return int(result[0])
+        except Exception as e:                 
+            print(e)              
+        else:
+            print('e')
+
+def redisSave(dataList,conn):
+        try:
+            pipe = conn.pipeline(transaction=True)
+            for index in range(len(dataList)):               
+                key = "c"+str(dataList[index]['serialNumber'])
+                data = dataList[index]['data']   
+                pipe.set(key,data)                                      
+            pipe.execute()     
+        except Exception as e:
+            print(e)                    
+            return e               
+        else:
+            return True
+        

+ 277 - 0
001_h511/imageCapture/dataPackUp.py

@@ -0,0 +1,277 @@
+import time
+import configparser
+import datetime
+from mysqlDataBase import MysqldbOperational
+import os
+import zipfile
+import copy
+import requests
+import LogOut
+import urllib3
+
+def get_txt_name(beginTime, code):
+    # 获取txt文件名
+    txt_name = code + '-' + str(int(beginTime) * 1000) + '.txt'
+    return txt_name
+
+
+def delete_txt(file_path):
+    # 删除txt文件及文件夹
+    txt_file_list = os.listdir(file_path)
+    for txt in txt_file_list:
+        os.remove(os.path.join(file_path, txt))
+    os.rmdir(file_path)
+
+
+def get_zip_name():
+    # 获取zip包名
+    zip_name = PLATFORM_ID + '-' + str(int(time.time() * 1000)) + '000' + '.zip'
+    return zip_name
+
+
+def make_zip(file_path):
+    # 组包
+    # 参数:file_path, 包含txt的目录
+    # 返回:zip包文件名
+
+    # txt文件名列表
+    txt_file_list = os.listdir(file_path)
+
+    # zip包文件名
+    zip_name = "HDU/" + get_zip_name()
+    zp = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
+    for txt_file in txt_file_list:
+        txt_file_path = os.path.join(file_path, txt_file)
+        # 打开txt,写入zip
+        with open(txt_file_path, 'r') as f:
+            zp.write(txt_file_path, txt_file)
+        os.remove(txt_file_path)
+        # 关闭zip包
+    zp.close()
+    # 删除txt文件
+    # delete_txt(file_path)
+    return zip_name
+
+
+def dateAndTimeToTimestamp(date_time):
+    time_array = time.strptime(date_time, "%Y-%m-%d %H:%M:%S")
+    time_stamp = int(time.mktime(time_array))
+    return time_stamp
+
+
+def getCodeAndPoint(addrData):
+    str = "."
+    code = addrData[:addrData.index(str)]
+    point = addrData[addrData.index(str) + 1:]
+    return code, point
+
+
+def getMqttDataFromMysqlHistory(data_list, code_list):
+    dataList = []
+    is_send_0 = []
+    for index in range(len(data_list)):
+        date_time = data_list[index]['times']
+        # date_time = dateAndTimeToTimestamp(date_time)
+        # print(date_time)
+        dataDist = {}
+        code = ''
+        dataDist['DQ_DI'] = '0'
+        dataDist['STS_DI'] = '0'
+        for i in range(len(code_list)):
+            # print(code_list[i])
+            code, point = getCodeAndPoint(code_list[i]['mqttCode'])
+            dataDist[point] = str(data_list[index]["c" + str(code_list[i]['serialNumber'])])
+            if code_list[i]['lowLimit'] != None and code_list[i]['upLimit'] != None:
+                if dataDist[point] != 'None':
+                    if dataDist[point] is None or float(dataDist[point]) < code_list[i]['lowLimit'] or float(dataDist[point]) > code_list[i]['upLimit']:
+                        # dataDist['DQ_DI'] = '1'     # 功能优化
+                        dataDist.pop(point)     # 功能优化,过滤坏数据
+
+            if code_list[i]['storageType'] == "datetime":
+
+                try:
+                    timeArray = time.strptime(dataDist[point], "%Y-%m-%d %H:%M:%S")
+
+                    timeStamp = int(time.mktime(timeArray) * 1000)
+                    dataDist[point] = timeStamp
+
+                except Exception as e:
+                    dataDist['DQ_DI'] = '1'
+                    dataDist[point] = '0'
+                    print(e)
+
+        dataDist['code'] = code
+        dataDist['ts'] = date_time * 1000
+        dataList.append(dataDist)
+        # param = json.dumps(dataList)
+
+    for data in data_list:
+        is_send_0.append(data["id"])
+    return dataList, is_send_0
+
+
+def data_alignment_date_and_time(data_list, begin_timestamp, end_timestamp, frequency):
+    all_dict = {}
+    lists = []
+    for index in range(begin_timestamp, end_timestamp):
+        all_dict[index] = None
+    all_dict[begin_timestamp] = data_list[0]
+    all_dict[end_timestamp] = data_list[len(data_list) - 1]
+    for index in range(len(data_list)):
+        timeArray = time.strptime(str(data_list[index]['Date']) + " " + str(data_list[index]['Time']),
+                                  "%Y-%m-%d %H:%M:%S")
+        dataTime = int(time.mktime(timeArray))
+        all_dict[dataTime] = data_list[index]
+    for index in range(begin_timestamp, end_timestamp):
+        if all_dict[index] == None:
+            all_dict[index] = copy.deepcopy(all_dict[index - 1])
+    for index in range(begin_timestamp, end_timestamp):
+        if index % frequency == 0:
+            all_dict[index]['times'] = index
+            lists.append(all_dict[index])
+    return lists
+
+
+def data_alignment(data_list, begin_timestamp, end_timestamp, frequency):
+    all_dict = {}
+    lists = []
+    for index in range(begin_timestamp, end_timestamp):
+        all_dict[index] = None
+    all_dict[begin_timestamp] = data_list[0]
+    all_dict[end_timestamp] = data_list[len(data_list) - 1]
+    for index in range(len(data_list)):
+        timeArray = time.strptime(str(data_list[index]['times']), "%Y-%m-%d %H:%M:%S")
+        dataTime = int(time.mktime(timeArray))
+        all_dict[dataTime] = data_list[index]
+    for index in range(begin_timestamp, end_timestamp):
+        if all_dict[index] == None:
+            all_dict[index] = copy.deepcopy(all_dict[index - 1])
+        else:
+            all_dict[index] = copy.deepcopy(all_dict[index])
+    for index in range(begin_timestamp, end_timestamp):
+        if index % frequency == 0:
+            all_dict[index]['times'] = index
+            lists.append(all_dict[index])
+    return lists
+
+
+def post(zip_file):
+    headers = {
+        "Authorization": token,
+        "Content-Type": "application/json"}
+    data = {"platformId": PLATFORM_ID,
+            "fileNames": zip_file
+            }
+    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+    # print(zip_file)
+    # print('timestamp: ',datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
+    try:
+        ret = requests.post('https://management.super-sight.com.cn/device/api/v2/device/history', headers=headers,json=data, verify=False)
+    except Exception as e:
+        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())+"[ERROR] {0}\n".format(e))
+
+    if ret.status_code == 200:
+        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), ret.text, ret.status_code, 'len(zip_file)=', len(zip_file))
+        return "SUCCESS"
+    else:
+        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), ret.text, ret.status_code)
+        return "FAIL"
+
+
+if __name__ == "__main__":
+    _logger = LogOut.Log('dataPackUp')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的section标签
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+    token = config.get(section, 'token')
+    PLATFORM_ID = config.get(section, 'appId')
+
+    # 读取专有配置项
+    section = 'dataPackUp'
+    mysql_database = config.get(section, 'mysqlDatabase')
+
+    post_time = 0
+    pack_time = 0
+    mysql_object = MysqldbOperational(host=mysql_host,
+                                      username=mysql_username,
+                                      password=mysql_password,
+                                      port=mysql_port,
+                                      database=mysql_database,
+                                      logger=_logger)
+    list_devices = mysql_object.get_devices_name()
+    count = mysql_object.get_mqtt_devices_count()
+    # print(list_devices)
+    txt_path = "cache"
+    if not os.path.exists(txt_path):
+        os.mkdir(txt_path)
+    while True:
+        # time.sleep(1)
+        if post_time < time.time() - 3600:
+            zip_list = []
+            flie_name = os.listdir("HDU/")
+            for filenames in flie_name:
+                if filenames.endswith('.zip') == True:
+                    zip_list.append(filenames)
+            if len(zip_list) > 0:
+                # pass
+                result = post(zip_list)
+                post_time = time.time()
+                print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + ":" + str(result))
+
+        if pack_time < time.time() - 3600:
+            i = 0
+            while i < max(int(200 / count), 1):
+                for device_name in list_devices:
+                    code_devices = mysql_object.get_mqtt_devices_from_name(device_name)
+                    # 鏋勯?犺〃鍚嶇О锛屽table_fg
+                    table_name = 'table_' + device_name
+                    # 鑾峰彇鏂偣鏃堕棿
+                    break_point = mysql_object.get_breakpoint_last_time_datetime(table_name)
+                    if break_point != None:
+                        # 构造表名称,如table_fg
+                        table_name = 'table_' + device_name
+                        # 获取断点时间
+                        break_point = mysql_object.get_breakpoint_last_time_datetime(table_name)
+                        if break_point != None:
+                            # 找到断点时间前后一个小时的时间点
+                            timeArray = time.strptime(str(break_point['times']), "%Y-%m-%d %H:%M:%S")
+                            begin = time.strftime("%Y-%m-%d %H:00:00", timeArray)
+                            end = time.strftime("%Y-%m-%d %H:59:59", timeArray)
+                            begin_timeArray = time.strptime(str(begin), "%Y-%m-%d %H:%M:%S")
+                            end_timeArray = time.strptime(str(end), "%Y-%m-%d %H:%M:%S")
+                            begin_timestamp = int(time.mktime(begin_timeArray))
+                            end_timestamp = int(time.mktime(end_timeArray))
+                            # 获取断点前后一个小时的数据
+                            data_list = mysql_object.get_hour_data_datetime(table_name, begin, end)
+                            history_data_list = data_alignment(data_list, begin_timestamp, end_timestamp, 2)
+                            if len(code_devices) >= 1:
+                                for index in range(len(code_devices)):
+                                    # 获取设备码表
+                                    code_list = mysql_object.get_mqtt_point(code_devices[index])
+                                    param, id = getMqttDataFromMysqlHistory(history_data_list, code_list)
+                                    txt_name = get_txt_name(begin_timestamp, param[0]["code"])
+                                    # 将txt_path目录下所有设备txt组包
+                                    if len(os.listdir(txt_path)) >= 20:
+                                        zip_name = make_zip(txt_path)
+                                        time.sleep(5)
+                                    with open(os.path.join(txt_path, txt_name), 'w') as f:
+                                        txt_content = [str(line) + '\n' for line in param]
+                                        f.writelines(txt_content)
+                                    time.sleep(1)
+                                    # print(zip_name)
+                                    if index == len(code_devices) - 1:
+                                        # pass
+                                        mysql_object.set_many_send_status(table_name, data_list)
+                i += 1
+            pack_time = time.time()
+            if len(os.listdir(txt_path)) > 0:
+                zip_name = make_zip(txt_path)
+                time.sleep(5)

+ 25 - 0
001_h511/imageCapture/fwtest.py

@@ -0,0 +1,25 @@
+# encoding: utf-8
+import cv2
+import time
+
+if __name__ == '__main__':
+
+    rtspAddr = "rtsp://admin:w88888888@192.168.1.27:554/h264/ch18/main/av_stream"
+    cameraName = "test_"
+    while True:
+        try:
+            cap = cv2.VideoCapture(rtspAddr)
+            # cap.set(cv2.CAP_PROP_BUFFERSIZE, 0)
+            ret, image = cap.read()
+            print(ret)
+            i = 1
+            while ret:
+                time.sleep(10)
+                cv2.imwrite('%s%s.jpg' % (cameraName, i), image)
+                print('%s.jpg' % cameraName)
+                i = i + 1
+            cv2.destroyAllWindows()
+            cap.release()
+        except Exception as e:
+            print("e=", e)
+            print('read %s error!' % rtspAddr, cameraName)

+ 267 - 0
001_h511/imageCapture/getconf.py

@@ -0,0 +1,267 @@
+import datetime
+import json
+import pymysql
+import os
+import sys
+import time
+import requests
+import base64
+import configparser
+from sanic import Sanic
+from sanic.response import text, json
+from sanic_cors import CORS, cross_origin
+from sanic import response
+from mysqlDataBase import MysqldbOperational
+from configobj import ConfigObj
+
+app = Sanic(__name__)
+CORS(app)
+
+@app.route('/marinePlatform/v1/devices/frameExtractionSetting', methods=['POST'])
+async def capture_getconf(request):
+    result = updata_conf(request.json)
+    return response.text(result)
+
+
+def update_sql_splicing(tablename, attrs_dict, cond_dict):
+    """更新数据
+        args:
+            tablename  :表名字
+            attrs_dict  :更改属性键值对字典
+            cond_dict  :更新条件字典
+
+        example:
+            params = {"name" : "caixinglong", "age" : "38"}
+            cond_dict = {"name" : "liuqiao", "age" : "18"}
+            mydb.update(table, params, cond_dict)
+    """
+    attrs_list = []
+    consql = ' '
+    for y in attrs_dict:
+        if not isinstance(attrs_dict[y], str):
+            attrs_dict[y] = str(attrs_dict[y])
+    for x in cond_dict:
+        if not isinstance(cond_dict[x], str):
+            cond_dict[x] = str(cond_dict[x])
+    for tmpkey, tmpvalue in attrs_dict.items():
+        attrs_list.append("`" + tmpkey + "`" + "=" + "\'" + tmpvalue + "\'")
+    attrs_sql = ",".join(attrs_list)
+    #print("attrs_sql:", attrs_sql)
+    if cond_dict != '':
+        for k, v in cond_dict.items():
+            if isinstance(v, str):
+                v = "\'" + v + "\'"
+            consql = consql + "`" + tablename + "`." + "`" + k + "`" + '=' + v + ' and '
+    consql = consql + ' 1=1 '
+    sql = "UPDATE %s SET %s where%s" % (tablename, attrs_sql, consql)
+    #print(sql)
+    return sql
+
+def updata_conf(json_in):
+    cond_dict = {"conf_type": 'camera_capture'}
+    json_in["is_read"] = "0"
+    try:
+        db = pymysql.connect(mysql_host, mysql_username, mysql_password, mysql_database)
+        sql = update_sql_splicing('camera_strategy_table', json_in, cond_dict)
+        cursor = db.cursor()
+        cursor.execute(sql)
+        db.commit()
+        db.close()
+        return 'SUCCESS'
+    except:
+        return 'ERROR'
+
+
+@app.route('/marinePlatform/v2/data/history', methods=['POST'])
+async def delete_file(request):
+    try:
+        if request.json['token'] == token:
+            result = find_and_delete_file(file_dir,request.json['fileNames'])
+            return response.text(result)
+        else:
+            #return response.text('ERROR')
+            return response.text('Token not exist')
+
+    except:
+        #return response.text('ERROR')
+        return response.text('data format error!')
+
+
+def find_and_delete_file(file_dir,name_list):
+    #result_list = []
+    file_exists = True
+    for index in range(0,len(name_list)):
+        if os.path.exists(file_dir+name_list[index]) == False:
+            file_exists = False
+            #return "ERROR"
+            return "error " + file_dir+name_list[index] + " not find"
+    if file_exists == True:
+        for index in range(0,len(name_list)):
+            #result_dict = {}
+            result = delete_single_file(file_dir,name_list[index])
+            #result_dict["file_name"] = result_dict
+            #result_dict["delete"] = result
+            #result_list.append(result_dict)
+        return "SUCCESS"
+        #return result_list
+
+
+def delete_single_file(file_dir,file_name):
+    try:
+        os.remove(file_dir+file_name)
+        return True
+    except:
+        return False 
+
+
+
+
+# ===============================================================================
+# =================================== 新增部分 ===================================
+# ===============================================================================
+
+
+@app.route('/marinePlatform/v1/app/appToken', methods=['POST'])
+async def update_token(request):
+    """
+    下行数据:下发平台验证token
+    :param request:
+    :return:
+    """
+    print("下发平台验证token request.json=", request.json)
+    if request.json['old-token'] == token:
+        # noinspection PyBroadException
+        try:
+            change_config = ConfigObj("config.ini", encoding='UTF8')
+            # 修改配置文件中的token
+            change_config['General']['token'] = request.json['token']
+            change_config.write()
+
+            result = "SUCCESS"
+        except Exception as e:
+            print("e=", e)
+            result = "ERROR"
+    else:
+        result = "token 验证失败!"
+    print("下发平台验证token result", result)
+    return response.text(result)
+
+
+
+@app.route('/marinePlatform/v1/data/extremeModeSetting', methods=['POST'])
+async def set_extreme_mode(request):
+    """
+    设置极端模式规则
+    :param request:
+    :return:
+    """
+    if request.json['token'] == token:
+        extreme_case_make_id = request.json["extreme_case_make_id"]
+        posterize_rule = request.json["posterize_rule"]
+        '''未完成...'''
+    else:
+        print("token 验证失败!")
+
+
+
+@app.route('/marinePlatform/v1/devices/delFrameExtraction', methods=['POST'])
+async def del_camera(request):
+    """
+    下行数据:删除摄像头
+    :param request:
+    :return:
+    """
+    print("删除摄像头 request.json=", request.json)
+
+    receive_args = request.json
+    if receive_args['token'] == token:
+        if "id" in request.json.keys():
+            camera_id = receive_args["id"]
+            del_sql = "DELETE FROM camera_configuration_table WHERE camera_id in %s;"
+            if camera_configuration_sql.commit_sql(del_sql, camera_id):
+                result = "SUCCESS"
+            else:
+                result = "ERROR"
+        else:
+            result = "未传入摄像头id"
+    else:
+        result = "token 验证失败!"
+    print("删除摄像头 result", result)
+    return response.text(result)
+
+
+
+@app.route('/marinePlatform/v1/devices/setVideoRecognize', methods=['POST'])
+async def camera_image_recognize_conf(request):
+    """
+    下行数据:设置摄像头图像识别
+    :param request:
+    :return:
+    """
+    print("设置摄像头图像识别 request.json=", request.json)
+    result = process_args(request.json)
+    print("设置摄像头图像识别 result", result)
+
+    return response.text(result)
+
+
+
+
+def process_args(receive_args):
+    """
+    处理接收到的参数
+    :param receive_args:
+    :return:
+    """
+    if receive_args['token'] == token:
+        value = []
+        value.append(receive_args["camera_id"])
+        value.append(int(receive_args["recognize_rate"]))
+        value.append(receive_args["camera_ip"])
+        value.append(int(receive_args["nvr_port"]))
+        value.append(receive_args["user_name"])
+        value.append(receive_args["password"])
+        value.append(receive_args["channel_id"])
+
+        insert_sql = "INSERT INTO camera_configuration_table " \
+                     "(camera_id,recognize_rate,camera_ip,nvr_port, user_name,password,channel_id) " \
+                     "VALUES %s;"
+        if camera_configuration_sql.commit_sql(insert_sql, value):
+            result = "SUCCESS"
+        else:
+            result = "ERROR"
+    else:
+        result = "token 验证失败!"
+    return result
+
+
+
+
+
+
+
+if __name__ == "__main__":
+    file_dir = r'/home/sencott/imageCapture/HDU/'
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的部section标签
+    token = config.get(section, 'token')
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+
+    # 获取特有配置项
+    mysql_database = config.get('api', 'mysqlDatabase')
+    camera_configuration_sql = MysqldbOperational(host=mysql_host,
+                                                   username=mysql_username,
+                                                   password=mysql_password,
+                                                   port=mysql_port,
+                                                   database=mysql_database)
+
+
+    app.run(host="0.0.0.0", port=8765, workers=1, debug=False, access_log=False)

+ 147 - 0
001_h511/imageCapture/identify_fish.py

@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+# @CreateTime: 2021/7/21 11:08
+# @Author: lxc
+# @LastEditTime:
+# @Desctiption: 上行数据:上传识别图像到云平台
+"""
+
+import time
+import threading
+import json
+import configparser
+import cv2
+import requests
+import LogOut
+from mysqlDataBase import MysqldbOperational
+
+
+
+class MyThread(threading.Thread):
+    """
+    连接摄像头的线程
+    """
+    def __init__(self, camera, bearer_token):
+        threading.Thread.__init__(self)
+        self._camera_ip = camera[1]
+        self._camera_id = camera[2]
+        self._token = bearer_token
+        self._recognize_rate = camera[4]
+
+
+    def run(self):
+        while True:
+            self.recognize_fish()
+
+
+    def recognize_fish(self):
+        """
+        识别是否有鱼
+        :return:
+        """
+        time.sleep(0.2)
+        time_standard = "%Y-%m-%d %H:%M:%S"
+        try:
+            cap = cv2.VideoCapture(self._camera_ip)
+            ret, frame = cap.read()
+
+            timing = 0      # 计时 --- 识别是否有鱼
+            run_time = 0    # 识别频率
+            while True:
+                new_time = time.time()
+                if new_time - run_time > self._recognize_rate:
+                    run_time = new_time
+                    gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)  # 灰度化
+                    gaus_img = cv2.GaussianBlur(gray_img, (1, 1), 0)  # 高斯滤波
+                    retval, dst = cv2.threshold(gaus_img, 100, 255, cv2.THRESH_BINARY)  # 二值化
+                    # image, contours, hierarchy = cv2.findContours(dst, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 找轮廓 opencv3
+                    contours, hierarchy = cv2.findContours(dst, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 找轮廓 opencv2
+
+                    fish_sign = 1   # 没有鱼
+                    for contour in contours:
+                        if cv2.contourArea(contour) > 1800:
+                            fish_sign = 0   # 发现有鱼
+                            break
+
+                    # 未开始计时且有鱼 ---> 开始计时
+                    # 已开始计时且无鱼 ---> 计时归0,上传时间戳
+                    # 已开始计时且时长大于15min ---> 计时归0,上传时间戳
+                    if timing == 0 and fish_sign == 0:
+                        timing = time.time()
+                    elif timing != 0 and (fish_sign == 1 or time.time() - timing > 15*60):
+                        start_time = time.strftime(time_standard, time.localtime(timing))
+                        end_time = time.strftime(time_standard, time.localtime(time.time()))
+                        self.post(start_time, end_time)
+                        timing = 0
+
+            cap.release()
+        except Exception as e:
+            _logger.error('%s --- failed --- %s' % (self._camera_ip, e))
+            self.run()
+
+
+
+    def post(self, begin, end):
+        """
+        上传识别到鱼的时间段
+        :param begin: 起始时间
+        :param end: 结束时间
+        :return: 结果
+        """
+        headers = {
+            "Authorization": self._token,
+            "Content-Type": "application/json"}
+        data = {
+            "cameraID": self._camera_id,
+            "dateStart": begin,
+            "dateEnd": end}
+
+        _logger.info("headers=%s" % (headers))
+        _logger.info("data=%s" % (json.dumps(data)))
+
+        requests.urllib3.disable_warnings()
+        url = "https://management.super-sight.com.cn:8000/system/api/v1/videoReceive/receiveVideo"
+        ret = requests.post(url=url, headers=headers, data=json.dumps(data), verify=False)
+        if ret.status_code == 200:
+            print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), ret.text, ret.status_code, "    dateStart=", begin, "dateEnd=", end)
+            _logger.info("ret.text=%s" % (ret.text))
+            _logger.info("ret.status_code=%s" % (ret.status_code))
+        else:
+            print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), ret.text, ret.status_code)
+            _logger.error("ret.text=%s" % (ret.text))
+            _logger.error("ret.status_code=%s" % (ret.status_code))
+
+
+if __name__ == '__main__':
+    time.sleep(1)
+    _logger = LogOut.Log('identify_fish')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    mysql_host = config.get("General", 'mysqlHost')
+    mysql_username = config.get("General", 'mysqlUsername')
+    mysql_password = config.get("General", 'mysqlPassword')
+    mysql_port = config.get("General", 'mysqlPort')
+    token = config.get("General", 'token')
+
+    # 获取特有配置项
+    mysql_database = config.get("CPrecognizefish", 'mysqlDatabase')
+    camera_sql = MysqldbOperational(host=mysql_host,
+                                   username=mysql_username,
+                                   password=mysql_password,
+                                   port=int(mysql_port),
+                                   database=mysql_database,
+                                   logger=_logger)
+
+    fields = ["camera_name", "camera_ip", "camera_id", "identify_fish", "recognize_rate"]
+    camera_info = camera_sql.select("camera_configuration_table", fields=fields)
+    for each in camera_info:
+        # 只识别 水下视频
+        if each[3] == 0:
+            t = MyThread(each, token)
+            t.start()
+    time.sleep(5)

+ 233 - 0
001_h511/imageCapture/iotServerMQTT.py

@@ -0,0 +1,233 @@
+#!/usr/bin/env python
+import time
+import configparser
+from mysqlDataBase import MysqldbOperational
+import json
+from Crypto.Cipher import AES
+import hashlib
+import paho.mqtt.client as mqtt
+import ssl
+import LogOut
+
+
+def getCodeAndPoint(addrData):
+    str = "."
+    code = addrData[:addrData.index(str)]
+    point = addrData[addrData.index(str) + 1:]
+    return code, point
+
+
+def getDeviceConnectionStatus(data_time_stamp):
+    now_time_stamp = time.time()
+    if data_time_stamp < now_time_stamp - 300:
+        return 1
+    else:
+        return 0
+
+
+def dateAndTimeToTimestamp(date_time):
+    time_array = time.strptime(date_time, "%Y-%m-%d %H:%M:%S")
+    time_stamp = int(time.mktime(time_array))
+    return time_stamp
+
+
+def setSendStatusIsSucceed(dataInfo):
+    if dataInfo != None:
+        for i in range(len(dataInfo)):
+            id = dataInfo[i]['id']
+            table_name = "table_" + str(dataInfo[i]['tableName'])
+            my.set_send_status(table_name, id, 1)
+
+
+def getMqttDataFromMysql(list_devices, appId, token):
+    dataList = []
+    data = {}
+    data_from_mysql_info_list = []
+    for index in range(len(list_devices)):
+        list_points = my.get_mqtt_point(list_devices[index])
+        data_from_mysql = my.get_newest_data('table_' + str(list_points[0]['deviceName']))
+        if len(data_from_mysql) > 0:
+            date_time = str(data_from_mysql['times'])
+            date_time = dateAndTimeToTimestamp(date_time)
+            STS_DI = getDeviceConnectionStatus(date_time)
+            # print("STS_DI = ", STS_DI)
+        else:
+            STS_DI = 1
+        dataDist = {}
+        data_from_mysql_info_dict = {}
+        code = ''
+        if STS_DI == 0:
+            dataDist['DQ_DI'] = '0'
+            dataDist['STS_DI'] = '0'
+            data_from_mysql_info_dict['id'] = data_from_mysql['id']
+            data_from_mysql_info_dict['tableName'] = list_points[0]['deviceName']
+            data_from_mysql_info_list.append(data_from_mysql_info_dict)
+            for i in range(len(list_points)):
+                code, point = getCodeAndPoint(list_points[i]['mqttCode'])
+                columnName = "c" + str(list_points[i]['serialNumber'])
+                dataDist[point] = str(data_from_mysql[columnName])
+                if list_points[i]['lowLimit'] != None and list_points[i]['upLimit'] != None:
+                    if dataDist[point] is None or float(dataDist[point]) < list_points[i]['lowLimit'] or float(dataDist[point]) > list_points[i]['upLimit']:
+                        # dataDist['DQ_DI'] = '1'     # 功能优化
+                        dataDist.pop(point)     # 功能优化,过滤坏数据
+                if list_points[i]['storageType'] == "datetime":
+                    try:
+                        timeArray = time.strptime(dataDist[point], "%Y-%m-%d %H:%M:%S")
+                        timeStamp = int(time.mktime(timeArray) * 1000)
+                        dataDist[point] = timeStamp
+                    except Exception as e:
+                        dataDist['DQ_DI'] = '1'
+                        dataDist[point] = '0'
+                        print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), 'e1=', e)
+            dataDist['code'] = code
+            dataDist['ts'] = int(round(time.time() * 1000))
+            # print(dataDist['ts'])
+            dataList.append(dataDist)
+
+        elif STS_DI == 1:
+            code, point = getCodeAndPoint(list_points[0]['mqttCode'])
+            dataDist['DQ_DI'] = '1'
+            dataDist['STS_DI'] = '1'
+            dataDist['code'] = code
+            dataDist['ts'] = int(round(time.time() * 1000))
+            dataList.append(dataDist)
+
+    data['data'] = dataList
+    data['appId'] = appId
+    data['token'] = token
+    param = json.dumps(data)
+    return param, data_from_mysql_info_list
+
+
+def padding_pkcs5(value):
+    return str.encode(value + (BS - len(value) % BS) * chr(BS - len(value) % BS))
+
+
+def padding_zero(value):
+    while len(value) % 16 != 0:
+        value += '\0'
+    return str.encode(value)
+
+
+def aes_ecb_encrypt(key, value):
+    # AES/ECB/PKCS5padding
+    # key is sha1prng encrypted before
+    cryptor = AES.new(bytes.fromhex(key), AES.MODE_ECB)
+    padding_value = padding_pkcs5(value)  # padding content with pkcs5
+    ciphertext = cryptor.encrypt(padding_value)
+    return ''.join(['%02x' % i for i in ciphertext]).upper()
+
+
+# def get_sha1prng_key(key):
+#     '''[summary]
+#     encrypt key with SHA1PRNG
+#     same as java AES crypto key generator SHA1PRNG
+#     Arguments:
+#         key {[string]} -- [key]
+#
+#     Returns:
+#         [string] -- [hexstring]
+#     '''
+#     signature = hashlib.sha1(key.encode()).digest()
+#     signature = hashlib.sha1(signature).digest()
+#     return ''.join(['%02x' % i for i in signature]).upper()[:32]
+
+
+def get_sha1prng_key(key):
+    '''[summary]
+    encrypt key with SHA1PRNG
+    same as java AES crypto key generator SHA1PRNG
+    Arguments:
+        key {[string]} -- [key]
+    Returns:
+        [string] -- [hexstring]
+    '''
+    signature = hashlib.sha1(key.encode()).digest()
+    signature = hashlib.sha1(signature).digest()
+    return ''.join(['%02x' % i for i in signature]).upper()[:32]
+
+
+def on_connect(client, userdata, flags, rc):
+    print("Connected with result code " + str(rc))
+    # client.subscribe("hdbrecord1")         # 订阅消息
+
+
+def on_message(client, userdata, msg):
+    print("主题:" + msg.topic + " 消息:" + str(msg.payload.decode('utf-8')))
+
+
+def on_subscribe(client, userdata, mid, granted_qos):
+    print("On Subscribed: qos = %d" % granted_qos)
+
+
+def on_disconnect(client, userdata, rc):
+    if rc != 0:
+        print("Unexpected disconnection %s" % rc)
+
+
+if __name__ == "__main__":
+    _logger = LogOut.Log('iotServerMQTT')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的部section标签
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+    token = config.get(section, 'token')
+    appId = config.get(section, 'appId')
+
+    # 获取特有配置项
+    section = 'iotServerMQTT'  # 读取的部section标签
+    mysql_database = config.get(section, 'mysqlDatabase')
+    HOST = config.get(section, 'mqttHost')
+    PORT = config.getint(section, 'mqttPort')
+    client_id = config.get(section, 'mqttClientId')
+    key = config.get(section, 'mqttKey')  # keypassword
+    username = config.get(section, 'mqttUsername')
+    password = config.get(section, 'mqttPassword')
+    topic = config.get(section, 'mqttTopic')
+    frequency = config.getint(section, 'mqttFrequency')
+
+    # 连接数据库
+    my = MysqldbOperational(host=mysql_host,
+                            username=mysql_username,
+                            password=mysql_password,
+                            port=mysql_port,
+                            database=mysql_database,
+                            logger=_logger)
+    # r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0, decode_responses=True)
+
+    BS = AES.block_size
+    post_time = 0
+    list_devices = my.get_mqtt_devices()
+    client = mqtt.Client(client_id)
+    client.tls_set(ca_certs='ca.crt', certfile=None, keyfile=None, cert_reqs=ssl.CERT_NONE,
+                   tls_version=ssl.PROTOCOL_TLSv1, ciphers=None)
+    # client.tls_set_context(context=None)
+    client.username_pw_set(username, password)
+    client.on_connect = on_connect
+    client.on_message = on_message
+    client.on_subscribe = on_subscribe
+    client.on_disconnect = on_disconnect
+    client.connect(HOST, PORT, 10)
+    client.loop_start()
+    while True:
+        time.sleep(0.1)
+        if post_time < time.time() - frequency:
+            try:
+                post_time = time.time()
+                param, dataInfo = getMqttDataFromMysql(list_devices, appId, token)
+                # print(param)
+                aes128string = aes_ecb_encrypt(get_sha1prng_key(key), param)
+                is_send, mid = client.publish(topic, payload=aes128string, qos=1)
+                if is_send == 0:
+                    setSendStatusIsSucceed(dataInfo)
+                print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), 'is_send=', is_send)
+            except Exception as e:
+                print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()), 'e2=',e)
+    client.loop_stop()

+ 237 - 0
001_h511/imageCapture/iotServerMQTT_001.py

@@ -0,0 +1,237 @@
+#!/usr/bin/env python
+import time
+import configparser
+from mysqlDataBase import MysqldbOperational
+import json
+from Crypto.Cipher import AES
+import hashlib
+import paho.mqtt.client as mqtt
+import ssl
+import LogOut
+
+
+def getCodeAndPoint(addrData):
+    str = "."
+    code = addrData[:addrData.index(str)]
+    point = addrData[addrData.index(str) + 1:]
+    return code, point
+
+
+def getDeviceConnectionStatus(data_time_stamp):
+    now_time_stamp = time.time()
+    if data_time_stamp < now_time_stamp - 300:
+        return 1
+    else:
+        return 0
+
+
+def dateAndTimeToTimestamp(date_time):
+    time_array = time.strptime(date_time, "%Y-%m-%d %H:%M:%S")
+    time_stamp = int(time.mktime(time_array))
+    return time_stamp
+
+
+def setSendStatusIsSucceed(dataInfo):
+    if dataInfo != None:
+        for i in range(len(dataInfo)):
+            id = dataInfo[i]['id']
+            table_name = "table_" + str(dataInfo[i]['tableName'])
+            my.set_send_status(table_name, id, 1)
+
+
+def getMqttDataFromMysql(list_devices, appId, token):
+    dataList = []
+    data = {}
+    data_from_mysql_info_list = []
+    for index in range(len(list_devices)):
+        list_points = my.get_mqtt_point(list_devices[index])
+        data_from_mysql = my.get_newest_data('table_' + str(list_points[0]['deviceName']))
+        if len(data_from_mysql) > 0:
+            date_time = str(data_from_mysql['times'])
+            date_time = dateAndTimeToTimestamp(date_time)
+            STS_DI = getDeviceConnectionStatus(date_time)
+            # print("STS_DI = ", STS_DI)
+        else:
+            STS_DI = 1
+        dataDist = {}
+        data_from_mysql_info_dict = {}
+        code = ''
+        if STS_DI == 0:
+            dataDist['DQ_DI'] = '0'
+            dataDist['STS_DI'] = '0'
+            data_from_mysql_info_dict['id'] = data_from_mysql['id']
+            data_from_mysql_info_dict['tableName'] = list_points[0]['deviceName']
+            data_from_mysql_info_list.append(data_from_mysql_info_dict)
+            for i in range(len(list_points)):
+                code, point = getCodeAndPoint(list_points[i]['mqttCode'])
+                columnName = "c" + str(list_points[i]['serialNumber'])
+                dataDist[point] = str(data_from_mysql[columnName])
+                if list_points[i]['lowLimit'] != None and list_points[i]['upLimit'] != None:
+                    if float(dataDist[point]) <= list_points[i]['lowLimit'] or float(dataDist[point]) > list_points[i]['upLimit']:
+                        print(point, dataDist[point], list_points[i]['lowLimit'], list_points[i]['upLimit'])
+                        # dataDist.pop(point)
+                        dataDist['DQ_DI'] = '1'
+                if list_points[i]['storageType'] == "datetime":
+                    try:
+                        timeArray = time.strptime(dataDist[point], "%Y-%m-%d %H:%M:%S")
+                        timeStamp = int(time.mktime(timeArray) * 1000)
+                        dataDist[point] = timeStamp
+                    except Exception as e:
+                        dataDist['DQ_DI'] = '1'
+                        dataDist[point] = '0'
+                        print(e)
+            dataDist['code'] = code
+            dataDist['ts'] = int(round(time.time() * 1000))
+            # print(dataDist['ts'])
+            dataList.append(dataDist)
+        elif STS_DI == 1:
+            code, point = getCodeAndPoint(list_points[0]['mqttCode'])
+            dataDist['DQ_DI'] = '1'
+            dataDist['STS_DI'] = '1'
+            dataDist['code'] = code
+            dataDist['ts'] = int(round(time.time() * 1000))
+            dataList.append(dataDist)
+        print("dataDist = ", dataDist)
+
+    data['data'] = dataList
+    data['appId'] = appId
+    data['token'] = token
+    param = json.dumps(data)
+    return param, data_from_mysql_info_list
+
+
+def padding_pkcs5(value):
+    return str.encode(value + (BS - len(value) % BS) * chr(BS - len(value) % BS))
+
+
+def padding_zero(value):
+    while len(value) % 16 != 0:
+        value += '\0'
+    return str.encode(value)
+
+
+def aes_ecb_encrypt(key, value):
+    # AES/ECB/PKCS5padding
+    # key is sha1prng encrypted before
+    cryptor = AES.new(bytes.fromhex(key), AES.MODE_ECB)
+    padding_value = padding_pkcs5(value)  # padding content with pkcs5
+    ciphertext = cryptor.encrypt(padding_value)
+    return ''.join(['%02x' % i for i in ciphertext]).upper()
+
+
+# def get_sha1prng_key(key):
+#     '''[summary]
+#     encrypt key with SHA1PRNG
+#     same as java AES crypto key generator SHA1PRNG
+#     Arguments:
+#         key {[string]} -- [key]
+#
+#     Returns:
+#         [string] -- [hexstring]
+#     '''
+#     signature = hashlib.sha1(key.encode()).digest()
+#     signature = hashlib.sha1(signature).digest()
+#     return ''.join(['%02x' % i for i in signature]).upper()[:32]
+
+
+def get_sha1prng_key(key):
+    '''[summary]
+    encrypt key with SHA1PRNG
+    same as java AES crypto key generator SHA1PRNG
+    Arguments:
+        key {[string]} -- [key]
+    Returns:
+        [string] -- [hexstring]
+    '''
+    signature = hashlib.sha1(key.encode()).digest()
+    signature = hashlib.sha1(signature).digest()
+    return ''.join(['%02x' % i for i in signature]).upper()[:32]
+
+
+def on_connect(client, userdata, flags, rc):
+    print("Connected with result code " + str(rc))
+    # client.subscribe("hdbrecord1")         # 订阅消息
+
+
+def on_message(client, userdata, msg):
+    print("主题:" + msg.topic + " 消息:" + str(msg.payload.decode('utf-8')))
+
+
+def on_subscribe(client, userdata, mid, granted_qos):
+    print("On Subscribed: qos = %d" % granted_qos)
+
+
+def on_disconnect(client, userdata, rc):
+    if rc != 0:
+        print("Unexpected disconnection %s" % rc)
+
+
+if __name__ == "__main__":
+    _logger = LogOut.Log('iotServerMQTT')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    section = "General"  # 读取的部section标签
+    mysql_host = config.get(section, 'mysqlHost')
+    mysql_username = config.get(section, 'mysqlUsername')
+    mysql_password = config.get(section, 'mysqlPassword')
+    mysql_port = config.getint(section, 'mysqlPort')
+    token = config.get(section, 'token')
+    appId = config.get(section, 'appId')
+
+    # 获取特有配置项
+    section = 'iotServerMQTT'  # 读取的部section标签
+    mysql_database = config.get(section, 'mysqlDatabase')
+    HOST = config.get(section, 'mqttHost')
+    PORT = config.getint(section, 'mqttPort')
+    client_id = config.get(section, 'mqttClientId')
+    key = config.get(section, 'mqttKey')  # keypassword
+    username = config.get(section, 'mqttUsername')
+    password = config.get(section, 'mqttPassword')
+    topic = config.get(section, 'mqttTopic')
+    frequency = config.getint(section, 'mqttFrequency')
+
+    # 连接数据库
+    my = MysqldbOperational(host=mysql_host,
+                            username=mysql_username,
+                            password=mysql_password,
+                            port=mysql_port,
+                            database=mysql_database,
+                            logger=_logger)
+    # r = redis.StrictRedis(host='127.0.0.1', port=6379, db=0, decode_responses=True)
+
+    BS = AES.block_size
+    post_time = 0
+    list_devices = my.get_mqtt_devices()
+    # client = mqtt.Client(client_id)
+    # client.tls_set(ca_certs='ca.crt', certfile=None, keyfile=None, cert_reqs=ssl.CERT_NONE,
+    #                tls_version=ssl.PROTOCOL_TLSv1, ciphers=None)
+    # # client.tls_set_context(context=None)
+    # client.username_pw_set(username, password)
+    # client.on_connect = on_connect
+    # client.on_message = on_message
+    # client.on_subscribe = on_subscribe
+    # client.on_disconnect = on_disconnect
+    # client.connect(HOST, PORT, 10)
+    # client.loop_start()
+    # while True:
+    #     time.sleep(0.1)
+    #     if post_time < time.time() - frequency:
+    #         try:
+    #             post_time = time.time()
+    #             param, dataInfo = getMqttDataFromMysql(list_devices, appId, token)
+    #             #print(param)
+    #             aes128string = aes_ecb_encrypt(get_sha1prng_key(key), param)
+    #             is_send, mid = client.publish(topic, payload=aes128string, qos=1)
+    #             if is_send == 0:
+    #                 setSendStatusIsSucceed(dataInfo)
+    #             print(is_send)
+    #         except Exception as e:
+    #             print(e)
+    # client.loop_stop()
+
+
+    param, dataInfo = getMqttDataFromMysql(list_devices, appId, token)

+ 746 - 0
001_h511/imageCapture/mysqlDataBase.py

@@ -0,0 +1,746 @@
+import re
+import pymysql
+import time
+import LogOut
+import traceback
+from datetime import datetime, timedelta
+
+"""
+connect连接对象的方法:
+
+close()  --关闭的方法
+
+commit()   --如果支持事务则提交挂起的事务
+
+rollback()  --回滚挂起的事务
+
+cursor()  --返回连接的游标对象
+游标对象的方法:
+
+callproc(name,[params]) --用来执行存储过程,接收的参数为存储过程的名字和参数列表,返回受影响的行数
+
+close()  --关闭游标
+
+execute(sql,[params])--执行sql语句,可以使用参数,(使用参数时,sql语句中用%s进行站位注值),返回受影响的行数
+
+executemany(sql,params)--执行单挑sql语句,但是重复执行参数列表里的参数,返回受影响的行数
+
+fetchone()  --返回结果的下一行
+
+fetchall()  --返回结果的 所有行
+
+fetchmany(size)--返回size条记录,如果size大于返回结果行的数量,则会返回cursor.arraysize条记录
+
+nextset()  --条至下一行
+
+setinputsizes(size)--定义cursor
+
+游标对象的属性:
+
+description--结果列的描述,只读
+
+rowcount  --结果中的行数,只读
+
+arraysize  --fetchmany返回的行数,默认为1
+
+"""
+
+
+class MysqldbOperational(object):
+    """
+    操作mysql数据库,基本方法
+    """
+
+    # logger = LogOut.Log("mysql")
+
+    def __init__(self, host="localhost", username="root", password="", port=3306, database="", logger=None,
+                 charset='utf-8'):
+        self.host = host
+        self.username = username
+        self.password = password
+        self.database = database
+        self.port = port
+        self.charset = charset
+        self.logger = logger
+        self.con = None
+        self.cur = None
+        self._conn()
+
+    def _conn(self):
+        try:
+            self.con = pymysql.connect(host=self.host, user=self.username, passwd=self.password, port=self.port,
+                                       db=self.database, autocommit=True)
+            # 所有的查询,都在连接 con 的一个模块 cursor 上面运行的
+            self.cur = self.con.cursor()
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function _conn.' + repr(e))
+
+    def close(self):
+        """
+        关闭数据库连接
+        """
+        try:
+            self.con.close()
+            self.logger.info("Database connection close.")
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function close.' + repr(e))
+
+    def _reConn(self, num=28800, stime=3):  # 重试连接总次数为1天,这里根据实际情况自己设置,如果服务器宕机1天都没发现就......
+        _number = 0
+        _status = True
+        while _status and _number <= num:
+            try:
+                self.con.ping()  # cping 校验连接是否异常
+                _status = False
+            except Exception as e:
+                # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+                #     traceback.format_exc(limit=1)))
+                self.logger.error('in function _reConn.' + repr(e))
+                if self._conn():  # 重新连接,成功退出
+                    _status = False
+                    break
+                _number += 1
+                time.sleep(stime)  # 连接不成功,休眠3秒钟,继续循环,知道成功或重试次数结束
+
+    # 抽帧相关函数
+    def getOneData(self):
+        # 取得上个查询的结果,是单个结果
+        data = self.cur.fetchone()
+        return data
+
+    def creatTable(self, tablename, attrdict, constraint):
+        """创建数据库表
+            args:
+                tablename  :表名字
+                attrdict   :属性键值对,{'book_name':'varchar(200) NOT NULL'...}DEFAULT NULL NOT NULL
+                constraint :主外键约束,PRIMARY KEY(`id`)  自动增量
+        """
+        self._reConn()
+        if self.isExistTable(tablename):
+            return
+        sql = ''
+        sql_mid = '`id` bigint(11) NOT NULL AUTO_INCREMENT,'
+        for attr, value in attrdict.items():
+            sql_mid = sql_mid + '`' + attr + '`' + ' ' + value + ','
+        sql = sql + 'CREATE TABLE IF NOT EXISTS %s (' % tablename
+        sql = sql + sql_mid
+        sql = sql + constraint
+        sql = sql + ') ENGINE=InnoDB DEFAULT CHARSET=utf8'
+        print('creatTable:' + sql)
+        self.executeCommit(sql)
+
+    def executeSql(self, sql=''):
+        """执行sql语句,针对读操作返回结果集
+
+            args:
+                sql  :sql语句
+        """
+        try:
+            self.cur.execute(sql)
+            records = self.cur.fetchall()
+            return records
+        except pymysql.Error as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function executeSql.' + repr(e))
+
+
+    def executeCommit(self, sql=''):
+        """执行数据库sql语句,针对更新,删除,事务等操作失败时回滚
+
+        """
+        try:
+            self.cur.execute(sql)
+            self.con.commit()
+            return True
+        except pymysql.Error as e:
+            self.con.rollback()
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function executeCommit.' + repr(e))
+
+            return False
+
+    def insert(self, tablename, params):
+        """插入数据库
+            args:
+                tablename  :表名字
+                key        :属性键
+                value      :属性值
+        """
+        self._reConn()
+        key = []
+        value = []
+        for tmpkey, tmpvalue in params.items():
+            key.append(tmpkey)
+            if isinstance(tmpvalue, str):
+                value.append("\'" + tmpvalue + "\'")
+            else:
+                value.append(tmpvalue)
+        attrs_sql = '(' + ','.join(key) + ')'
+        values_sql = ' values(' + ','.join(value) + ')'
+        sql = 'insert into %s' % tablename
+        sql = sql + attrs_sql + values_sql
+        print('_insert:' + sql)
+        self.executeCommit(sql)
+
+    def select(self, tablename, cond_dict='', order='', fields='*'):
+        """查询数据
+            args:
+                tablename  :表名字
+                cond_dict  :查询条件
+                order      :排序条件
+
+            example:
+                print mydb.select(table)
+                print mydb.select(table, fields=["name"])
+                print mydb.select(table, fields=["name", "age"])
+                print mydb.select(table, fields=["age", "name"])
+        """
+        self._reConn()
+        consql = ' '
+        if cond_dict != '':
+            for k, v in cond_dict.items():
+                consql = consql + "`" + tablename + "`" + '.' + "`" + k + "`" + '=' + "'" + v + "'" + ' and'
+        consql = consql + ' 1=1 '
+        if fields == "*":
+            sql = 'select * from %s where' % tablename
+        else:
+            if isinstance(fields, list):
+                fields = ",".join(fields)
+                sql = 'select %s from %s where' % (fields, tablename)
+            else:
+                self.logger.error("fields input error, please input list fields.")
+                raise Exception("fields input error, please input list fields.")
+        sql = sql + consql + order
+        #print('select:' + sql)
+        return self.executeSql(sql)
+
+    def select_last_one(self, tablename, fields='*'):
+        """倒叙查询
+            args:
+                tablename  :表名字
+                fields     :检索的名称
+        """
+
+        sql = 'select %s from %s order by time desc limit 1 ' % (fields, tablename)
+        #print('select:' + sql)
+        if fields == "*":
+            return self.executeSql(sql)
+        else:
+            return self.executeSql(sql)[0][0]
+
+    def insertMany(self, table, attrs, values):
+        """插入多条数据
+
+            args:
+                tablename  :表名字
+                attrs        :属性键
+                values      :属性值
+
+            example:
+                table='test_mysqldb'
+                key = ["id" ,"name", "age"]
+                value = [[101, "liuqiao", "25"], [102,"liuqiao1", "26"], [103 ,"liuqiao2", "27"], [104 ,"liuqiao3", "28"]]
+                mydb.insertMany(table, key, value)
+        """
+        self._reConn()
+        values_sql = ['%s' for v in attrs]
+        attrs_sql = '(' + ','.join(attrs) + ')'
+        values_sql = ' values(' + ','.join(values_sql) + ')'
+        sql = 'insert into %s' % table
+        sql = sql + attrs_sql + values_sql
+        print('insertMany:' + sql)
+        try:
+            # print(sql)
+            for i in range(0, len(values), 20000):
+                self.cur.executemany(sql, values[i:i + 20000])
+                self.con.commit()
+        except pymysql.Error as e:
+            self.con.rollback()
+            self.logger.error('in function insertMany.' + repr(e))
+
+
+
+    def insert_sql(self, table_name, keys, values):
+        """
+        增加数据
+        :param table_name: (字符串)表名
+        :param keys: (字符串) 字段名, 如 “(device_name, code)”
+        :param values: (元组)每个字段的值, 如 ('sm140', '006001001WAVE')
+        :return: True / False
+        """
+        for each in values:
+            in_sql = "INSERT INTO %s %s VALUES %s;" % (table_name, keys, each)
+            try:
+                self._reConn()
+                self.cur.execute(in_sql)
+                self.con.commit()
+            except pymysql.Error as e:
+                self.con.rollback()
+                self.logger.error('in function insert_sql.' + repr(e))
+
+
+
+    def delete(self, tablename, cond_dict):
+        """删除数据
+            args:
+                tablename  :表名字
+                cond_dict  :删除条件字典
+
+            example:
+                params = {"name" : "caixinglong", "age" : "38"}
+                mydb.delete(table, params)
+
+        """
+        self._reConn()
+        consql = ' '
+        if cond_dict != '':
+            for k, v in cond_dict.items():
+                if isinstance(v, str):
+                    v = "\'" + v + "\'"
+                consql = consql + tablename + "." + k + '=' + v + ' and '
+        consql = consql + ' 1=1 '
+        sql = "DELETE FROM %s where%s" % (tablename, consql)
+        print(sql)
+        return self.executeCommit(sql)
+
+    def update(self, tablename, attrs_dict, cond_dict):
+        """更新数据
+            args:
+                tablename  :表名字
+                attrs_dict  :更改属性键值对字典
+                cond_dict  :更新条件字典
+
+            example:
+                params = {"name" : "caixinglong", "age" : "38"}
+                cond_dict = {"name" : "liuqiao", "age" : "18"}
+                mydb.update(table, params, cond_dict)
+        """
+        self._reConn()
+        attrs_list = []
+        consql = ' '
+        for y in attrs_dict:
+            if not isinstance(attrs_dict[y], str):
+                attrs_dict[y] = str(attrs_dict[y])
+        for x in cond_dict:
+            if not isinstance(cond_dict[x], str):
+                cond_dict[x] = str(cond_dict[x])
+
+        for tmpkey, tmpvalue in attrs_dict.items():
+            attrs_list.append("`" + tmpkey + "`" + "=" + "\'" + tmpvalue + "\'")
+        attrs_sql = ",".join(attrs_list)
+        #print("attrs_sql:", attrs_sql)
+        if cond_dict != '':
+            for k, v in cond_dict.items():
+                if isinstance(v, str):
+                    v = "\'" + v + "\'"
+                consql = consql + "`" + tablename + "`." + "`" + k + "`" + '=' + v + ' and '
+        consql = consql + ' 1=1 '
+        sql = "UPDATE %s SET %s where%s" % (tablename, attrs_sql, consql)
+        #print(sql)
+        return self.executeCommit(sql)
+
+    def dropTable(self, tablename):
+        """删除数据库表
+
+            args:
+                tablename  :表名字
+        """
+        sql = "DROP TABLE  %s" % tablename
+        self.executeCommit(sql)
+
+    def deleteTable(self, tablename):
+        """清空数据库表
+            args:
+                tablename  :表名字
+        """
+        sql = "DELETE FROM %s" % tablename
+        self.executeCommit(sql)
+
+    def isExistTable(self, tablename):
+        """判断数据表是否存在
+            args:
+                tablename  :表名字
+            Return:
+                存在返回True,不存在返回False
+        """
+        sql = "select * from %s" % tablename
+        result = self.executeCommit(sql)
+        if result is None:
+            return True
+        else:
+            if re.search("doesn't exist", result):
+                return False
+            else:
+                return True
+
+    # 数据上传相关函数
+    def get_devices_name(self):
+        list = []
+        sql = "SELECT DISTINCT device_name FROM data_point_tbl WHERE mqtt_code != 'NULL'"
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list.append(row[0])
+            self.cursor.close()
+            return list
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_devices_name.' + repr(e))
+            return False
+
+    def get_mqtt_devices_count(self):
+        list = 0
+        sql = "SELECT COUNT(DISTINCT device_code) FROM data_point_tbl"
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list = row[0]
+            self.cursor.close()
+            return list
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_mqtt_devices_count.' + repr(e))
+            return False
+
+    def get_mqtt_devices_from_name(self, device_name):
+        list = []
+        sql = "SELECT DISTINCT device_code FROM data_point_tbl WHERE device_name = '%s'" % (device_name)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list.append(row[0])
+            self.cursor.close()
+            return list
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_mqtt_devices_from_name.' + repr(e))
+            return False
+
+    def get_mqtt_point(self, deviceCode):
+        list = []
+        dict = {}
+        sql = "SELECT device_name,serial_number,storage_type,mqtt_code,low_limit,up_limit FROM data_point_tbl where device_code = '%s'" % (
+            deviceCode)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                dict = {}
+                dict['deviceName'] = row[0]
+                dict['serialNumber'] = row[1]
+                dict['storageType'] = row[2]
+                dict['mqttCode'] = row[3]
+                dict['lowLimit'] = row[4]
+                dict['upLimit'] = row[5]
+                list.append(dict)
+            self.cursor.close()
+            return list
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_mqtt_point.' + repr(e))
+            return False
+
+    def get_breakpoint_last_time_datetime(self, tableName):
+        sql = "SELECT times FROM %s WHERE is_send = 0 AND times < date_sub(now(), interval 1 hour) ORDER BY id DESC LIMIT 1;" % (
+            tableName)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            if len(results) > 0:
+                return results[0]
+            else:
+                #self.logger.debug(results)
+                return None
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_breakpoint_last_time_datetime.' + repr(e))
+            return None
+
+    def get_breakpoint_last_time_date_and_time(self, tableName):
+        sql = "SELECT Date,Time FROM %s WHERE is_send = 0 ORDER BY id LIMIT 1;" % (tableName)
+        dict = {}
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            if len(results) > 0:
+                dict['times'] = str(results[0][0]) + " " + str(results[0][1])
+                return dict
+            else:
+                return None
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_breakpoint_last_time_date_and_time.' + repr(e))
+            return None
+
+    def get_hour_data_datetime(self, tableName, begin, end):
+        sql = "SELECT * FROM %s WHERE times >= '%s' And times <= '%s' ORDER BY id ASC;" % (tableName, begin, end)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            if len(results) != 0:
+                return results
+            else:
+                return None
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_hour_data_datetime.' + repr(e))
+            return None
+
+    def get_hour_data_date_and_time(self, tableName, begin, end):
+        sql = "SELECT * FROM %s WHERE CONCAT(Date,' ', Time) >= '%s' And CONCAT(Date,' ', Time) <= '%s' ORDER BY id ASC;" % (
+            tableName, begin, end)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            if len(results) != 0:
+                return results
+            else:
+                return None
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_hour_data_date_and_time.' + repr(e))
+            return None
+
+    def set_many_send_status(self, tableName, id_list):
+        if len(id_list) >= 1:
+            id = id_list[0]['id']
+            value = 1
+            sql = "UPDATE %s SET is_send = %s WHERE id = %s" % (tableName, value, id)
+            for index in range(len(id_list)):
+                sql = sql + " OR id = %s" % (id_list[index]['id'])
+
+            try:
+                self._reConn()
+                self.cursor = self.con.cursor()
+                self.cursor.execute(sql)
+                # 提交到数据库执行
+                self.con.commit()
+                self.cursor.close()
+            except Exception as e:
+                # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+                #     traceback.format_exc(limit=1)))
+                self.logger.error('in function set_many_send_status.' + repr(e))
+
+    def get_mqtt_devices(self):
+        list = []
+        sql = "SELECT DISTINCT device_code FROM data_point_tbl"
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            for row in results:
+                if row[0] != None:
+                    list.append(row[0])
+            self.cursor.close()
+            return list
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_mqtt_devices.' + repr(e))
+            return False
+
+    def get_newest_data(self, tableName):
+        sql = "SELECT * FROM %s ORDER BY id DESC LIMIT 1;" % (tableName)
+        results = []
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+
+            if len(results) > 0:
+                #print(results[0])
+                return results[0]
+
+            else:
+                self.logger.debug(results)
+                return results
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function get_newest_data.' + repr(e))
+            return None
+
+    def set_send_status(self, tableName, id, value):
+        sql = "UPDATE %s SET is_send = %s WHERE id = %s;" % (tableName, value, id)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql)
+            # 提交到数据库执行
+            self.con.commit()
+            self.cursor.close()
+        except Exception as e:
+            # print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + "[ERROR] {0}\n".format(
+            #     traceback.format_exc(limit=1)))
+            self.logger.error('in function set_send_status.' + repr(e))
+
+
+
+    def binocular_data(self):
+        """
+        生物监控子系统:sql1:将值为null的数据状态置为1, sql2:查询双目未上传的数据
+        :return:[{'datetime': datetime.date(2021, 6, 10), 'fish_species': '许氏平鲉', 'size_average': 288.0, 'size_median': 286.6, 'weight_average': 458.3, 'weight_median': 432.6}]
+        """
+
+        yes_time = datetime.now().strftime("%Y-%m-%d")
+        sql1 = "UPDATE binocular_dailyreport SET is_send = 1 WHERE size_average IS NULL;"
+        sql2 = "SELECT datetime,fish_species,size_average,size_median,weight_average,weight_median FROM binocular_dailyreport WHERE datetime<\'%s\' AND is_send=0 AND size_average IS NOT NULL;" % (yes_time)
+
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql1)
+            self.con.commit()
+            self.cursor.execute(sql2)
+            results = self.cursor.fetchall()         
+            self.cursor.close()
+            return results
+
+        except Exception as e:
+            self.logger.error('in function get_newest_data.' + repr(e))
+            return None
+
+
+    def sonar_data_dailyReport(self):
+        """
+        生物监控子系统:查询声呐未上传的数据,每日的总数
+        :return: [{'date': '2021-07-06', 'assess_total_number': 699718}, {'date': '2021-07-07', 'assess_total_number': 579352}]
+        """
+        td_time = datetime.now().strftime("%Y-%m-%d")
+        sql = "SELECT date_format(datetime,'%%Y-%%m-%%d') AS date, assess_total_number FROM fish_distribution_dailyReport WHERE datetime<\'%s\' AND is_send=0 AND assess_total_number IS NOT NULL;" % (td_time)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            return results
+
+        except Exception as e:
+            self.logger.error('in function get_newest_data.' + repr(e))
+            return None
+
+    def sonar_data_avg(self):
+        """
+        生物监控子系统:查询声呐未上传的数据,上中下三层每日的平均值
+        :return: [{'date': '2022-08-02', 'assess_top_number': 6855, 'assess_middle_number': 91480, 'assess_bottom_number': 251176}]
+        """
+        td_time = datetime.now().strftime("%Y-%m-%d")
+        sql = "SELECT date_format(datetime,'%%Y-%%m-%%d') AS date, " \
+              "CAST(AVG(assess_top_number) AS signed) AS assess_top_number," \
+              "CAST(AVG(assess_middle_number) AS signed) AS assess_middle_number," \
+              "CAST(AVG(assess_bottom_number) AS signed) AS assess_bottom_number " \
+              "FROM fish_distribution_data WHERE datetime<\'%s\' AND is_send=0 GROUP BY date_format(datetime,'%%Y-%%m-%%d');" % (td_time)
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor(cursor=pymysql.cursors.DictCursor)
+            self.cursor.execute(sql)
+            results = self.cursor.fetchall()
+            self.cursor.close()
+            return results
+
+        except Exception as e:
+            self.logger.error('in function get_newest_data.' + repr(e))
+            return None
+
+
+    def binocular_send_status(self, dates):
+        """
+        生物监控子系统:将上传成功的双目数据状态置1
+        :param dates:
+        :return:
+        """
+        sql = "UPDATE binocular_dailyreport SET is_send = 1 WHERE datetime in %s;"
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql, (dates,))
+            self.con.commit()
+            self.cursor.close()
+        except Exception as e:
+            self.logger.error('in function set_send_status.' + repr(e))
+
+
+    def sonar_send_status(self, dates):
+        """
+        生物监控子系统:将上传成功的声呐数据状态置1
+        :param dates:
+        :return:
+        """
+        sql1 = "UPDATE fish_distribution_dailyReport SET is_send = 1 WHERE date_format(datetime,'%%Y-%%m-%%d') in %s;"
+        sql2 = "UPDATE fish_distribution_data SET is_send = 1 WHERE date_format(datetime,'%%Y-%%m-%%d') in %s;"
+
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql1, (dates,))
+            self.cursor.execute(sql2, (dates,))
+            self.con.commit()
+            self.cursor.close()
+        except Exception as e:
+            self.logger.error('in function set_send_status.' + repr(e))
+
+
+
+    def commit_sql(self, sql, params):
+        """
+        执行 MySQL 的删除、插入、更新语句,如
+        :param table_name: (字符串)表名
+        :param cond_dict: (字典)条件
+        :return:
+        """
+
+        try:
+            self._reConn()
+            self.cursor = self.con.cursor()
+            self.cursor.execute(sql, (params,))
+            self.con.commit()
+            self.cursor.close()
+            result = True
+        except pymysql.Error as err:
+            self.logger.error("in function delete_sql. " + repr(err))
+            result = False
+        return result

+ 8 - 0
001_h511/imageCapture/requirements.txt

@@ -0,0 +1,8 @@
+requests==2.25.1
+redis==3.5.3
+sanic==21.3.4
+Sanic_Cors==1.0.0
+PyMySQL==1.0.2
+paho_mqtt==1.5.1
+pycryptodome==3.10.1
+requests_toolbelt==0.9.1

+ 50 - 0
001_h511/imageCapture/reset_issend_to_zero.py

@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+"""
+@File  : reset_issend_to_zero.py
+@Author: DJW
+@Date  : 2023-06-13 14:35:14
+@Desc  : 重新设置某个时间段is_send为0,为了重新打包上传历史数据
+"""
+import time
+import configparser
+import LogOut
+
+from mysqlDataBase import MysqldbOperational
+
+if __name__ == "__main__":
+    _logger = LogOut.Log('reset_issend_to_zero')
+    # 获取通用配置项
+    # section = "General"  # 读取的部section标签
+    mysql_host = "localhost"
+    mysql_username = "root"
+    mysql_password = "R.!a@O&t9CjweWLSTr"
+    mysql_port = 3306
+    mysql_database = "centralized_control_db"
+    # 连接数据库
+    my = MysqldbOperational(
+        host=mysql_host,
+        username=mysql_username,
+        password=mysql_password,
+        port=mysql_port,
+        database=mysql_database,
+        logger=_logger)
+
+    dates = ["2023-01-06", "2023-01-07", "2023-01-25", "2023-02-14", "2023-02-15", "2023-03-02", "2023-03-03",
+         "2023-03-04", "2023-03-05", "2023-03-06", "2023-03-30", "2023-03-31", "2023-05-16", "2023-05-17",
+         "2023-05-18", "2023-05-19"]
+
+    # 查询含有is_send字段的数据表
+    sql = f"SELECT TABLE_NAME from INFORMATION_SCHEMA.columns " \
+          f"WHERE TABLE_NAME LIKE 'table_%' AND COLUMN_NAME = 'is_send' AND table_schema = '{mysql_database}';"
+    result = my.executeSql(sql)
+    if result:
+        table_names = [i[0] for i in result]
+        # 遍历表名和需要is_send置0的日期,更新置0
+        for table_name in table_names:
+            for date in dates:
+                try:
+                    sql = f"UPDATE `{table_name}` SET is_send=0 WHERE times BETWEEN '{date} 00:00:00' AND '{date} 23:59:59';"
+                    my.executeCommit(sql)
+                except Exception as e:
+                    _logger.error(e)
+                print(f"【{table_name}】已经完成置0 sql:{sql}")

+ 82 - 0
001_h511/imageCapture/update_code.py

@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+@CreateTime: 2021/8/10 14:48
+@Author: lxc
+@LastEditTime:
+@Desctiption: 更新 update_code_period(设备传输周期表) 中的 设备码
+"""
+
+import configparser
+
+import pymysql
+
+import LogOut
+from mysqlDataBase import MysqldbOperational
+
+
+def main():
+    """
+    更新设备名和设备码
+    :return: SUCCESS 或 ERROR
+    """
+    try:
+        # 点表中的设备名和设备码
+        point_sql = "SELECT DISTINCT SUBSTRING_INDEX(mqtt_code, '.',1) FROM data_point_tbl WHERE mqtt_code IS NOT NULL;"
+        point_code = cameraSql.executeSql(point_sql)
+        # 设备传输周期表中的设备名和设备码
+        period_code = cameraSql.executeSql("SELECT code FROM update_code_period;")
+    except pymysql.Error as err:
+        _logger.error(repr(err))
+
+    point_diff = set(point_code).difference(set(period_code))     # 点表中的不同部分
+    period_diff = set(period_code).difference(set(point_code))    # 设备传输周期表中的不同部分
+    # noinspection PyBroadException
+    try:
+        # 删除 设备传输周期表中 不同的部分
+        if len(period_diff) > 0:
+            for each in period_diff:
+                cond_dict = {"code": each[0]}
+                cameraSql.delete(tablename="update_code_period", cond_dict=cond_dict)
+        # 向 设备传输周期表 中添加 点表 中的不同部分
+        if len(point_diff) > 0:
+            code = []
+            for each in point_diff:
+                code.append("(\'"+each[0]+"\')")
+            cameraSql.insert_sql(table_name="update_code_period",
+                                 keys="(code)",
+                                 values=code)
+        # 修改新加设备码的上传周期
+        cameraSql.executeCommit("UPDATE update_code_period SET period=2 WHERE period is NULL;")
+        _logger.info("SUCCESS")
+    except Exception as e:
+        _logger.error("ERROR %s" % (e))
+
+
+
+
+if __name__ == '__main__':
+    _logger = LogOut.Log('update_code')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    GENERAL = "General"   # 读取标签
+    mysql_host = config.get(GENERAL, 'mysqlHost')
+    mysql_username = config.get(GENERAL, 'mysqlUsername')
+    mysql_password = config.get(GENERAL, 'mysqlPassword')
+    mysql_port = config.get(GENERAL, 'mysqlPort')
+
+    # 获取特有配置项
+    SECTION = 'updateDeviceUploadPeriod'
+    mysql_database = config.get(SECTION, 'mysqlDatabase')
+    cameraSql = MysqldbOperational(host=mysql_host,
+                                   username=mysql_username,
+                                   password=mysql_password,
+                                   port=int(mysql_port),
+                                   database=mysql_database,
+                                   logger=_logger)
+
+    main()

+ 166 - 0
001_h511/imageCapture/upload_biology_monitor_data.py

@@ -0,0 +1,166 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+@CreateTime: 2021/9/26 16:25
+@Author: lxc
+@LastEditTime: 
+@Desctiption: 上传生物监控系统数据到云平台
+"""
+
+import time
+import LogOut
+import configparser
+from mysqlDataBase import MysqldbOperational
+import requests
+import json
+
+
+def post_data(all_data):
+    """
+    上传生物监控子系统的数据到云平台
+    :param datas:
+    :return:
+    """
+    now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
+    success_date = []
+    headers = {
+        "Authorization": token,
+        "Content-Type": "application/json"
+    }
+    for each in all_data:
+        data = all_data[each]
+        data["platformId"] = platform_id
+        data["cageId"] = cage_id
+        data["date"] = each
+        data["upperRange"] = upper_range
+        data["middleRange"] = middle_range
+        data["lowerRange"] = lower_range
+        if 'cageBiomass' in data.keys():
+            data["breedBiomass"] = int(coefficient) * data['cageBiomass']
+
+        if 'breedInfo' not in data.keys():
+            data['breedInfo'] = []
+        print("data = ", data)
+
+        url = "https://management.super-sight.com.cn/system/api/v1/farmingOperationLog/log/monitor"
+        ret = requests.post(url=url, headers=headers, json=data, verify=False)
+        if ret.status_code == 200:
+            print(now, ret.text, ret.status_code)
+            success_date.append(each)
+        else:
+            print(now, ret.text, ret.status_code)
+    if len(success_date) > 0:
+        change_upload_status(success_date)
+
+
+def deal_data():
+    data_all = {}
+
+    # 声呐的数据;每天的总数
+    sonar_data_dailyReport = sonarSql.sonar_data_dailyReport()
+    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), 'sonar_data_dailyReport = ',
+          sonar_data_dailyReport)
+    if len(sonar_data_dailyReport) > 0:
+        for each in sonar_data_dailyReport:
+            date = each["date"]
+            each_data = {"cageBiomass": each["assess_total_number"]}
+            data_all[date] = each_data
+
+    # 声呐的数据;每天的上中下三层的均值
+    sonar_data_avg = sonarSql.sonar_data_avg()
+    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), 'sonar_data_avg = ', sonar_data_avg)
+    if len(sonar_data_avg) > 0:
+        for each in sonar_data_avg:
+            date = each["date"]
+            each_data = {"upperBiomass": each["assess_top_number"], "middleBiomass": each["assess_middle_number"],
+                         "lowerBiomass": each["assess_bottom_number"]}
+            if date in data_all.keys():
+                tmp = data_all[date]
+                each_data = {**tmp, **each_data}
+            data_all[date] = each_data
+
+    # 双目的数据
+    binocular_datas = binocularSql.binocular_data()
+    print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())), 'binocular_datas = ', binocular_datas)
+    if len(binocular_datas) > 0:
+        for each in binocular_datas:
+            breed_info = {"breedName": each["fish_species"], "lengthAverage": each["size_average"],
+                          "lengthMedian": each["size_median"], "weightAverage": each["weight_average"],
+                          "weightMedian": each["weight_median"]}
+            # breed_info["breedBiomass"] =
+
+            date = str(each["datetime"])
+            if date in data_all.keys():
+                tmp = data_all[date]
+                if "breedInfo" not in tmp.keys():
+                    tmp["breedInfo"] = [breed_info]
+                else:
+                    tmp["breedInfo"].append(breed_info)
+                data_all[date] = tmp
+            else:
+                data_all[date] = {"breedInfo": [breed_info]}
+
+    # 将数据上传至云平台
+    if len(data_all) > 0:
+        post_data(data_all)
+
+
+def change_upload_status(date):
+    """
+    修改数据的上传状态
+    :param date: 上传成功的数据的时间列表:['2021-07-06', '2021-07-07', '2021-07-08', ...]
+    :return:
+    """
+    try:
+        upload_binocular = binocularSql.binocular_send_status(date)
+        upload_sonar = sonarSql.sonar_send_status(date)
+    except Exception as e:
+        print(e)
+
+
+if __name__ == '__main__':
+    time.sleep(2)
+    _logger = LogOut.Log('upload_biology_monitor_data')
+
+    run_time = 0
+    file_time = 0
+    while True:
+        now_time = time.time()
+        if now_time - run_time > 24 * 60 * 60:
+            run_time = now_time
+
+            # 创建读取配置文件对象
+            config = configparser.ConfigParser()
+            config.read("config.ini", encoding="utf-8")
+
+            token = config.get("General", "token")
+            platform_id = config.get("General", "appid")  # 平台ID
+
+            # 双目和声呐数据库:获取通用配置项
+            SECTION = "biologyMonitor"  # 读取的SECTION标签
+            mysql_host = config.get(SECTION, 'mysqlHost')
+            mysql_username = config.get(SECTION, 'mysqlUsername')
+            mysql_password = config.get(SECTION, 'mysqlPassword')
+            mysql_port = config.getint(SECTION, 'mysqlPort')
+            binocular_database = config.get(SECTION, 'binocular_database')  # 双目数据库
+            sonar_database = config.get(SECTION, 'sonar_database')  # 声呐数据库
+            cage_id = config.get(SECTION, "cageId")  # 网箱ID
+            upper_range = config.get(SECTION, "upperRange")  # 上层范围
+            middle_range = config.get(SECTION, "middleRange")  # 中层范围
+            lower_range = config.get(SECTION, "lowerRange")  # 下层范围
+            coefficient = config.get(SECTION, "coefficient")  # 系数:来计算各种鱼的数量
+
+            binocularSql = MysqldbOperational(host=mysql_host,
+                                              username=mysql_username,
+                                              password=mysql_password,
+                                              port=mysql_port,
+                                              database=binocular_database,
+                                              logger=_logger)
+
+            sonarSql = MysqldbOperational(host=mysql_host,
+                                          username=mysql_username,
+                                          password=mysql_password,
+                                          port=mysql_port,
+                                          database=sonar_database,
+                                          logger=_logger)
+            deal_data()

+ 85 - 0
001_h511/imageCapture/upload_camera_profile.py

@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# encoding: utf-8
+"""
+@CreateTime: 2021/8/5 9:54
+@Author: lxc
+@LastEditTime:
+@Desctiption: 上行数据:上传(更新)摄像设备配置文件到云平台
+"""
+
+import configparser
+import time
+import os
+import requests
+from requests_toolbelt.multipart import MultipartEncoder
+import LogOut
+
+
+def post_upload_file():
+    """
+    上传二进制字节流文件
+    :return: "SUCCESS" or "ERROR"
+    """
+    now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
+    headers = {
+        "Authorization": token,
+        "userAccount": '1'
+    }
+    multipart_encoder = MultipartEncoder(
+        fields={
+            "file": (FILENAME, open(config_path, 'rb'), "multipart/form-data")
+        }
+    )
+
+    headers['Content-Type'] = multipart_encoder.content_type
+    requests.urllib3.disable_warnings()
+    url = "https://management.super-sight.com.cn:8000/system/api/cameraManagement/cameraInfoFileUpload"
+    ret = requests.post(url=url, headers=headers, data=multipart_encoder, verify=False)
+
+    if ret.status_code == 200 and "success" in ret.text:
+        _logger.info("%s: ret.text=%s" % (now_time, ret.text))
+        _logger.info("%s: ret.status_code=%s" % (now_time, ret.status_code))
+    else:
+        _logger.error("%s: ret.text=%s" % (now_time, ret.text))
+        _logger.error("%s: ret.status_code=%s" % (now_time, ret.status_code))
+
+def main():
+    """
+    判断文件是否需要更新
+    :return: 无
+    """
+    run_time = 0
+    file_time = 0
+    while True:
+        now_time = time.time()
+        if now_time - run_time > 60*60:
+            run_time = now_time
+            status = os.path.exists(config_path)
+            if status:
+                file_new_time = os.path.getmtime(config_path)
+                if file_time != file_new_time:
+                    file_time = file_new_time
+                    post_upload_file()
+            else:
+                _logger.error("未找到目标文件:" + config_path)
+
+
+
+if __name__ == '__main__':
+
+    _logger = LogOut.Log('uploadCameraProfile')
+
+    # 创建读取配置文件对象
+    config = configparser.ConfigParser()
+    config.read("config.ini", encoding="utf-8")
+
+    # 获取通用配置项
+    SECTION = "General"  # 读取的SECTION标签
+    token = config.get(SECTION, 'token')
+    appId = config.get(SECTION, 'appId')
+
+    FILEPATH = r"/home/sencott/imageCapture/configration_files"
+    FILENAME = "云平台导入海上平台摄像配置文件模板.xlsx"
+    config_path = os.path.join(FILEPATH, FILENAME)
+    main()
+