Python-Tkinter+Logging+Sqlserver项目结合

参考文章:
https://www.jb51.net/article/283745.htm

目录:

  • common(文件夹)
    – base.py
    – config_reader.py
    – dosqlserver.py
    – log.py

  • txt(空文件夹,后面会自动生成txt文件在该文件夹下面)

  • 1.txt

  • 2.txt

  • env.info.cfg

  • main.py(执行文件)

common 文件夹下:

base.py文件

import os
import shutil
import time
from common.log import Log
from common.dosqlserver import ExceteSqlserver
import glob


single_ticket = {}

class base:
    def __init__(self):
        self.log = Log()


    def exe_cmd(self, cmd):
        result = os.popen(cmd).read()
        return result

    def execute_sql(self,db,metting_code):
        db_service = ExceteSqlserver(db)
        sql = "SELECT chrims_event_code,date_meeting,venue_code FROM meeting WHERE venue_code IN ('%s') ORDER by meeting_id desc" % (metting_code)
        value= db_service.exe_query(sql)
        db_service.close_db()
        code = None
        if value[0][0] == None:
            if value[0][2] == "S1":
                code = "HK1"
            elif value[0][2] == "S2":
                code = "HK2"
            elif value[0][2] == "S3":
                code = "HK3"
            elif value[0][2] == "S4":
                code = "HK4"
            elif value[0][2] == "S5":
                code = "HK5"
        else:
             code = value[0][0]
        datetime = str(value[0][1]).split(" ")[0].split("-")
        date = datetime[1]+datetime[2]+datetime[0]
        return code,date

    def remove_file(self,path):
        # 获取所有txt文件的路径
        self.txt_files = glob.glob(os.path.join(path, '*.txt'))
        self.dat_files = glob.glob(os.path.join(path, '*.dat'))

    def delete_txt(self,path):
        self.remove_file(path)
        # 删除文件
        for txt_file in self.txt_files:
            os.remove(txt_file)
        for dat_file in self.dat_files:
            os.remove(dat_file)

    def generate_dat(self,path):
        for txt_file in self.txt_files:
            time.sleep(1)
            self.exe_cmd(f"{path}TxlvTLogMkDat.exe {txt_file}")
        file = os.getcwd()
        dat = glob.glob(os.path.join(file, '*.dat'))
        for files in dat:
            shutil.copy(files, path)
            self.log.logMsg(4, f"{files} move {path} file completed ")
            # time.sleep(1)
            # os.remove(files)

    def py_remove(self,path):
        file = os.getcwd()
        dat = glob.glob(os.path.join(file, '*.dat'))
        for files in dat:
            shutil.copy(files,path)

        for remove in dat:
            os.remove(remove)


config_reader.py文件

import configparser
import os.path
import shutil


class ConfigReader:
    def __init__(self):
        self.cfg_file= "./env.info.cfg"

    def get_value(self,section, option):
        cp = configparser.ConfigParser()
        cp.read(self.cfg_file, encoding='utf-8')
        return cp.get(section, option)

    def get_sections(self):
        cp = configparser.ConfigParser()
        cp.read(self.cfg_file, encoding='utf-8')
        sections=cp.sections()
        return sections

    def write_value(self,section,option,value):
        cp = configparser.ConfigParser()
        cp.read(self.cfg_file, encoding='utf-8')
        cp.set(section,option,value)
        cp.write(open(self.cfg_file,"w"))


dosqlserver.py文件

import time
from common.config_reader import ConfigReader
from common.log import Log
import pymssql


class ExceteSqlserver:
    db_connect = None
    cursor = None



    def __init__(self,databasename):
        self.host = ConfigReader().get_value(databasename, "host")
        self.user = ConfigReader().get_value(databasename, "user")
        self.passwd = ConfigReader().get_value(databasename, "passwd")
        self.database = ConfigReader().get_value(databasename, "database")
        self.port = ConfigReader().get_value(databasename, "port")
        self.selection=ConfigReader().get_sections()  # 获取cfg的title
        self.log = Log()


    def get_db_connet(self):
        """ 输入地址 连接DB """
        try:
            db_connect = pymssql.connect(server=self.host, user=self.user, password=self.passwd, database=self.database, port=self.port)
        except Exception as e:
            self.log.logMsg(3, f"database {self.database} connect exception cause: {e}")
        else:
            if db_connect:
                pass
                # self.log.logMsg(4, f"database [{self.database}] connect success")
            cursor= db_connect.cursor()
            ExceteSqlserver.db_connect,ExceteSqlserver.cursor = db_connect,cursor
            return db_connect, cursor

    def exe_query(self,sql):
        db_connect, cursor = self.get_db_connet()
        cursor.execute(sql)
        result = cursor.fetchall() # fetchall()
        # self.close_db()
        return result

    def exe_execute(self,sql):
        db_connect, cursor = self.get_db_connet()
        cursor.execute(sql)
        db_connect.commit()
        self.close_db()

    def close_db(self):
        """ 关闭游标 关闭DB连接 """
        try:
            ExceteSqlserver.cursor.close()  # 关闭游标
            ExceteSqlserver.db_connect.close()  # 关闭DB连接
            # self.log.logMsg(4, f"close database success")
            time.sleep(3)
        except Exception as e:
            self.log.logMsg(4, f"close database exception cause: {e}")

log.py文件

import os
from common.config_reader import *

import time
import logging
import colorlog

class Log:
    def __init__(self):
        self.log_folder_path = ConfigReader().get_value("log", "log_folder_path")
        self.log_level = ConfigReader().get_value("log", "log_level")
        self.log_path = os.path.join("logs")
        if not os.path.exists(self.log_folder_path):
            os.mkdir(self.log_folder_path)
        self.logname= os.path.join(self.log_folder_path, '%s.log' % time.strftime('%Y-%m-%d'))
        self.logger = logging.getLogger()
        #输出到控制台
        self.console_handler = logging.StreamHandler()
        #输出到文件
        self.file_handler = logging.FileHandler(self.logname, mode='a', encoding='utf8')
        log_colors_config = {
            'DEBUG': 'white',
            'INFO': 'green',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'bold_red',
        }
        # 日志输出格式
        file_formatter = logging.Formatter(
            fmt='[%(asctime)s.%(msecs)03d] %(filename)s -> %(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s',
            datefmt='%Y-%m-%d %H:%M:%S'
        )
        console_formatter = colorlog.ColoredFormatter(
            fmt='%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s -> %(funcName)s line:%(lineno)d [%(levelname)s] : %(message)s',
            datefmt='%Y-%m-%d  %H:%M:%S',
            log_colors=log_colors_config
        )
        self.console_handler.setFormatter(console_formatter)
        self.file_handler.setFormatter(file_formatter)

        if not self.logger.handlers:
            self.logger.addHandler(self.console_handler)
            self.logger.addHandler(self.file_handler)
        self.console_handler.close()
        self.file_handler.close()

    def logMsg(self,level,message):
        #控制台日志输出等级
        if int(self.log_level)==1:
            self.logger.setLevel(logging.CRITICAL)
            self.console_handler.setLevel(logging.CRITICAL)
            self.file_handler.setLevel(logging.CRITICAL)
        elif int(self.log_level)==2:
            self.logger.setLevel(logging.ERROR)
            self.console_handler.setLevel(logging.ERROR)
            self.file_handler.setLevel(logging.ERROR)
        elif int(self.log_level)==3:
            self.logger.setLevel(logging.WARNING)
            self.console_handler.setLevel(logging.WARNING)
            self.file_handler.setLevel(logging.WARNING)
        elif int(self.log_level)==4:
            self.logger.setLevel(logging.INFO)
            self.console_handler.setLevel(logging.INFO)
            self.file_handler.setLevel(logging.INFO)

        elif int(self.log_level)==5:
            self.logger.setLevel(logging.DEBUG)
            self.console_handler.setLevel(logging.DEBUG)
            self.file_handler.setLevel(logging.DEBUG)
        #控制台日志输出定义
        if level==5:
            self.logger.debug(message)
        elif level==4:
            self.logger.info(message)
        elif level==3:
            self.logger.warning(message)
        elif level==2:
            self.logger.error(message)
        elif level==1:
            self.logger.critical(message)

env.info.cfg文件

[file]
txt_file_path = ./txt/
take_txt_path = E:\\002TXLV\\TOTE\\PMC\\
dat_path = E:\002TXLV\TOTE\PMC\
[log]
log_folder_path = .\logs
log_level = 4
[version]
versionid = v0.1

[xxx]
host=xx.xx.xx.xx
user=xxx
passwd=xxx
database=xx
port=40000

[xxx]
host=xx.xx.xx.158
user=xx
passwd=xxx
database=xxx
port=40000

main.py文件

import datetime
import logging
import os
from glob import glob
import shutil
from common.config_reader import ConfigReader
from common.base import base
from common.log import Log
import tkinter as tk


root = tk.Tk()
root.geometry("1000x500")
root.title("Dat file tools")
root.configure(bg='#F5F5F5')

class TextboxHandler(logging.Handler):

    def __init__(self,textbox):
        logging.Handler.__init__(self)
        self.textbox = textbox

    def emit(self, record):
        msg = self.format(record)
        self.textbox.insert("end",msg + "\n")
        
class basemethod:

    def __init__(self):
        self.tote_dict = dict()
        self.txt_file_path = ConfigReader().get_value("file", "txt_file_path")
        self.take_txt_path = ConfigReader().get_value("file", "take_txt_path")
        self.log = Log()
        self.bs = base()
        self.bs.delete_txt(self.take_txt_path)

    def dump_tote(self,venue):
        self.EventCode, self.BusDay = self.bs.execute_sql("sit_cmgc", venue)
        folder_path = self.txt_file_path
        shutil.rmtree(folder_path)
        os.mkdir(folder_path)

        input_file = "1.txt"
        tote_file = "2.txt"
        with open(tote_file, "r") as f:
            list0 = f.readlines()
        for tickets in list0:
            ts = [x.strip() for x in tickets.split("\t") if x.strip() != ""] # 清除Excel中copy出来的值 清除空格
            if ts[0] in '1':
                self.tote_dict[ts[1]] = ts[2]
                file_txt = f"{self.txt_file_path}{ts[2]}{self.EventCode}{self.BusDay}.txt"
                with open(file_txt, "w") as file:
                    file.write(f"VAR!{ts[2]}!{self.EventCode}!{self.BusDay}!USD!7.78\n")

        txt_files = glob(os.path.join(self.txt_file_path, "*.txt"))
        with open(input_file, "r") as f:
            content = f.readlines()[1:]
            tic = ''.join(content)
            for file in txt_files:
                with open(file, 'a+') as f:
                    f.write(tic)
                    # self.log.logMsg(4, f"{file}: add txt file completed ")
                    f.close()
                    # shutil.copy(file, self.take_txt_path)this an Operate could take file place to take_txt_path below
                    self.bs.exe_cmd(f"{self.take_txt_path}TxlvTLogMkDat.exe {file}")
        self.bs.py_remove(self.take_txt_path)

class TK:
    dat_path = ConfigReader().get_value("file", "dat_path")
    def clearBox(self):
        self.te.delete("1.0","end")

    def selection_text(self):
        value = self.lb.get(self.lb.curselection())  # 获取当前选中的文本
        basemethod().dump_tote(value)
        file = os.getcwd() + r"\txt"
        dat = glob(os.path.join(file, '*.txt'))
        self.log2.info("*****************************************************************************")
        for files in dat:
            s = files.replace(".txt", '.dat').split('\\')[-1]
            self.log2.info(f"TextboxHandler:{TK.dat_path}{s} Upload finishied")

    def exe(self):
        # chear bottom
        tk.Button(root,text="Chear",width=22, height=1,command=self.clearBox).place(x=350, y=450)
        tk.Button(root, text="Quit",width=22, height=1, command=root.quit).place(x=650, y=450)
        # title
        labels = tk.Label(root, text="Generate dat file tools", background='#FF8C00', width=500, font=('Arial', 30), anchor="n")
        labels.pack(side='top', expand="no", fill="x")

        # Label Venue
        Venue = tk.Label(root,text='Venue',bg='yellow',font=('黑体', 10), height=2,width=22).place(x=0,y=110)

        # 列表选择
        self.lb = tk.Listbox(root, width=26,font=('黑体', 10))
        list_items=["S1","S2","S3","S4","S5"]
        for item in list_items:
            self.lb.insert('end',item)
        self.lb.place(x=0, y=150)

        # Upload 按钮
        Upload = tk.Button(root, text="Upload",font=('Arial', 10), width=22, height=2,command=self.selection_text)
        Upload.place(x=0, y=360)  # anchor = n, ne, e, se, s, sw, w, nw

        # text
        self.te = tk.Text(root,width=80, height=20)
        self.te.place(x=250,y=110)
        self.log2 = logging.getLogger('log2')
        self.log2.setLevel(logging.INFO)
        handler = TextboxHandler(self.te)
        self.log2.addHandler(handler)

        # text.pack(side=tk.RIGHT)
        yscrollbar = tk.Scrollbar(root,orient=tk.VERTICAL)
        yscrollbar.pack(side=tk.RIGHT,fill=tk.Y)
        # 滚动条与Text联动
        yscrollbar.config(command=self.te.yview)
        # Text与滚动条联动
        self.te.config(yscrollcommand=yscrollbar.set)
        # self.te.insert(tk.END,f"{basemethod().take_txt_path} TxlvTLogMkDat.exe")


if __name__ == '__main__':
    TK().exe()
    root.mainloop()

1.txt

VAR!NTT!HK1!02042023!USD!7.78
BET!3!8UP!R28982 A2098 001BA10AB!1000!1000!5/11/6/5/12/5
BET!3!8UP!R28122 A2078 001BB10AB!1000!1000!5/11/6/5/12/1
BET!3!8UP!RA092A 08A38 089B29021!1000!1000!9/3/8/7/7/8
BET!3!8UP!RA0380 28A90 081B210B3!1000!1000!9/3/6/7/12/8
BET!3!8UP!R029A8 28000 878B3A002!10000000!10000000!1/1/1/1/2/2
PCL!3!8UP

2.txt

genFlg	ToteName	ShortName
1	PMU	PMC
1	4Racing	TVA
1	TabVIC	TBA
1	TabNSW	TBB
1	TabUBET	TBC
1	SPPL	SSS
1	PATG	PGG
1	DANSKE	DTA
1	AmGWG	HHA
1	TVGSP	ODA
0	TVGUT	POG
0	AmTote	OGE
1	AmtoteMD	MDA
0	UT	POT
1	PGI	PGA
0	AmWB	Q9A
0	Macau	MU1
0	TPOOL	UKT
0	SPTPOOL	UKB
0	NETX	LIV
0	SPTK	ODB
0	SPGTOTE	GLA
0	SPGerman	ODG
0	SPHLaneB	GLB
0	SPHLaneC	GLC
0	PBETLTD	PGE
0	PDATAP	PGF
0	AmPBET	HHC
0	WBUT	ONB
0	AmHLANE	HHH
0	NewTtAA	NTA
0	NewTtAB	NAB
0	NewTtAC	NAC
0	NewTtAD	NAD
0	NewTtAE	NAE
0	NewTtF	NTF
0	NewTtG	NTG
0	NewTtH	NTH
0	NewTtI	NTI
0	NewTtJ	NTJ
0	NewTtK	NTK
0	NewTtL	NTL
0	NewTtM	NTM
0	NewTtN	NTN
0	NewTtO	NTO
0	NewTtP	NTP
0	NewTtQ	NTQ
0	NewTtR	NTR
0	NewTtS	NTS
0	NewTtT	NTT

生成文件的运行日志:

[2024-07-02  11:10:53.586] main.py -> selection_text line:80 [INFO] : *****************************************************************************
[2024-07-02  11:10:53.587] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\DTAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.587] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\HHAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.587] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\MDAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.587] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\ODAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.588] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\PGAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.588] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\PGGHK102102023.dat Upload finishied
[2024-07-02  11:10:53.588] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\PMCHK102102023.dat Upload finishied
[2024-07-02  11:10:53.588] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\SSSHK102102023.dat Upload finishied
[2024-07-02  11:10:53.588] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\TBAHK102102023.dat Upload finishied
[2024-07-02  11:10:53.589] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\TBBHK102102023.dat Upload finishied
[2024-07-02  11:10:53.589] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\TBCHK102102023.dat Upload finishied
[2024-07-02  11:10:53.589] main.py -> selection_text line:83 [INFO] : TextboxHandler:E:\002TXLV\TOTE\PMC\TVAHK102102023.dat Upload finishied

功能介绍:
Upload 是加载出来Dat文件日志在Text文本框:
chear:是清除Text文本框日志
Quit:是退出
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/766007.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

非平稳信号的时频表示-基于本征模态函数(MATLAB)

时频分析思想萌芽于匈牙利物理学家 Gabor 在 1946 年所提出的 Gabor 展开理论,随后以此为基础发展出著名的线性时频变换方法—短时傅里叶变换。短时傅里叶变换假设分析信号在有限时长内具有平稳特性,它首先将时间与频率均为有限支撑的窗函数与分析信号进…

973. 最接近原点的 K 个点-k数组维护+二分查找

973. 最接近原点的 K 个点-k数组维护二分查找 给定一个数组 points ,其中 points[i] [xi, yi] 表示 X-Y 平面上的一个点,并且是一个整数 k ,返回离原点 (0,0) 最近的 k 个点。 这里,平面上两点之间的距离是 欧几里德距离&#…

Linux修炼之路之进程概念,fork函数,进程状态

目录 一:进程概念 二:Linux中的进程概念 三:用getpid(),getppid()获取该进程的PID,PPID 四:用fork()来创建子进程 五:操作系统学科的进程状态 六:Linux中的进程状态 接下来的日子会顺顺利利&#xf…

【MySQL备份】Percona XtraBackup加密备份实战篇

目录 1.前言 2.准备工作 2.1.环境信息 2.2.配置/etc/my.cnf文件 2.3.授予root用户BACKUP_ADMIN权限 2.4.生成加密密钥 2.5.配置加密密钥文件 3.加密备份 4.优化加密过程 5.解密加密备份 6.准备加密备份 7.恢复加密备份 7.1.使用rsync进行恢复 7.2.使用xtrabackup命令恢…

crewAI实践过程中,memory规避openai的使用方法以及(windows下xinferece框架使用踩过的坑)

问题: 在使用crewAI开发项目的过程中,memory开启后报错:openai key is fake 经代码核查,其默认使用了openai的embedding模型。 解决方法 经查阅资料,可以参考其本地部署llm的方法。 本地部署模型可以使用xinference…

人工智能导论速成笔记

文章目录 前言考试题型第一章、人工智能导引 (10分 )课后习题第二章、Python基础 (10分 )*文件读写NumPy的使用Python绘图基础第三章、机器学习初步(15分 )逻辑回归分类(Logistic Regression)*,3.5线性回归预测(Linear Regression)*,3.6 、3.7、 3.8聚类 3.9第四章、自然语言…

【信息系统项目管理师】常见图表

作文里面的画图题用语言描述画图过程 合同 采购综合评分标准 责任分配矩阵 成本预算表 成本估算 成本管理计划 活动清单 活动属性 变更日志 问题日志 项目章程 自己再添加更多内容 甘特图 甘特图包含以下三个含义: 1、以图形或表格的形式显示活动; 2、…

uniapp封装虚拟列表滚动组件

uniapp封装虚拟列表滚动组件 这里用到一个列表&#xff0c;然后数据可能有很多很多…&#xff0c;一次性全部渲染到dom上会卡顿&#xff0c;很废性能&#xff0c;于是用了这个虚拟列表就变丝滑很多很多。 组件mosoweInventedList 代码&#xff1a; <!-- 虚拟滚动列表组件&a…

常见VPS主机术语有哪些?VPS术语解析

常见VPS主机术语有哪些&#xff1f;本期为大家解析一下我们常见到的听到的VPS专业术语&#xff0c;帮助大家更轻松的了解VPS主机相关知识。 常见VPS主机术语 Apache – 世界上最流行的 Web 服务器软件。 CentOS – 旨在提供基于 Red Hat Enterprise Linux 的企业级操作系统的…

常微分方程算法之编程示例七-两点混合边值问题(打靶法)

目录 一、研究问题 二、C++代码 三、计算结果 一、研究问题 本节我们采用打靶法求解两点混合边值问题,打靶法的原理及推导思路请参考: 常微分方程算法之“两点边值问题”求解-CSDN博客https://blog.csdn.net/L_peanut/article/details/137449287 研究问题为

学习笔记(linux高级编程)9

void pthread_cleanup_push(void (*routine)(void *)&#xff0c; void *arg); 功能&#xff1a;注册一个线程清理函数 参数&#xff0c;routine&#xff0c;线程清理函数的入口 arg&#xff0c;清理函数的参数。 返回值&#xff0c;无 void pthread_cleanup_pop(int execute)…

Node.js学习(一)

Node.js安装与入门案例&#xff1a; 需求&#xff1a;点击按钮&#xff0c;请求本地目录指定文件的内容&#xff0c;并显示在页面上 刚入门肯定想着直接写相对路径请求指定路径数据就行了&#xff0c;可是会发现不行。 网页运行在浏览器端&#xff0c;通常后续要发布&#xf…

大模型应用开发实战基础

大模型应用开发实战基础 1. 背景 大模型如日中天&#xff0c;各行各业都受它影响&#xff0c;但是作为程序员&#xff0c;除了让它翻译代码不知道用它干什么&#xff0c;就像是拿着锤子的木匠&#xff0c;找不到钉子在哪。一边听着别人说2024是AI元年&#xff0c;一边又不知所…

数组-二分查找

二分查找 leetcode704 /*** param {number[]} nums* param {number} target* return {number}*/ var search function(nums, target) {let left 0, right nums.length - 1;while (left < right) {const mid Math.floor((right - left) / 2) left;const num nums[mid]…

【antd + vue】表格行合并,同时使用插槽

一、需求说明 表格中&#xff0c;如果一个学校有多个考试科目&#xff0c;则分行展示&#xff0c;其余列&#xff0c;则合并为一行展示&#xff0c;如图所示 二、需求分析 1、表格行合并 相当于有4行&#xff0c;其中1、2行是同一个学校包含不同考试科目及对应人次的数据&am…

生成式AI赋能金融信贷:减少信用评分偏差

信用评分在确定谁获得信贷以及以何种条件获得信贷方面发挥着关键作用。然而&#xff0c;尽管这一点很重要&#xff0c;但传统的信用评分系统长期以来一直受到一系列关键问题的困扰——从偏见和歧视&#xff0c;到有限的数据考虑和可扩展性挑战。例如&#xff0c;一项针对美国贷…

1:25万基础电子地图(西藏版)

我们为你分享过四川版、云南版、江西版、贵州版、重庆版和青海版的1比25万基础电子地图&#xff0c;现在再为你分享西藏版的电子地图。 如果你需要西藏版的1比25万基础电子地图&#xff0c;你可以在文末查看该数据的领取方法。 基础电子地图西藏版 西藏版1:25万基础电子地图…

Xilinx FPGA:vivado利用单端RAM/串口传输数据实现自定义私有协议

一、项目要求 实现自定义私有协议&#xff0c;如&#xff1a;pc端产生数据&#xff1a;02 56 38 &#xff0c;“02”代表要发送数据的个数&#xff0c;“56”“38”需要写进RAM中。当按键信号到来时&#xff0c;将“56”“38”读出返回给PC端。 二、信号流向图 三、状态…

FVCOM水环境、污染物迁移、水交换、水质、潮流、温盐、波浪及泥沙数值模拟

原文链接&#xff1a;FVCOM水环境、污染物迁移、水交换、水质、潮流、温盐、波浪及泥沙数值模拟https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247607618&idx2&sn5132fb8bfcbd02c2be308f6c6304c6d2&chksmfa8264a5cdf5edb3226d1b0597bb6c39f867601b961b…

[开源软件] 支持链接汇总

“Common rules: 1- If the repo is on github, the support/bug link is also on the github with issues”" label; 2- Could ask questions by email list;" 3rd party software support link Note gcc https://gcc.gnu.org openssh https://bugzilla.mindrot.o…