本文最后更新于:18 天前
路段版本 Sa-Token
2026 年 1 月 13 日
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 package com.tomm.framework.config;import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;import cn.dev33.satoken.interceptor.SaRouteInterceptor;import cn.dev33.satoken.jwt.StpLogicJwtForSimple;import cn.dev33.satoken.router.SaRouter;import cn.dev33.satoken.stp.StpLogic;import cn.dev33.satoken.stp.StpUtil;import com.tomm.common.utils.spring.SpringUtils;import com.tomm.framework.config.properties.ExcludeUrlProperties;import com.tomm.framework.config.properties.SecurityProperties;import lombok.RequiredArgsConstructor;import lombok.extern.slf4j.Slf4j;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@RequiredArgsConstructor @Slf4j @Configuration public class SaTokenConfig implements WebMvcConfigurer { private final SecurityProperties securityProperties; @Override public void addInterceptors (InterceptorRegistry registry) { registry.addInterceptor(new SaRouteInterceptor ((request, response, handler) -> { ExcludeUrlProperties excludeUrlProperties = SpringUtils.getBean(ExcludeUrlProperties.class); SaRouter .match("/**" ) .notMatch(securityProperties.getExcludes()) .notMatch(excludeUrlProperties.getExcludes()) .check(() -> { StpUtil.checkLogin(); }); })).addPathPatterns("/**" ); registry.addInterceptor(new SaAnnotationInterceptor ()).addPathPatterns("/**" ); } @Bean public StpLogic getStpLogicJwt () { return new StpLogicJwtForSimple (); } }
核心方法解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package com.tomm.framework.config.properties;import cn.hutool.core.util.ReUtil;import com.tomm.common.annotation.Anonymous;import com.tomm.common.utils.spring.SpringUtils;import lombok.Getter;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.annotation.Lazy;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.stereotype.Component;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import org.springframework.web.util.pattern.PathPattern;import java.util.*;import java.util.regex.Pattern;@Lazy @Component public class ExcludeUrlProperties implements InitializingBean { private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}" ); @Getter private final List<String> excludes = new ArrayList <>(); @Override public void afterPropertiesSet () { String asterisk = "*" ; RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping" , RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods(); map.keySet().forEach(info -> { HandlerMethod handlerMethod = map.get(info); Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); Optional.ofNullable(method).ifPresent(anonymous -> { Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns(); patterns.forEach(url -> { excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); }); }); Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); Optional.ofNullable(controller).ifPresent(anonymous -> { Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns(); patterns.forEach(url -> { excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); }); }); }); } }
afterPropertiesSet()方法
步骤1:获取所有接口映射
1 2 RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping" , RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
从 Spring 容器中获取 RequestMappingHandlerMapping(Spring MVC 的核心组件,存储所有Controller的映射信息)
获取所有接口映射的 Map,key 是接口信息,value 是处理方法
步骤2:扫描方法上的 @Anonymous注解
1 2 3 4 5 6 7 8 9 10 Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); Optional.ofNullable(method).ifPresent(anonymous -> { Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns(); patterns.forEach(url -> { excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); }); });
如果方法上有 @Anonymous注解,收集其所有URL
将路径变量(如 {id})替换为 *
示例:/api/users/{id}→ /api/users/*
步骤3:扫描类上的 @Anonymous注解
1 2 3 4 5 Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); Optional.ofNullable(controller).ifPresent(anonymous -> { });
如果 Controller 类上有 @Anonymous注解,该类下所有接口都允许匿名访问
小屏概览
2026 年 1 月 13 日
本机调试。
已部署的路段版本接口文档,测试环境:OpenAPI definition
路段版本接口文档,本机启动,OpenAPI definition
测试这个接口,POST 请求。
1 http:// localhost:10057 /smallScreenDispla/m onitorSummary
小屏概览接口,查询本机的cpu、内存、磁盘、上下行参数
1 2 3 4 5 6 @Operation(summary = "小屏概览接口,查询本机的cpu、内存、磁盘、上下行参数") @PostMapping("/monitorSummary") public R<MonitorSummaryVo> monitorSummary (@RequestBody SyncAssetInfoDto syncAssetInfoDto) { System.out.println("小屏概览接口,查询本机的cpu、内存、磁盘、上下行参数" ); return R.ok(smallScreenDisplayService.monitorSummary(syncAssetInfoDto)); }
1 2 3 4 5 6 7 8 MonitorSummaryVo monitorSummaryVo = new MonitorSummaryVo (); List<SectionHostDeptMap> sectionHostDeptMapList = sectionHostDeptMapService.selectSectionHostDeptMapByHostTypeAndDeptId( Lists.newArrayList(syncAssetInfoDto.getDeptId()), Lists.newArrayList((byte )10 )); log.info("查询概览参数,获取本机资产数据结果:{}" , JsonUtils.toJsonString(sectionHostDeptMapList)); if (CollUtil.isEmpty(sectionHostDeptMapList) || sectionHostDeptMapList.size() > RmgtMagicValue.ONE) { throw new ServiceException ("获取资产信息有误" ); }
1 2 3 4 5 6 7 List<SectionHostDeptMap> selectSectionHostDeptMapByHostTypeAndDeptId (List<Long> deptIds, List<Byte> hostTypes) ;
1 2 3 4 @Override public List<SectionHostDeptMap> selectSectionHostDeptMapByHostTypeAndDeptId (List<Long> deptIds, List<Byte> hostTypes) { return sectionHostDeptMapMapper.selectSectionHostDeptMapByHostTypeAndDeptId(deptIds, hostTypes); }
1 2 3 4 5 6 7 8 List<SectionHostDeptMap> selectSectionHostDeptMapByHostTypeAndDeptId (@Param("deptIds") List<Long> deptIds, @Param("hostTypes") List<Byte> hostTypes) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <select id ="selectSectionHostDeptMapByHostTypeAndDeptId" parameterType ="java.lang.Byte" resultType ="com.tomm.system.domain.SectionHostDeptMap" > SELECT <include refid ="Base_Column_List" /> FROM t_section_host_dept_map <where > <if test ="deptIds != null and deptIds.size() > 0" > AND dept_id IN <foreach item ="item" collection ="deptIds" open ="(" separator ="," close =")" > #{item} </foreach > </if > <if test ="hostTypes != null and hostTypes.size() > 0" > AND host_type IN <foreach item ="item" collection ="hostTypes" open ="(" separator ="," close =")" > #{item} </foreach > </if > </where > </select >
Lists.newArrayList((byte)10)创建了一个包含单个字节值 10 的 List,表示查询主机类型为 10 的记录。
小屏监测
2026 年 1 月 15 日
1 2 3 4 5 6 7 8 9 10 log.info("查询路段、门架、车道、设备等主机列表,入参:{}" , JsonUtils.toJsonString(monitorAssetDto));if (CollUtil.isEmpty(monitorAssetDto.getMonitorHostTypeAll())) { throw new ServiceException ("监测的主机类型列表为空" ); }if (ObjUtil.isEmpty(monitorAssetDto.getMonitorHostType())) { throw new ServiceException ("当前监测的主机类型为空" ); }if (ObjUtil.isEmpty(monitorAssetDto.getDeptId())) { throw new ServiceException ("当前监测的部门为空" ); }
1 2 3 4 5 List<SysDept> selectSysDeptAndSubDeptById(@Param("deptId" ) Long deptId);
1 2 3 4 5 6 7 8 9 <select id="selectSysDeptAndSubDeptById" parameterType="java.lang.Long" resultType="com.tomm.common.core.domain.entity.SysDept" > SELECT <include refid="Base_Column_List" /> FROM sys_dept WHERE (del_flag = '0' and (dept_id=#{deptId} or FIND_IN_SET(#{deptId},ancestors))) ORDER BY parent_id ASC , order_num ASC </select >
1 2 3 4 5 6 7 8 9 Long countHostsByDeptAndType (@Param ("deptIds" ) List<Long> deptIds, @Param ("hostTypes" ) List<Byte> hostTypes);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 MonitorAssetVo monitorAssetVo = new MonitorAssetVo() ; for (String type : monitorAssetDto.getMonitorHostTypeAll() ) { if (MonitorHostTypeEnum .STATION . getKey() .equals(type )) { monitorAssetVo.setStationHostNum(sectionHostDeptMapService .countHostsByDeptAndType (deptIds , MonitorHostTypeEnum.STATION.getValue () )); } if (MonitorHostTypeEnum .LANE . getKey() .equals(type )) { monitorAssetVo.setLaneHostNum(sectionHostDeptMapService .countHostsByDeptAndType (deptIds , MonitorHostTypeEnum.LANE.getValue () )); } if (MonitorHostTypeEnum .GANTRY . getKey() .equals(type )) { monitorAssetVo.setGantryHostNum(sectionHostDeptMapService .countHostsByDeptAndType (deptIds , MonitorHostTypeEnum.GANTRY.getValue () )); } }
站服务器数,车道工控机数,门架工控机。t_section_host_dept_map
1 2 3 4 5 6 7 8 9 10 //查询主机列表 Page<MonitorAssetHost> monitorAssetHostList = sectionHostDeptMapService.selectAssetHostListPage(deptIds, hostTypes, monitorAssetDto .getMonitorStateType(), monitorAssetDto .build()); //转换HostTypeName for (MonitorAssetHost monitorAssetHost : monitorAssetHostList.getRecords()) { monitorAssetHost.set HostTypeName(HostTypeEnum.getValue(monitorAssetHost.getHostType())); } monitorAssetVo.set HostTos (monitorAssetHostList); log .info("查询路段、门架、车道、设备等主机列表,返参:{}" , JsonUtils.to JsonString(monitorAssetVo)); return monitorAssetVo;
1 2 3 4 5 6 7 8 9 /* * * 查询资产主机列表,带监测状态 * * @param deptIds 部门ID集合(为空时查询所有) * @param hostTypes 主机类型 * @param page 分页参数 * @return 资产主机状态列表 * / Page<MonitorAssetHost> selectAssetHostListPage(List<Long> deptIds, List<Byte> hostTypes, String monitorStateType, Page<MonitorAssetHost> page);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <select id="selectAssetHostListPage" parameterType="map" resultType="com.tomm.system.domain.vo.MonitorAssetHost"> SELECT shdm.host_ip, shdm.host_type, shdm.update_time, h.name as hostName, if (h.`status`='0' ,'1' ,'0' ) monitorState FROM t_section_host_dept_map shdm left JOIN zabbix.hosts h ON h.hostid = shdm.host_id <where > <if test="deptIds != null and deptIds.size() > 0"> AND shdm.dept_id IN <foreach item="item" collection="deptIds" open ="(" separator="," close =")"> #{item} </foreach > </if > <if test="hostTypes != null and hostTypes.size() > 0"> AND shdm.host_type IN <foreach item="item" collection="hostTypes" open ="(" separator="," close =")"> #{item} </foreach > </if > <if test="monitorStateType != null and monitorStateType != ''"> AND h.`status`!= #{monitorStateType} </if > </where > </select >
这个 page 怎么没用过。
1 2 3 4 5 6 7 8 9 10 11 Page<MonitorAssetHost> selectAssetHostListPage(@Param("deptIds" ) List<Long > deptIds, @Param("hostTypes" ) List<Byte > hostTypes, @Param("monitorStateType" ) String monitorStateType, Page<MonitorAssetHost> page);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <select id="selectAssetHostListPage" parameterType="map" resultType="com.tomm.system.domain.vo.MonitorAssetHost"> SELECT shdm.host_ip, shdm.host_type, shdm.update_time, h.name as hostName, if (h.`status`='0' ,'1' ,'0' ) monitorState FROM t_section_host_dept_map shdm left JOIN zabbix.hosts h ON h.hostid = shdm.host_id <where > <if test="deptIds != null and deptIds.size() > 0"> AND shdm.dept_id IN <foreach item="item" collection="deptIds" open ="(" separator="," close =")"> #{item} </foreach > </if > <if test="hostTypes != null and hostTypes.size() > 0"> AND shdm.host_type IN <foreach item="item" collection="hostTypes" open ="(" separator="," close =")"> #{item} </foreach > </if > <if test="monitorStateType != null and monitorStateType != ''"> AND h.`status`!= #{monitorStateType} </if > </where > </select >
有问题。所以这里构造的page对象,PageSize竟然是0,pageNum是1,这不对吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 public <T> Page<T> build() { Integer pageNum = ObjectUtil . defaultIfNull(getPageNum () , DEFAULT_PAGE_NUM); Integer pageSize = ObjectUtil . defaultIfNull(getPageSize () , DEFAULT_PAGE_SIZE); if (pageNum <= 0 ) { pageNum = DEFAULT_PAGE_NUM; } if (pageSize == null || pageSize <= 0 ) { pageSize = DEFAULT_PAGE_SIZE; } Page<T> page = new Page<>(pageNum, pageSize); OrderItem orderItem = buildOrderItem() ; if (ObjectUtil . isNotNull(orderItem ) ) { page.addOrder(orderItem ) ; } return page; }
成功了,PageSize 默认查询所有记录。
罗芬科技 主板
2026 年 2 月 9 日
(99+ 封私信 / 81 条消息) 电脑主板主要由那些部分组成,它们的作用是什么? - 知乎
固态硬盘接口,规格。
SATA、mSATA、M.2、M.2(NVMe)、PCIE固态硬盘接口详解-腾讯云开发者社区-腾讯云
1 SATA 一般指串行ATA。 串行ATA的全称是Serial Advanced Technology Attachment,是由Intel、IBM、Dell、APT、Maxtor和Seagate公司共同提出的硬盘接口规范,在IDF Fall 2001 大会上,Seagate宣布了Serial ATA 1 .0 标准,正式宣告了SATA规范的确立。
SATA硬盘接口_百度百科
m.2接口sata和pcie区别_M2固态硬盘安装方法-腾讯云开发者社区-腾讯云
PCIE 接口。
1 PCI - E 接口:在传统SATA 硬盘中,当我们进行数据操作时,数据会先从硬盘读取到内存,再将数据提取至CPU 内部进行计算,计算后写入内存,存储至硬盘中;而PCI - E 就不一样了,数据直接通过总线与CPU 直连,省去了内存调用硬盘的过程,传输效率与速度都成倍提升。
今天才知道固态硬盘原来还有这么多种-腾讯云开发者社区-腾讯云
(99+ 封私信 / 81 条消息) pcie 接口长什么样呢?它有哪些用处呢? - 知乎
工控主板上PCIE插槽有什么作用?
M.2接口。
内存条插槽规格。
标书
2026 年 2 月 3 日
📊 招标投标全流程解析,详细步骤一览 📊
大彩
2026 年 2 月 2 日
VisualTFT_开发软件_广州大彩专注组态串口屏,国内首创《虚拟串口屏》,大彩屏无需购买硬件!主营串口屏,串口显示屏,86面板,串口彩屏,触摸屏,HMI人机界面
QT环境
2026 年 1 月 30 日
麒麟系统离线极速安装QT_麒麟系统安装qt-CSDN博客
国产Linux麒麟系统QT安装及其之后安装QChart库步骤_linux 下 qt安装程序库-CSDN博客
1 2 3 4 5 6 7 8 9 10 11 12 loongson@loongson-pc:~$ ./qt-opensource-linux-x64-5.14.2.run -bash: ./qt-opensource-linux-x64-5.14.2.run: 权限不够 loongson@loongson-pc:~$ chmod 777 ./qt-opensource-linux-x64-5.14.2.run loongson@loongson-pc:~$ ./qt-opensource-linux-x64-5.14.2.run not found LASX, use 128-bit vectors qt.qpa.xcb: could not connect to display qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found. This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. Available platform plugins are: minimal, xcb. 已放弃 (核心已转储)
Qt5.15下载和安装教程「建议收藏」-腾讯云开发者社区-腾讯云
Git认证
2026 年 1 月 28 日
1 ssh -T git@101.227.48.102 -p 2
1 ssh -Tvvv git@101.227.48.102 -p 2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 C:\WINDOWS\system32>ssh -Tvvv git@101.227 .48.102 -p 22 OpenSSH_for_Windows_9.5 p1, LibreSSL 3.8 .2 debug1: Reading configuration data C:\\Users\\Lenovo/.ssh/ config debug3: Failed to open file :C:/ProgramData/ ssh/ssh_config error:2 debug2: resolve_canonicalize: hostname 101.227 .48.102 is address debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts' -> 'C:\\Users\\Lenovo/.ssh/known_hosts' debug3: expanded UserKnownHostsFile '~/.ssh/known_hosts2' -> 'C:\\Users\\Lenovo/.ssh/known_hosts2' debug3: ssh_connect_direct: entering debug1: Connecting to 101.227 .48.102 [101.227 .48.102 ] port 22 . debug1: Connection established. debug1: identity file C:\\Users\\Lenovo/.ssh/i d_rsa type 0 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_rsa-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_rsa-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_rsa-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_rsa-cert type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ecdsa type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ecdsa-cert type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ecdsa_sk type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ecdsa_sk-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ecdsa_sk-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ed25519 type 3 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ed25519-cert type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ed25519_sk type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_ed25519_sk-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_ed25519_sk-cert type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_xmss type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_xmss-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_xmss-cert type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_dsa type -1 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa-cert error:2 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa-cert.pub error:2 debug3: failed to open file :C:/Users/ Lenovo/.ssh/i d_dsa-cert error:2 debug1: identity file C:\\Users\\Lenovo/.ssh/i d_dsa-cert type -1 debug1: Local version string SSH-2.0 -OpenSSH_for_Windows_9.5 debug1: Remote protocol version 2.0 , remote software version OpenSSH_8.0 debug1: compat_banner: match: OpenSSH_8.0 pat OpenSSH* compat 0 x04000000 debug2: fd 3 setting O_NONBLOCK debug1: Authenticating to 101.227 .48.102 :22 as 'git' debug3: record_hostkey: found key type ED25519 in file C:\\Users\\Lenovo/.ssh/ known_hosts:10 debug3: load_hostkeys_file: loaded 1 keys from 101.227 .48.102 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/ known_hosts2 error:2 debug1: load_hostkeys: fopen C:\\Users\\Lenovo/.ssh/ known_hosts2: No such file or directory debug3: Failed to open file :C:/ProgramData/ ssh/ssh_known_hosts error:2 debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directory debug3: Failed to open file :C:/ProgramData/ ssh/ssh_known_hosts2 error:2 debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directory debug3: order_hostkeyalgs: have matching best-preference key type ssh-ed25519-cert-v01@openssh.com, using HostkeyAlgorithms verbatim debug3: send packet: type 20 debug1: SSH2_MSG_KEXINIT sent debug3: receive packet: type 20 debug1: SSH2_MSG_KEXINIT received debug2: local client KEXINIT proposal debug2: KEX algorithms: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group -exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,ext-info-c,kex-strict-c-v00@openssh.com debug2: host key algorithms: ssh-ed25519-cert-v01@openssh.com,ecdsa-sha2-nistp256-cert-v01@openssh.com,ecdsa-sha2-nistp384-cert-v01@openssh.com,ecdsa-sha2-nistp521-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com,sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,rsa-sha2-512 -cert-v01@openssh.com,rsa-sha2-256 -cert-v01@openssh.com,ssh-ed25519,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ssh-ed25519@openssh.com,sk-ecdsa-sha2-nistp256@openssh.com,rsa-sha2-512 ,rsa-sha2-256 debug2: ciphers ctos: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com debug2: ciphers stoc: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com debug2: MACs ctos: umac-64 -etm@openssh.com,umac-128 -etm@openssh.com,hmac-sha2-256 -etm@openssh.com,hmac-sha2-512 -etm@openssh.com,umac-64 @openssh.com,umac-128 @openssh.com,hmac-sha2-256 ,hmac-sha2-512 debug2: MACs stoc: umac-64 -etm@openssh.com,umac-128 -etm@openssh.com,hmac-sha2-256 -etm@openssh.com,hmac-sha2-512 -etm@openssh.com,umac-64 @openssh.com,umac-128 @openssh.com,hmac-sha2-256 ,hmac-sha2-512 debug2: compression ctos: none,zlib@openssh.com,zlib debug2: compression stoc: none,zlib@openssh.com,zlib debug2: languages ctos: debug2: languages stoc: debug2: first_kex_follows 0 debug2: reserved 0 debug2: peer server KEXINIT proposal debug2: KEX algorithms: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group -exchange-sha256,diffie-hellman-group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group -exchange-sha1,diffie-hellman-group14-sha1 debug2: host key algorithms: rsa-sha2-512 ,rsa-sha2-256 ,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519 debug2: ciphers ctos: aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc debug2: ciphers stoc: aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes256-ctr,aes256-cbc,aes128-gcm@openssh.com,aes128-ctr,aes128-cbc debug2: MACs ctos: hmac-sha2-256 -etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128 -etm@openssh.com,hmac-sha2-512 -etm@openssh.com,hmac-sha2-256 ,hmac-sha1,umac-128 @openssh.com,hmac-sha2-512 debug2: MACs stoc: hmac-sha2-256 -etm@openssh.com,hmac-sha1-etm@openssh.com,umac-128 -etm@openssh.com,hmac-sha2-512 -etm@openssh.com,hmac-sha2-256 ,hmac-sha1,umac-128 @openssh.com,hmac-sha2-512 debug2: compression ctos: none,zlib@openssh.com debug2: compression stoc: none,zlib@openssh.com debug2: languages ctos: debug2: languages stoc: debug2: first_kex_follows 0 debug2: reserved 0 debug1: kex: algorithm: curve25519-sha256 debug1: kex: host key algorithm: ssh-ed25519 debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none debug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: none debug3: send packet: type 30 debug1: expecting SSH2_MSG_KEX_ECDH_REPLY debug3: receive packet: type 31 debug1: SSH2_MSG_KEX_ECDH_REPLY received debug1: Server host key: ssh-ed25519 SHA256:CPXsWA3qquwUoOVeMDDaHHbgsc1zmJWrM01Yoy6hMmI debug3: record_hostkey: found key type ED25519 in file C:\\Users\\Lenovo/.ssh/ known_hosts:10 debug3: load_hostkeys_file: loaded 1 keys from 101.227 .48.102 debug3: Failed to open file :C:/Users/ Lenovo/.ssh/ known_hosts2 error:2 debug1: load_hostkeys: fopen C:\\Users\\Lenovo/.ssh/ known_hosts2: No such file or directory debug3: Failed to open file :C:/ProgramData/ ssh/ssh_known_hosts error:2 debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directory debug3: Failed to open file :C:/ProgramData/ ssh/ssh_known_hosts2 error:2 debug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directory debug1: Host '101.227.48.102' is known and matches the ED25519 host key. debug1: Found key in C:\\Users\\Lenovo/.ssh/ known_hosts:10 debug3: send packet: type 21 debug2: ssh_set_newkeys: mode 1 debug1: rekey out after 134217728 blocks debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug3: receive packet: type 21 debug1: SSH2_MSG_NEWKEYS received debug2: ssh_set_newkeys: mode 0 debug1: rekey in after 134217728 blocks debug3: ssh_get_authentication_socket_path: path '\\\\.\\pipe\\openssh-ssh-agent' debug3: unable to connect to pipe \\\\.\\pipe\\openssh-ssh-agent, error: 2 debug1: get_agent_identities: ssh_get_authentication_socket: No such file or directory debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_rsa RSA SHA256:18 HfOCQvT8zCV5AVrzxYRzhwO4W0HB0pOhzCk8klaLw debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_ecdsa debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_ecdsa_sk debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_ed25519 ED25519 SHA256:314 LS48LcdNWWV6CRzNlB0/oeBGMioEXuiYGuMtMAAM debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_ed25519_sk debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_xmss debug1: Will attempt key: C:\\Users\\Lenovo/.ssh/i d_dsa debug2: pubkey_prepare: done debug3: send packet: type 5 debug3: receive packet: type 7 debug1: SSH2_MSG_EXT_INFO received debug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,rsa-sha2-256 ,rsa-sha2-512 ,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521> debug3: receive packet: type 6 debug2: service_accept: ssh-userauth debug1: SSH2_MSG_SERVICE_ACCEPT received debug3: send packet: type 50 debug3: receive packet: type 51 debug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with-mic,password debug3: start over, passed a different list publickey,gssapi-keyex,gssapi-with-mic,password debug3: preferred publickey,keyboard-interactive,password debug3: authmethod_lookup publickey debug3: remaining preferred: keyboard-interactive,password debug3: authmethod_is_enabled publickey debug1: Next authentication method: publickey debug1: Offering public key: C:\\Users\\Lenovo/.ssh/i d_rsa RSA SHA256:18 HfOCQvT8zCV5AVrzxYRzhwO4W0HB0pOhzCk8klaLw debug3: send packet: type 50 debug2: we sent a publickey packet, wait for reply debug3: receive packet: type 51 debug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with-mic,password debug1: Trying private key: C:\\Users\\Lenovo/.ssh/i d_ecdsa debug3: no such identity: C:\\Users\\Lenovo/.ssh/i d_ecdsa: No such file or directory debug1: Trying private key: C:\\Users\\Lenovo/.ssh/i d_ecdsa_sk debug3: no such identity: C:\\Users\\Lenovo/.ssh/i d_ecdsa_sk: No such file or directory debug1: Offering public key: C:\\Users\\Lenovo/.ssh/i d_ed25519 ED25519 SHA256:314 LS48LcdNWWV6CRzNlB0/oeBGMioEXuiYGuMtMAAM debug3: send packet: type 50 debug2: we sent a publickey packet, wait for reply debug3: receive packet: type 51 debug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with-mic,password debug1: Trying private key: C:\\Users\\Lenovo/.ssh/i d_ed25519_sk debug3: no such identity: C:\\Users\\Lenovo/.ssh/i d_ed25519_sk: No such file or directory debug1: Trying private key: C:\\Users\\Lenovo/.ssh/i d_xmss debug3: no such identity: C:\\Users\\Lenovo/.ssh/i d_xmss: No such file or directory debug1: Trying private key: C:\\Users\\Lenovo/.ssh/i d_dsa debug3: no such identity: C:\\Users\\Lenovo/.ssh/i d_dsa: No such file or directory debug2: we did not send a packet, disable method debug3: authmethod_lookup password debug3: remaining preferred: ,password debug3: authmethod_is_enabled password debug1: Next authentication method: password git@101.227 .48.102 's password:
1 2 3 4 5 6 7 C: \WINDOWS\system32>ssh -T git@101.227 .48.102 -i "C:\Users\Lenovo\.ssh\id_rsa" The authenticity of host ED25519 key fingerprint is SHA256:CPXsWA3qquwUoOVeMDDaHHbgsc1zmJWrM01Yoy6hMmI. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? yesWarning: Permanently added git@101.227 .48.102
known hosts 文件内容。
known_hosts 是 SSH 的 “信任名单”,存储了你确认过的、可信的远程服务器的公钥信息。
1 101.227.48.102 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICtguMSSuf4Fk0NbTJiq0oto20+x9NqDxLMDV19ahMOX
1 2 3 4 5 ssh-keyscan 101.227.48.102 ssh-keyscan -t ed25519 101.227.48.102
1 2 3 4 5 6 7 8 9 C :\WINDOWS\system32>ssh-keyscan 101.227.48.102 101 .227 .48 .102 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC8T2ttfbUFdbRAImGUYy1yRfV4o3u3uFZF2fDntvq9VvHOT1h4HINIAlXqvq+Pk0DwdOnXBn5AwTYfY0H0Tar8WjddvG1Hk5W4QCpqMWsyQ9FqwYtYgpQQEXOm9sxlLu13mAjI94+Tz1ozjmMjcc+JTPJ57In8nkLzLcfiOk9RApJ26jM2Vww7c3uAzhQCqRdjzBeozADgJT2kJfltcs+9 s9OjSNSl3ff8SWvRlbsnGX2WLDFtv5/NAVGXVfn/iiZPNKu6lUy/xwGycJYjq2zRplcmBwYXDt9x5ZUC/n/4 WjitT5cvpMf13LZzncV7PJ4PPXn0s2Uo5hcW4S/hWxxovOe2gW/iOTosaUmJGJaXJfA74PTBvAH4MwkFzV19DKjJQ5OMzixHhTE+B7z9JELKarDen2bMUR5kFrnZK+guK4B5zfeZ/YEkH9/PM6I719hKbmWp6ubc9bpKHs9dUQfzHHeuBmt2L3YxA/jVmjM6BJB9aL9wzIzALs7wgMp+hN8=101 .227 .48 .102 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBMk9rDm6ntFgVbjwbKKZHsOgZ7XoxVLSxu1/eGMXgJx30jPlN6DxVh7dCy13LRfxU/fKrnqCHoz3EvBP0Ii6/H0=101 .227 .48 .102 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICtguMSSuf4Fk0NbTJiq0oto20+x9NqDxLMDV19ahMOX
1 2 3 4 5 6 7 8 git config --global --unset core.sshCommand git config --global core.sshCommand "ssh -i C:/Users/Lenovo/.ssh/id_rsa" git config --global core.sshCommand
1 git clone http://101.227.48.102:10080/zhm/tomm-rmgt-server.git
1 2 3 4 5 6 7 8 9 10 11 12 13 **** **** **** **** **** **** *** APPLICATION FAILED TO START ** **** **** **** **** **** **** * Description: Failed to bind properties under 'spring.redis.password' to java.lang.String: Reason: java.lang.IllegalStateException: either 'jasypt.encryptor.password' or one of ['jasypt.encryptor.private-key-string', 'jasypt.encryptor.private-key-location'] must be provided for Password-based or Asymmetric encryption Action: Update your application's configuration
1 2 3 4 5 6 7 8 9 10 spring: application: name: ${ruoyi.name} messages: basename: i18n/messages profiles: active: dev
访问令牌。
1 glpat-zx59RyfXdquQ2xBRmchz
服务单元
2026 年 1 月 27 日
Linux怎么使用systemctl管理服务-linux运维-PHP中文网
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [Unit] Description=触摸屏 After=network.target [Service] Type=simple User=root WorkingDirectory=/home/memory/touchScreen/src/dist ExecStart=/home/memory/touchScreen/src/dist/__init__ Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=my-app [Install] WantedBy=multi-user.target
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 sudo system ctl daemon-reload sudo system ctl start touchscreen sudo system ctl status touchscreen sudo journalctl -u touchscreen -f sudo system ctl enable touchscreen sudo system ctl is-enabled touchscreen
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 Jan 27 02 :10 :43 localhost.localdomain setroubleshoot[3206 ]: AnalyzeThread.run (): Cancel pending alarm Jan 27 02 :10 :43 localhost.localdomain dbus-daemon[982 ]: [system] Activating service name ='org.fedoraproject.SetroubleshootPrivileged' requested by ':1.83 ' (uid=977 pid=3206 comm="/usr/libexec/platform-python -Es /usr/sbin/setroub" label="system_u:system_r:setroubleshootd_t:s0-s0:c0.c1023" ) (using servicehelper) Jan 27 02 :10 :43 localhost.localdomain dbus-daemon[982 ]: [system] Successfully activated service 'org.fedoraproject.SetroubleshootPrivileged' Jan 27 02 :10 :44 localhost.localdomain setroubleshoot[3206 ]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file touchscreen. For complete SELinux messages run : sealert -l a1107bcb-4757 -4 dc0-80 a0-c58e2657ca97 Jan 27 02 :10 :44 localhost.localdomain setroubleshoot[3206 ]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file touchscreen. ***** Plugin catchall (100. confidence) suggests ************************** If you believe that systemd should be allowed execute access on the touchscreen file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: Jan 27 02 :10 :44 localhost.localdomain setroubleshoot[3206 ]: AnalyzeThread.run (): Set alarm timeout to 10 Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: touchscreen.service: Service RestartSec=10 s expired, scheduling restart. Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: touchscreen.service: Scheduled restart job, restart counter is at 80. Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: Stopped 触摸屏. Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: Started 触摸屏. Jan 27 02 :10 :53 localhost.localdomain systemd[3782 ]: touchscreen.service: Failed to execute command: Permission denied Jan 27 02 :10 :53 localhost.localdomain systemd[3782 ]: touchscreen.service: Failed at step EXEC spawning /home/memory/touchScreen/src/dist/touchscreen: Permission denied Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: touchscreen.service: Main process exited, code=exited, status=203 /EXEC Jan 27 02 :10 :53 localhost.localdomain systemd[1 ]: touchscreen.service: Failed with result 'exit -code'. Jan 27 02 :10 :53 localhost.localdomain setroubleshoot[3206 ]: AnalyzeThread.run (): Cancel pending alarm Jan 27 02 :10 :53 localhost.localdomain setroubleshoot[3206 ]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file touchscreen. For complete SELinux messages run : sealert -l a1107bcb-4757 -4 dc0-80 a0-c58e2657ca97 Jan 27 02 :10 :53 localhost.localdomain setroubleshoot[3206 ]: SELinux is preventing /usr/lib/systemd/systemd from execute access on the file touchscreen. ***** Plugin catchall (100. confidence) suggests ************************** If you believe that systemd should be allowed execute access on the touchscreen file by default. Then you should report this as a bug. You can generate a local policy module to allow this access. Do allow this access for now by executing: Jan 27 02 :10 :53 localhost.localdomain setroubleshoot[3206 ]: AnalyzeThread.run (): Set alarm timeout to 10 Jan 27 02 :10 :53 localhost.localdomain sudo[3789 ]: root : TTY=pts/0 ; PWD=/etc/systemd/system ; USER=root ; COMMAND=/bin/journalctl -xe Jan 27 02 :10 :53 localhost.localdomain sudo[3789 ]: pam_systemd(sudo:session): Cannot create session: Already running in a session or user slice
1 SELinux is preventing /usr/lib/systemd/systemd from execute access on the file touchscreen.
可以看到,是 SELinux 阻止了应用程序。
1 2 3 4 5 6 7 8 9 10 11 12 [root@localhost system] [root@localhost system] Enforcing [root@localhost system] [root@localhost system] [root@localhost system] [root@localhost system] [root@localhost system] [root@localhost system] [root@localhost system] Permissive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@localhost system] [root@localhost system] [root@localhost system] [root@localhost system] ● touchscreen.service - 触摸屏 Loaded: loaded (/etc/systemd/system/touchscreen.service; disabled; vendor preset: disabled) Active: active (running) since Tue 2026-01-27 02:14:00 PST; 3s ago Main PID: 4026 (touchscreen) Tasks: 2 (limit : 11231) Memory: 27.7M CGroup: /system.slice/touchscreen.service ├─4026 /home/memory/touchScreen/src/dist/touchscreen └─4029 /home/memory/touchScreen/src/dist/touchscreen Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,905 - INFO - 更新控件 t19: 太原公司 Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,916 - INFO - 更新控件 t20: 太原路段 Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,927 - INFO - 更新控件 t21: 太原收费站 Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,927 - INFO - ----------智能联网监测终端启动成功---------- Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,927 - INFO - 初始化配置页1 Jan 27 02:14:00 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:00,927 - INFO - 初始化配置页1完毕 Jan 27 02:14:01 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:01,020 - INFO - ✅ 已连接到MySQL数据库: 14.103.238.145:10060/sx_rmgt Jan 27 02:14:01 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:01,049 - INFO - 🔌 MySQL连接已关闭 Jan 27 02:14:01 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:01,049 - INFO - 获取部门名称: ['长治北收费站' , '潞城收费站' , '黎城收费站' , '潞 > Jan 27 02:14:01 localhost.localdomain touchscreen[4026]: 2026-01-27 02:14:01,049 - INFO - 获取部门ID: [181, 182, 191, 192, 193, 194, 195, 195, 196, 197, >
成功运行,设置开机自启。
CentOS
2026 年 1 月 26 日
Download - The CentOS Project
Centos8 下载详细步骤(国内镜像源)_centos8镜像下载-CSDN博客
官网只提供 CentOS9,CentOS10下载。
阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区
吃饭。
1 sudo mv /etc/yum .repos.d/CentOS-Base.repo / etc/yum.repos.d/ CentOS-Base.repo.backup
1 sudo curl -o /etc/yum .repos.d/CentOS-Base.repo http:/ /mirrors.aliyun.com/ repo/Centos-8 .repo
是不是因为下载游戏网络不稳定啊。
阿里云镜像源,两个虚拟机都出现这问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root
清华大学 TUNA 源 (推荐)
1 2 3 4 5 6 7 8 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-7.repo sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-8.repo
解决 CentOS 7 报错: “Repository base is listed more than once in the configuration“问题-CSDN博客
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@localhost etc] [root@localhost yum.repos.d] total 64 drwxr-xr-x. 2 root root 187 Jan 23 00:05 backup -rw-r--r--. 1 root root 1694 Jan 26 00:03 CentOS-Base.repo -rw-r--r--. 1 root root 153 Jan 26 00:01 CentOS-Base.repo.backup -rw-r--r--. 1 root root 1309 May 21 2024 CentOS-CR.repo -rw-r--r--. 1 root root 649 May 21 2024 CentOS-Debuginfo.repo -rw-r--r--. 1 root root 314 May 21 2024 CentOS-fasttrack.repo -rw-r--r--. 1 root root 630 May 21 2024 CentOS-Media.repo -rw-r--r--. 1 root root 998 Dec 11 2018 CentOS-SCLo-scl.repo -rw-r--r--. 1 root root 971 Oct 29 2018 CentOS-SCLo-scl-rh.repo -rw-r--r--. 1 root root 1331 May 21 2024 CentOS-Sources.repo -rw-r--r--. 1 root root 9454 May 21 2024 CentOS-Vault.repo -rw-r--r--. 1 root root 616 May 21 2024 CentOS-x86_64-kernel.repo -rw-r--r--. 1 root root 1358 Sep 4 2021 epel.repo -rw-r--r--. 1 root root 1457 Sep 4 2021 epel-testing.repo -rw-r--r--. 1 root root 474 Apr 24 2018 nodesource-el7.repo
立即禁用有问题的仓库
1 2 3 sudo mv CentOS-SCLo-scl.repo CentOS-SCLo-scl.repo.disabled sudo mv CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl-rh.repo.disabled
清理缓存并测试
1 2 3 4 5 6 sudo yum clean all sudo rm -rf /var/cache/yum/* sudo yum makecache
EPEL(Extra Packages for Enterprise Linux)是由Fedora社区维护的一个高质量开源软件包仓库,专为基于Red Hat Enterprise Linux(RHEL)及其衍生发行版(如CentOS、Rocky Linux、AlmaLinux等)设计。
CentOS 8。
1 2 3 4 CentOS Linux 8 - AppStream 0.0 B/s | 0 B 00 :00 Errors during downloading metadata for repository 'appstream ': - Curl error (6 ): Couldn't resolve host name for http : Error: Failed to download metadata for repo 'appstream ': Cannot prepare internal mirrorlist: Curl error (6 ): Couldn't resolve host name for http :
这个错误的核心原因是:CentOS 8 官方源已经彻底停止服务了!
根本原因:
CentOS 8 已于 2021年12月31日停止维护
官方镜像站 mirrorlist.centos.org已移除 CentOS 8 的软件包
所有指向这个地址的仓库都会失败
立即操作:
1 2 3 4 cd /etc/yum.repos.d sudo mkdir -p backup sudo mv CentOS-Linux-*.repo backup/
改用国内镜像站(推荐清华源)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 sudo rm -f /etc/yum.repos.d/CentOS-* sudo tee /etc/yum.repos.d/CentOS-Vault.repo << 'EOF' [baseos] name=CentOS-8 - BaseOS (Tsinghua) baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111/BaseOS/$basearch /os/ gpgcheck=0 enabled=1 [appstream] name=CentOS-8 - AppStream (Tsinghua) baseurl=https://mirrors.tuna.tsinghua.edu.cn/centos-vault/8.5.2111/AppStream/$basearch /os/ gpgcheck=0 enabled=1 EOF'
强制清理缓存并重建
1 2 3 sudo dnf clean all sudo rm -rf /var/cache/dnf/* sudo dnf makecache
Python Release Python 3.6.8 | Python.org
下载这个包就行了:Windows x86-64 executable installer ,以下是本机 Python 环境变量路径,添加在了用户环境变量下。
1 2 3 C :\WINDOWS\system32>where pythonC :\Users\Lenovo\AppData\Local\Programs\Python\Python314\python.exeC :\Users\Lenovo\AppData\Local\Microsoft\WindowsApps\python.exe
pychram里面切换python版本方式_pycharm切换python版本-CSDN博客
VLC
2026 年 1 月 1 日
Open In VLC :: WebExtension.ORG
C++
2025 年 12 月 22 日
C++ Web 编程 | 菜鸟教程
perl_百度百科
1 Perl 语言是一种解释型、动态类型的编程语言,最初由Larry Wall于1987 年开发。Perl语言的主要目标是提供一种灵活、高效、易于使用的文本处理工具,因此Perl语言的语法和特性都与文本处理相关。Perl语言被广泛应用于Web开发、系统管理、网络编程、数据处理、科学计算和人工智能等领域。
什么是Perl_Perl简介_Perl的优势以及应用场景-腾讯云开发者社区
Perl 环境安装 | 菜鸟教程
中天中鼎
2025 年 12 月 22 日
河南交投集团“高速公路+产业”落子布局、全面启动—中天中鼎研发产品生产基地揭牌_河南省人民政府国有资产监督管理委员会
中天中鼎研发产品生产基地。
1 该自助发卡缴费设备由中天公司“中天中鼎”研发生产基地制造生产,自助发卡机采用客货上下双工位设计,具备自助发卡、按键求助、智能语音交互等功能,可同时容纳1000 张CPC卡,是常规发卡设备的两倍,发卡速度平均2 s,可有效提升发卡效率10 % 。自助缴费机采用投卡式双工位设计,具备扫码移动支付、电子发票、特情处理等功能,可有效提升车道通行缴费效率10 % 。此次是“中天中鼎”自助发卡缴费机器人在传统收费站的首例应用,有效提升收费站车道智能化水平及通行效率,实现“收费精准化”“降低运营成本”等效果。(中天公司)
中天公司研发的“中天中鼎”系列自助发卡缴费机器人实现传统收费站改造首例应用 - 河南交通投资集团
堡垒机
2025 年 12 月 22 日
IT知识百科:什么是堡垒机?-阿里云开发者社区
1 在实际应用中,三者常配合使用:VPN负责“安全接入内网”,防火墙负责“过滤非法流量”,堡垒机负责“管控接入后的资源访问”。
堡垒机是什么设备?一文读懂企业IT安全与运维的“核心守卫”
堡垒机是什么设备?一文读懂安全管理的核心中枢
显卡
2025 年 12 月 18 日
2025显卡十大品牌排行榜_显卡品牌前十名-中国品牌网
英伟达找了哪些下游的厂商造显卡?厂商名单全跟中国有关!
Nvidia 是造 GPU 芯片的,而国内这些厂商是造显卡的:华硕、技嘉、微星、七彩虹、影驰、索泰、映众、耕升、万丽……
AMD 是 CPU 还是显卡?一文分清:别再搞混它的 “双重身份”!
处理器
2025 年 12 月 18 日
2025CPU十大品牌排行榜_CPU品牌前十名-中国品牌网
ARM 和 x86 架构到底啥区别?手机电脑背后的 “隐形功臣”,一文讲透
ARM,X86,龙芯。
X86处理器技术_百度百科
英特尔® 处理器名称、编号和代次列表
英特尔CPU命名详解:32个后缀名、8个系列,如12700F等_英特尔cpu型号详解-CSDN博客
英特尔家族的CPU总共有8个“系列”,分别是至强(Xeon)、至强融核(Xeon Phi)、酷睿(Core)、奔腾(Pentium)、赛扬(Celeron)、凌动(Atom)、安腾(itanium)、Quark™ SoC。
Intel® Core™ i7-1195G7就属于酷睿系列的CPU。
总体来说,酷睿、赛扬、奔腾属于消费级CPU,主要分布在台式机和笔记本电脑领域。
Quark SoC属于可穿戴式设备。
凌动属于手机、平板和低成本电脑上的CPU。
至强、至强融核、安腾属于服务器领域的CPU,至强融核是英特尔集成众核架构产品。
1 Intel 的酷睿系列(i3/i5/i 7/i9)和 AMD 的锐龙系列(R3/ R5/R7/ R9),有什么本质上的区别?
选处理器纠结 AMD 还是 Intel?2025 避坑指南 + 场景适配,一看就懂!
英特尔和amd处理器哪个好?技术架构、性能表现与选购指南
AMD 是 CPU 还是显卡?一文分清:别再搞混它的 “双重身份”!
龙芯
2026 年 2 月 2 日
国产自主 CPU 芯片 ,由中科院计算所研发,现在由龙芯中科负责产业化。
龙芯开源社区
国产操作系统、麒麟操作系统——麒麟软件官方网站
飞腾、龙芯、鲲鹏国产 CPU。
银河麒麟,中标麒麟。
2025 年 12 月 18 日
LoongArch®
【知识— x86架构和arm架构有什么关系和区别】_x86有关系吗-CSDN博客
指令集架构:
1 2 x 86 : 复杂指令集计算机(CISC),指令集较为繁杂,包含大量的指令,执行每个指令的周期数不一定相等。 ARM: 精简指令集计算机(RISC),指令集相对简洁,执行每个指令的周期数相对较为一致。
ARM 和 x86 架构到底啥区别?手机电脑背后的 “隐形功臣”,一文讲透
英特尔®指令集扩展技术
1 中华人民共和国为取得技术独立,在龙芯处理器中排他性地使用 Linux。
Linux 简介 | 菜鸟教程
VMware 安装 Centos7 超详细过程 | 菜鸟教程
MobaXterm
2025 年 12 月 18 日
MobaXterm-MobaXterm远程终端管理软件-远程链接控工具-MobaXterm中文网站
进制
2025 年 12 月 11 日
字母 ‘H’ 的 ASCII 码是:
十进制 :72
二进制 :0100 1000
十六进制 :0x48
在十六进制中:
4 表示 4×16¹ = 4×16 = 64
8 表示 8×16⁰ = 8×1 = 8
64 + 8 = 72 ✅
ASCII 码表对应关系
1 2 3 4 5 6 字母 十进制 十六进制 二进制 -------------------------- 'H' 72 0x48 01001000'I' 73 0x49 01001001'J' 74 0x4A 01001010 ...
实际验证下。
1 2 3 4 print (hex (ord ('H' ))) print (int ('48' , 16 )) print (chr (0x48 ))
在你的原始数据中:
我们看到 \x48这样的表示形式
这实际上是 Python 中 bytes 字面量的表示方式
表示一个字节,其十六进制值为 0x48
Python
2025 年 12 月 12 日
Python调用java接口_python 使用json调取java接口-CSDN博客
python如何调用java接口 – PingCode
1 2 3 4 5 6 7 8 9 10 11 @RestController @RequestMapping("/api") public class TestController { @GetMapping("/test") public String test () { System.out.println("Hello World" ); return "Hello World" ; }
用 Java 实现服务端,写个简单的接口。
1 2 3 4 5 6 7 8 9 10 11 import requestsdef main (): response = requests.get('http://localhost:8080/api/test' ) print (response.status_code) print (response.text)if __name__ == '__main__' : main()
在 Python 中,可以使用requests库发送 HTTP 请求,调用 Java RESTful 服务,灵活性强,能够与任何支持HTTP协议的编程语言进行集成。
调用成功,这就基本实现了 Python 调用 Java 后台接口应用。
2025 年 12 月 3 日
Flask 教程 | 菜鸟教程
【超实用】3 分钟,教你用 Docker 部署一个 Python 应用!-腾讯云开发者社区-腾讯云
1 2 3 4 5 6 7 8 9 from flask import Flask app = Flask(__name__)@app.route('/' ) def index (): return "Hello World!" if __name__ == '__main__' : app.run(host="0.0.0.0" , port=5000 ,debug=True )
显而易见,就是一个非常基础的项目,当我们在浏览器输入网址以及对应的端口号的时候,会返回“Hello World!”内容。
执行以下命令安装可能缺失的依赖。
运行成功,访问成功。
1 2 3 4 5 6 7 C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\python.exe D:\Project\python\python通讯\python测试\test1203.py * Serving Flask app 'test1203' * Debug mode: on WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. * Running on all addresses (0.0.0.0) * Running on http://127.0.0.1:5000 * Running on http://192.168.1.105:5000
Python Flask 项目实战_python flask项目-CSDN博客
Flask 教程 | 菜鸟教程
1 2 3 4 5 6 7 8 9 10 FROM python:3.8 -slimWORKDIR /app COPY requirements.txt requirements.txt RUN pip install -r requirements.txt COPY . . CMD ["gunicorn" , "-b" , "0.0.0.0:8000" , "app:app" ]
1 2 COPY requirements.txt requirements.txt RUN pip install -r requirements.txt
触摸屏
2026 年 3 月 6 日
注:进度条控件和滑块控件关联使用时,进度条控件的ID一定要与滑块控件的ID相邻连续,且进度条的控件ID小于滑块控件ID,此时两者才能关联使用。如例程中:进度条控件ID为“1”,滑块控件ID为“2”。
2026 年 3 月 5 日
这么长时间了,这小屏还没有设计出页面来,光罗列了功能清单,得赶快设计下简单的排版,过两天得对一下。
2026 年 2 月 26 日
整理大彩串口屏,功能清单。
1 现在接手了一个任务,基于M系列、医用级、4 .6 寸、320 *960 、带组态RS232/TTL 、LUA脚本、视频、IPS贴合的大彩串口屏,开发一套软件。这个串口屏是镶嵌在一台机顶盒上的,这个盒子将来要放在高速公路收费站上,连接收费网操作车道硬件的,包括ETC专道的费额显示器,自动栏杆机,牌识摄像头,车辆检测器等等,还有自助车道的小黄人车辆检测器,人工车道的称重设备等等,这是这台云控盒的应用场景。现在我要问的是,这台云控盒上的串口屏,应该提供些哪些功能呢,主要是数据展示功能,不需要复杂的业务逻辑,需要你帮忙设计下这个屏幕要显示些哪些功能模块,要不要分几个主页面展示,还有整体画幅内怎么安排合理,这些都是你要考虑的,给我个初步方案吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 raph TD subgraph 首页 [960×320px 横屏] A [顶部状态栏:960 ×60 px] -->|左侧| 车道类型+时间<br>(如:ETC专道01 | 2026 -02 -26 14 :30 ) A -->|右侧| 网络状态+告警提示<br>(收费网√ | 0 条告警) B [中部核心区:960 ×180 px] --> B1[左模块:480 ×180 px] --> 车道状态:通行中<br>今日通行:89 辆(ETC占比92 %)<br>当前车辆:京A12345 | 计费15 .00 元 B --> B2[右模块:480 ×180 px] --> 核心设备状态(图标+状态):<br>费显✓ 栏杆机✓ 牌识✓ 车检器✓<br>(异常设备标红,如:栏杆机×) C [底部按钮区:960 ×80 px] --> C1[左按钮:320 ×80 px] --> 设备详情 C --> C2[中按钮:320 ×80 px] --> 通行数据 C --> C3[右按钮:320 ×80 px] --> 视频抓拍 end style 首页 fill:#f5f5f5,stroke:#333 ,stroke-width:1 px style A fill:#1 E3A8A,stroke:#fff,color:#fff style B1 fill:#fff,stroke:#e0e0e0,color:#333 style B2 fill:#fff,stroke:#e0e0e0,color:#333 style C1 fill:#0 EA5E9,stroke:#fff,color:#fff style C2 fill:#10 B981,stroke:#fff,color:#fff style C3 fill:#F59E0B,stroke:#fff,color:#fff
1 2 3 4 5 帮我生成图片:这个首页图确实有点想法,我提几点意见:1 、背景图的话将来实拍一张收费站全景图就行,这个思路不错。2 、画面尺寸一定要是横屏960X320 的,横竖比例是3 :1 ,这一点要注意了,所有的画面统一尺寸。3 、首页显示的画面,应该要包括收费站信息,车道信息,放在如图所示居中的窗口顶部就行,时间显示的话可以放在屏幕画面右上角,将来所有页面统一,风格的话你自己敲定。4 、居中窗口的内容暂时先保留当前的设计,下面三个子页面按钮可以保留,如果可以的话也能扩充成四个子页面,但具体显示内容还需要斟酌。
Linux 系统中添加或追加环境变量_linux添加环境变量-CSDN博客
2026 年 2 月 25 日
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 local progress = 0 local meter_value = 0 local meter_flag = 0 local Progress_screenid = 5 local Meter_screenid = 6 local Slider_screendid = 7 local Seltor_screenid = 12 local Languagescreen_id = 14 local Bootanimation_id = 26 local changbit = 0 function on_init () set_button_notify_release() start_timer(0 , 1000 , 0 , 0 ) start_timer(2 , 10 , 0 , 0 ) local language_id = get_language() if language_id == 0 then set_value(Languagescreen_id,1 ,1 ) set_value(Languagescreen_id,2 ,0 ) else set_value(Languagescreen_id,1 ,0 ) set_value(Languagescreen_id,2 ,1 ) end end
lua 脚本就是在这里集中写的。
2026 年 2 月 24 日
今早刚到办公室,发现这台机子连续开机已经十多天了,如果期间无人操作的话说明之前盒子停机的问题出在软件程序上,也就是前段时间排查出的系统资源分配问题。
先不管了,研究下串口屏开发再说。
2026 年 2 月 9 日
最近两天应该没什么事,上周新发来的云控盒早都装好软件放太原南去试运行了,除非最近再发来几个新盒子。
快过年了,还发个什么盒子,就是有事也不揽。
2026 年 2 月 6 日
串口屏基本不支持TCP,不能直接进行网络通信,如果要远程连接数据库那只能在主机用Python程序,屏内操作逻辑用lua脚本或c实现。
串口屏只用来发送信号的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 [Unit] Description=触摸屏 After=network.target serial-getty@ttyS0.service Wants=serial-getty@ttyS0.service [Service] Type=simple User=root WorkingDirectory=/home/memory/touchScreen/src/dist ExecStart=/home/memory/touchScreen/src/dist/touchscreen Restart=always RestartSec=10 StandardOutput=journal+console StandardError=journal+console SyslogIdentifier=touchscreen LogLevelMax=info [Install] WantedBy=multi-user.target
1 2 3 4 5 6 7 systemctl daemon-reload systemctl stop touchscreen.service systemctl start touchscreen.service systemctl status touchscreen.service
服务单元启动报错。
1 2 3 4 5 6 [root@localhost dist] ● touchscreen.service - 触摸屏 Loaded: loaded (/etc/systemd/system/touchscreen.service; enabled; vendor preset: disabled) Active: activating (auto-restart) (Result: exit-code) since Thu 2026-02-05 17:41:19 PST; 4s ago Process: 3522 ExecStart=/home/memory/touchScreen/src/dist/touchscreen (code=exited, status=203/EXEC) Main PID: 3522 (code=exited, status=203/EXEC)
1 2 su - root -c "/home/memory/touchScreen/src/dist/touchscreen"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 [root@localhost src] [Unit] Description=触摸屏 After=network.target [Service] Type=simple User=root Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" WorkingDirectory=/home/memory/touchScreen/src/dist ExecStart=/home/memory/touchScreen/src/dist/touchscreen Restart=always RestartSec=10 StandardOutput=journal+file:/home/memory/touchScreen/src/log/touchscreen.log StandardError=journal+file:/home/memory/touchScreen/src/log/touchscreen_error.log SyslogIdentifier=touchscreen LogLevelMax=info [Install] WantedBy=multi-user.target 这么配置有问题,现在启动后日志输出正常,但日志保存不起作用了
2026 年 2 月 4 日
最近几天的调试内容,都记录在Word文档里了,图片存储比较直观方便些。
从今天开始,研究大彩串口屏,这个屏幕比我想象的要高级许多。
2026 年 2 月 3 日
1 root@loongson-pc:/opt/ scaner
1 2 3 4 5 6 7 8 9 10 11 auto enp3s0 iface enp3s0 inet static address 192.168.2.12 netmask 255.255.255.0 gateway 192.168.2.1 dns-nameservers 223.5.5.5 8.8.8.8
2026 年 2 月 2 日
Redis 连接不上了,还没有完善从 Redis 拿 Token 再携带进每个请求中去的逻辑。
Smallpdf.com - A Free Solution to all your PDF Problems
免费在线编辑 PDF 文件的网站,订阅了7天免费试用,用完了就扔掉取消订阅不管了。
新发来的IP盒子串口屏厂家都不一样,尺寸也不一样,对应的上机位开发工具也不一样。
VisualTFT_开发软件_广州大彩专注组态串口屏,国内首创《虚拟串口屏》,大彩屏无需购买硬件!主营串口屏,串口显示屏,86面板,串口彩屏,触摸屏,HMI人机界面
D盘都爆满了,存储的图片视频过于庞大,这些资料应该寄存在U盘里,正好上个月从河南回来顺走了两块U盘,容量还不小。
代价就是两根顶好的网线了。
jiang让我买个大彩型号串口屏。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 01:35:01.103 [background-preinit] INFO o.h.v.i.util.Version - [<clinit>,21] - [] - HV000001: Hibernate Validator 6.1.6.Final 01:35:02.185 [main] ERROR c.a.c.n.NacosConfigManager - [createConfigService,60] - [] - java.lang.reflect.InvocationTargetException 01:35:02.187 [main] WARN o.s.c.a.AnnotationConfigApplicationContext - [refresh,559] - [] - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration' : Unsatisfied dependency expressed through field 'propertySourceLocators' ; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'nacosPropertySourceLocator' defined in class path resource [com/alibaba/cloud/nacos/NacosConfigBootstrapConfiguration.class]: Unsatisfied dependency expressed through method 'nacosPropertySourceLocator' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosConfigManager' defined in class path resource [com/alibaba/cloud/nacos/NacosConfigBootstrapConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.alibaba.cloud.nacos.NacosConfigManager]: Factory method 'nacosConfigManager' threw exception; nested exception is com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException: java.lang.reflect.InvocationTargetException 01:35:02.253 [main] ERROR o.s.b.d.LoggingFailureAnalysisReporter - [report,40] - [] - *************************** APPLICATION FAILED TO START *************************** Description: Application failed to connect to Nacos server: "nacos-svc:8848" Action: Please check your Nacos server config 01:35:02.263 [main] ERROR o.s.b.SpringApplication - [reportFailure,837] - [] - Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration' : Unsatisfied dependency expressed through field 'propertySourceLocators' ; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'nacosPropertySourceLocator' defined in class path resource [com/alibaba/cloud/nacos/NacosConfigBootstrapConfiguration.class]: Unsatisfied dependency expressed through method 'nacosPropertySourceLocator' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nacosConfigManager' defined in class path resource [com/alibaba/cloud/nacos/NacosConfigBootstrapConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.alibaba.cloud.nacos.NacosConfigManager]: Factory method 'nacosConfigManager' threw exception; nested exception is com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureException: java.lang.reflect.InvocationTargetException at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement .inject(AutowiredAnnotationBeanPostProcessor.java:643) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:130) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
1 2 3 root@loongson-pc:/opt/ scaner# grep -n "/opt/scaner/lib/" start.sh80 :cd /opt/ scaner/lib/ 108 :cd /opt/ scaner/lib/
2026 年 1 月 30 日
OpenAPI definition
1 2 3 4 5 6 7 8 9 10 public static void login (LoginUser loginUser) { SaHolder.getStorage().set(LOGIN_USER_KEY, loginUser); StpUtil.login(loginUser.getLoginId()); setLoginUser(loginUser); }
1 2 3 http:// 101.227 .48.102 :10003 admin yxjcgly202407!!AA
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Anonymous @PostMapping("/login") public R<Map<String, Object>> login (@Validated @RequestBody LoginBody loginBody) { Map<String, Object> ajax = new HashMap <>(); HttpServletRequest request = ServletUtils.getRequest(); UserAgent userAgent = UserAgentUtil.parse(request.getHeader("User-Agent" )); String s = RsaUtilClient.decryptByPrivateKey(loginBody.getPassword()); loginBody.setPassword(s);
1 java.lang .IllegalArgumentException : Last unit does not have enough valid bits
1 pip install pycryptodome
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 public static byte [] decryptByPrivateKey(byte [] data, String privateKey) throws Exception { byte [] keyBytes = decryptBASE64(privateKey); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec (keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privatizationKey = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, privatizationKey); return cipher.doFinal(data); }
这段代码的核心是用 RSA 私钥解密加密字节数组 ,流程为「BASE64 解私钥 → 构建 PKCS8 私钥对象 → 初始化解密器 → 执行解密」。
关键依赖:BASE64 解码工具、RSA 算法(KEY_ALGORITHM常量)、PKCS8 私钥格式。
核心类:PKCS8EncodedKeySpec(私钥包装)、KeyFactory(密钥转换)、Cipher(执行解密)。
1 2 3 private static final String privateKey = "MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKNPuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gAkM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWowcSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99EcvDQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthhYhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3UP8iWi1Qw0Y=" ;private static final String publicKey = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==" ;
后台的解密逻辑对应着前端 / 客户端必须执行的操作,缺一不可:
客户端获取后台提供的公钥(即你给出的publicKey字符串)。
客户端对明文密码执行「RSA 公钥加密」,得到加密后的字节数组。
客户端对该字节数组执行「BASE64 编码」,得到可传输的字符串data。
客户端将data通过接口传输给后台。
后台接收data后,先执行「BASE64 解码」(对应代码中的decryptBASE64),得到加密字节数组。
后台再执行「RSA 私钥解密」,得到明文密码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static byte [] encryptByPublicKey(String data, String key) throws Exception { byte [] keyBytes = decryptBASE64(key); X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec (keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key publicKey = keyFactory.generatePublic(x509KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(data.getBytes()); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 public static byte [] encryptByPrivateKey(byte [] data, String key) throws Exception { byte [] keyBytes = decryptBASE64(key); PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec (keyBytes); KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM); Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec); Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(data); }
1 2 String base64 = encryptBASE64(encryptByPublicKey("yxjcgly202407!!AA" , publicKey)); System.out.println(base64);
1 2 3 4 5 6 { "username" : "admin" , "password" : "f9PPJgmZzDTJpNS+xCLWt3BDTXxIuHiH4InCmf0i05WbFZ2I5tkRQqENSLTzCRuAOsxXuGCw+qUkzg+wzeWKZg==" , "code" : "" , "uuid" : "" }
1 2 3 4 5 6 7 { "code" : 500 , "msg" : "验证码已失效" , "data" : null , "error" : true , "success" : false }
2026 年 1 月 29 日
1 2 3 4 5 6 7 8 9 @DataPermission(value = { @DataRule( tableName = "asset_info", columnName = "dept_id", matchRule = "IN" ) }, logicJoin = "and") List<AssetInfo> selectByExample (AssetInfoExample example) ;
1 2 3 4 5 6 7 8 9 10 11 12 AssetInfoExample example = new AssetInfoExample() ; AssetInfoExample.Criteria criteria = example.createCriteria() ; criteria.and AssetIpEqualTo(s ) .and IsDeleteEqualTo(MgtMagicValue.ZERO_BYTE) ; List<AssetInfo> assetInfos = assetInfoService.selectByExample(example ) ; log.info("查询概览参数,获取本机资产数据结果:{}" , JsonUtils .to JsonString(assetInfos ) );if (CollUtil . isEmpty(assetInfos ) ) { throw new ServiceException("获取资产信息有误" ) ; }if (assetInfos.size() > RmgtMagicValue.ONE) { log.error("小屏概览,查询本服务器资源占用,获取路段服务器存在多条数据,请检查" ); }
概览页数据高度,数字显示。
pic-刷图指令 — 淘晶驰串口屏资料中心 1.1.0-2026-01-16 10:28:24 文档
move-控件移动 — 淘晶驰串口屏资料中心 1.1.0-2026-01-16 10:28:24 文档
1 2 3 4 5 6 7 8 9 10 cpu = data_dict['data' ]['cpu' ] ram = data_dict['data' ]['ram' ] disk = data_dict['data' ]['disk' ] cpu_usage = int (float (cpu)) memory_usage = int (float (ram)) disk_usage = int (float (disk)) logger.info(f"cpu_usage: {cpu_usage} , memory_usage: {memory_usage} , disk_usage: {disk_usage} " )
1 2 String s = sysConfigService.selectConfigByKey("server_ip" );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey") @Override public String selectConfigByKey (String configKey) { SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper <SysConfig>() .eq(SysConfig::getConfigKey, configKey)); if (ObjectUtil.isNotNull(retConfig)) { return retConfig.getConfigValue(); } return StringUtils.EMPTY; }
@Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey")(核心,缓存注解)
这是 Spring Cache 提供的缓存注解,作用是:
在方法执行前,先去指定缓存中查询数据,如果缓存中有,直接返回缓存结果,不执行方法体内部的代码;如果缓存中没有,才执行方法体代码,并且将方法返回结果存入缓存,供后续相同请求使用。
概览页固定查询主机 ip 为 14.103.238.145 的系统参数(CPU,内存,磁盘)。
2025 年 1 月 28 日
1 git clone http:// 101.227 .48.102 :10080 /zhm/ tomm-rmgt-server.git
1 2 3 4 5 6 7 8 9 10 11 12 13 **** **** **** **** **** **** *** APPLICATION FAILED TO START ** **** **** **** **** **** **** * Description: Failed to bind properties under 'spring.redis.password' to java.lang.String: Reason: java.lang.IllegalStateException: either 'jasypt.encryptor.password' or one of ['jasypt.encryptor.private-key-string', 'jasypt.encryptor.private-key-location'] must be provided for Password-based or Asymmetric encryption Action: Update your application's configuration
1 2 3 4 5 6 7 8 9 10 # Spring配置 spring: application: name: ${ ruoyi.name} # 资源信息 messages: # 国际化资源文件路径 basename: i18n/messages profiles: active: dev
访问令牌。
1 glpat-zx59RyfXdquQ2xBRmchz
2026 年 1 月 27 日
Nginx 烦人的 403 错误-腾讯云开发者社区-腾讯云
1 pip3 install pyinstaller
1 2 3 4 5 6 7 8 9 10 11 [root@localhost dist]# ./__init__ Traceback (most recent call last ): File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/pages/home_page.py" , line 6 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/utils/hmi_connect.py" , line 3 , in <module> ModuleNotFoundError: No module named 'serial' [3241 ] Failed to execute script '__init__' due to unhandled exception!
1 pip3 install dataclasses
1 2026 -01 -26 17 :36 :24 ,358 - ERROR - 连接串口屏失败: [Errno 2] could not open port COM7: [Errno 2] No such file or directory: 'COM7'
1 ls -la /dev/ ttyS* /dev/ ttyUSB* 2 >/dev/ null
1 init = InitControl(HMIConnect(port ='/ dev / ttyS0 ', baudrate =115200) )
1 2026 -01 -26 17 :59 :17 ,460 - ERROR - 连接串口屏失败: Could not configure port: (5 , 'Input/output error')
1 2 3 4 [root @localhost dist ] # ./__init__2026 -01 -26 18 :19 :37 ,529 - INFO - 成功连接到串口屏 /dev/tty52026 -01 -26 18 :19 :37 ,540 - INFO - 已跳转到页面 0 2026 -01 -26 18 :19 :37 ,543 - ERROR - ❌ 接口调用失败: HTTPConnectionPool(host ='localhost ', port =10057) : Max retries exceeded with url: /smallScreenDispla/homePageMonitorSummary (Caused by NewConnectionError('<urllib3 .connection .HTTPConnection object at 0x7f6930c08198>: Failed to establish a new connection : [Errno 111] Connection refused ',) )
虚拟机的串口和本机的串口的对应关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 [root@localhost ~] crw-rw-rw-. 1 root tty 5, 0 Jan 26 18:28 /dev/tty crw--w----. 1 root tty 4, 0 Jan 26 18:28 /dev/tty0 crw--w----. 1 root tty 4, 1 Jan 26 18:28 /dev/tty1 crw--w----. 1 root tty 4, 10 Jan 26 18:28 /dev/tty10 crw--w----. 1 root tty 4, 11 Jan 26 18:28 /dev/tty11 crw--w----. 1 root tty 4, 12 Jan 26 18:28 /dev/tty12 crw--w----. 1 root tty 4, 13 Jan 26 18:28 /dev/tty13 crw--w----. 1 root tty 4, 14 Jan 26 18:28 /dev/tty14 crw--w----. 1 root tty 4, 15 Jan 26 18:28 /dev/tty15 crw--w----. 1 root tty 4, 16 Jan 26 18:28 /dev/tty16 crw--w----. 1 root tty 4, 17 Jan 26 18:28 /dev/tty17 crw--w----. 1 root tty 4, 18 Jan 26 18:28 /dev/tty18 crw--w----. 1 root tty 4, 19 Jan 26 18:28 /dev/tty19 crw--w----. 1 root tty 4, 2 Jan 26 18:28 /dev/tty2 crw--w----. 1 root tty 4, 20 Jan 26 18:28 /dev/tty20 crw--w----. 1 root tty 4, 21 Jan 26 18:28 /dev/tty21 crw--w----. 1 root tty 4, 22 Jan 26 18:28 /dev/tty22 crw--w----. 1 root tty 4, 23 Jan 26 18:28 /dev/tty23 crw--w----. 1 root tty 4, 24 Jan 26 18:28 /dev/tty24 crw--w----. 1 root tty 4, 25 Jan 26 18:28 /dev/tty25 crw--w----. 1 root tty 4, 26 Jan 26 18:28 /dev/tty26 crw--w----. 1 root tty 4, 27 Jan 26 18:28 /dev/tty27 crw--w----. 1 root tty 4, 28 Jan 26 18:28 /dev/tty28 crw--w----. 1 root tty 4, 29 Jan 26 18:28 /dev/tty29 crw--w----. 1 root tty 4, 3 Jan 26 18:28 /dev/tty3 crw--w----. 1 root tty 4, 30 Jan 26 18:28 /dev/tty30 crw--w----. 1 root tty 4, 31 Jan 26 18:28 /dev/tty31 crw--w----. 1 root tty 4, 32 Jan 26 18:28 /dev/tty32 crw--w----. 1 root tty 4, 33 Jan 26 18:28 /dev/tty33 crw--w----. 1 root tty 4, 34 Jan 26 18:28 /dev/tty34 crw--w----. 1 root tty 4, 35 Jan 26 18:28 /dev/tty35 crw--w----. 1 root tty 4, 36 Jan 26 18:28 /dev/tty36 crw--w----. 1 root tty 4, 37 Jan 26 18:28 /dev/tty37 crw--w----. 1 root tty 4, 38 Jan 26 18:28 /dev/tty38 crw--w----. 1 root tty 4, 39 Jan 26 18:28 /dev/tty39 crw--w----. 1 root tty 4, 4 Jan 26 18:28 /dev/tty4 crw--w----. 1 root tty 4, 40 Jan 26 18:28 /dev/tty40 crw--w----. 1 root tty 4, 41 Jan 26 18:28 /dev/tty41 crw--w----. 1 root tty 4, 42 Jan 26 18:28 /dev/tty42 crw--w----. 1 root tty 4, 43 Jan 26 18:28 /dev/tty43 crw--w----. 1 root tty 4, 44 Jan 26 18:28 /dev/tty44 crw--w----. 1 root tty 4, 45 Jan 26 18:28 /dev/tty45 crw--w----. 1 root tty 4, 46 Jan 26 18:28 /dev/tty46 crw--w----. 1 root tty 4, 47 Jan 26 18:28 /dev/tty47 crw--w----. 1 root tty 4, 48 Jan 26 18:28 /dev/tty48 crw--w----. 1 root tty 4, 49 Jan 26 18:28 /dev/tty49 crw--w----. 1 root tty 4, 5 Jan 26 18:28 /dev/tty5 crw--w----. 1 root tty 4, 50 Jan 26 18:28 /dev/tty50 crw--w----. 1 root tty 4, 51 Jan 26 18:28 /dev/tty51 crw--w----. 1 root tty 4, 52 Jan 26 18:28 /dev/tty52 crw--w----. 1 root tty 4, 53 Jan 26 18:28 /dev/tty53 crw--w----. 1 root tty 4, 54 Jan 26 18:28 /dev/tty54 crw--w----. 1 root tty 4, 55 Jan 26 18:28 /dev/tty55 crw--w----. 1 root tty 4, 56 Jan 26 18:28 /dev/tty56 crw--w----. 1 root tty 4, 57 Jan 26 18:28 /dev/tty57 crw--w----. 1 root tty 4, 58 Jan 26 18:28 /dev/tty58 crw--w----. 1 root tty 4, 59 Jan 26 18:28 /dev/tty59 crw--w----. 1 root tty 4, 6 Jan 26 18:28 /dev/tty6 crw--w----. 1 root tty 4, 60 Jan 26 18:28 /dev/tty60 crw--w----. 1 root tty 4, 61 Jan 26 18:28 /dev/tty61 crw--w----. 1 root tty 4, 62 Jan 26 18:28 /dev/tty62 crw--w----. 1 root tty 4, 63 Jan 26 18:28 /dev/tty63 crw--w----. 1 root tty 4, 7 Jan 26 18:28 /dev/tty7 crw--w----. 1 root tty 4, 8 Jan 26 18:28 /dev/tty8 crw--w----. 1 root tty 4, 9 Jan 26 18:28 /dev/tty9 crw-rw----. 1 root dialout 4, 64 Jan 26 18:28 /dev/ttyS0 crw-rw----. 1 root dialout 4, 65 Jan 26 18:28 /dev/ttyS1 crw-rw----. 1 root dialout 4, 66 Jan 26 18:28 /dev/ttyS2 crw-rw----. 1 root dialout 4, 67 Jan 26 18:28 /dev/ttyS3
虚拟控制台终端 (tty0-tty63)不可用于串口通信,是系统控制台。
物理串口 (ttyS0-ttyS3)这才是真正的串口设备 ,用于串口通信。
当前控制台 (tty)。
1 2 3 4 5 6 if __name__ == '__main__' : # 使用示例 # init = InitControl(HMIConnect(port ='COM7' , baudrate =115200)) # init = InitControl(HMIConnect(port ='COM5' , baudrate =115200)) init = InitControl(HMIConnect(port ='/dev/ttyS0' , baudrate =115200)) init.main()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@localhost dist]# ./__init__ 2026-01-26 18:42:27,369 - INFO - 成功连接到串口屏 /dev/ttyS0 2026-01-26 18:42:27,381 - INFO - 已跳转到页面 0 2026-01-26 18:42:27,384 - ERROR - ❌ 接口调用失败: HTTPConnectionPool(host ='localhost' , port =10057): Max retries exceeded with url: /smallScreenDispla/homePageMonitorSummary (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f2a619b60f0>: Failed to establish a new connection: [Errno 111] Connection refused' ,)) 2026-01-26 18:42:27,384 - WARNING - ⚠️ 接口调用失败,使用模拟数据 2026-01-26 18:42:27,384 - INFO - 获取系统数据成功 2026-01-26 18:42:27,395 - INFO - 更新控件 t13: 正常 2026-01-26 18:42:27,406 - INFO - 更新控件 t14: 4个 2026-01-26 18:42:27,418 - INFO - 更新控件 g1: 18:42 2026-01-26 18:42:27,429 - INFO - 更新控件 t16: 8个 2026-01-26 18:42:27,440 - INFO - 更新控件 t17: 0个 2026-01-26 18:42:27,451 - INFO - 更新控件 g0: 18:42 2026-01-26 18:42:27,462 - INFO - 更新控件 t19: 太原公司 2026-01-26 18:42:27,473 - INFO - 更新控件 t20: 太原路段 2026-01-26 18:42:27,485 - INFO - 更新控件 t21: 太原收费站 2026-01-26 18:42:27,485 - INFO - ----------智能联网监测终端启动成功----------
总算在 Linux 环境下部署成功了。
研究下怎么把这个服务设置成开机自启,注册成为系统服务的其中一个。
Linux系统服务神器:systemctl的简单配置与使用-腾讯云开发者社区-腾讯云
2026 年 1 月 26 日
安装 Pyinstaller 打包项目。
1 pyinstaller --onefile main .py
这行代码报错了,日志打印不规范,见鬼的是为什么现在才报错。
1 2 3 4 5 6 def validate (self, hex_data ) -> tuple : """校验输入""" commands = [] try : logger.info("hex_data:" , hex_data)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 --- Logging error --- Traceback (most recent call last): File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\logging\__init__.py" , line 1151, in emit msg = self.format(record) File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\logging\__init__.py" , line 999, in format return fmt.format(record) ~~~~~~~~~~^^^^^^^^ File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\logging\__init__.py" , line 712, in format record.message = record.getMessage() ~~~~~~~~~~~~~~~~~^^ File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\logging\__init__.py" , line 400, in getMessage msg = msg % self.args ~~~~^~~~~~~~~~~ TypeError: not all arguments converted during string formatting Call stack: File "D:\Project\luofeng\touchScreen\src\__init__.py" , line 51, in <module> init.main() File "D:\Project\luofeng\touchScreen\src\__init__.py" , line 33, in main touch_event.display_touch_listener() File "D:\Project\luofeng\touchScreen\src\utils\touch_event.py" , line 51, in display_touch_listener self.handle_validate_event() File "D:\Project\luofeng\touchScreen\src\utils\touch_event.py" , line 209, in handle_validate_event result, commands, dept_id = self.config_page1_updater.validate(self.hex_data) File "D:\Project\luofeng\touchScreen\src\pages\config_page_1.py" , line 79, in validate logger.info("hex_data:" , hex_data) Message: 'hex_data:' Arguments: ('C0 E8 B3 C7 CA D5 B7 D1 D5 BE' ,) 2026-01-26 09:36:43,972 - INFO - 🔍 校验输入: 收费站=黎城收费站 2026-01-26 09:36:43,973 - INFO - 获取到dept_id: 191 2026-01-26 09:36:43,973 - INFO - ✅ 输入校验通过 2026-01-26 09:36:43,973 - INFO - 校验结束, 标记结果状态:True; 校验结果信息: ['t4.txt="校验通过\r\n点击下一步"' , 't4.pco=1696' ]; 收费站dept_id: 191 2026-01-26 09:36:43,973 - INFO - ==================================================
重新安装yum。
安装 python3 。
1 sudo yum install python3 python3 -devel python3 -pip
1 2 3 4 5 6 7 8 9 10 11 [root@localhost admin] WARNING: Running pip install with root privileges is generally not a good idea. Try `pip3 install --user` instead. Collecting pyinstaller Downloading https:// files.pythonhosted.org/packages/ b0/e6/ e5760666896739115b0e4538a42cdd895215581618ec885ad043dd35ee57/pyinstaller-4.10 .tar.gz (2.7 MB) 100 % |████████████████████████████████| 2.7 MB 557 kB/s Complete output from command python setup.py egg_info: Error: Building wheels requires the 'wheel' package. Please `pip install wheel` then try again. ---------------------------------------- Command "python setup.py egg_info" failed with error code 1 in /tmp/ pip-build-6 j4h6vx1/pyinstaller/
这个报错是因为没有安装编译依赖。
1 2 3 4 5 6 7 8 9 10 11 sudo yum install -y gcc gcc-c++ make sudo yum install -y python3-devel python3-setuptools python3-wheel sudo yum install -y openssl-devel bzip2-devel libffi-devel sqlite-devel python3 -m pip install --upgrade pip setuptools wheel
添加 PATH 到环境变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 echo $PATH find /root/.local -name "pyinstaller" -type fexport PATH="/root/.local/bin:$PATH " which pyinstaller pyinstaller --version
1 2 3 4 5 6 7 8 9 pyinstaller --onefile \ --name "myapp" \ --hidden-import requests \ --hidden-import chardet \ --hidden-import idna \ --hidden-import urllib3 \ --hidden-import certifi \ --add-data "src:src" \ src/__init__.py
还是报错。
1 2 3 4 5 6 7 8 9 [root@localhost dist]# ./myapp Traceback (most recent call last ): File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/pages/home_page.py" , line 3 , in <module> ModuleNotFoundError: No module named 'requests' [108286 ] Failed to execute script '__init__' due to unhandled exception!
排查问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 [root@localhost dist]# python3 -c > import pkg_resources > pkgs = ['requests' , 'urllib3' , 'chardet' , 'idna' , 'certifi' , 'charset-normalizer' ] > for pkg in pkgs: > try : > dist = pkg_resources.get_distribution(pkg) > print (f '✓ {pkg}: {dist.version}' ) > except: > print (f '✗ {pkg}: 未安装' ) > ✓ requests: 2.27 .1 ✓ urllib3: 1.26 .20 ✗ chardet: 未安装 ✓ idna: 3.10 ✓ certifi: 2025.4 .26 ✓ charset-normalizer: 2.0 .12 [root@localhost dist]# ./myapp Traceback (most recent call last ): File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/__init__.py" , line 4 , in <module> File "PyInstaller/loader/pyimod03_importers.py" , line 495 , in exec_module File "src/pages/home_page.py" , line 3 , in <module> ModuleNotFoundError: No module named 'requests' [108410 ] Failed to execute script '__init__' due to unhandled exception!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 安装 chardet pip install chardet # 验证所有依赖python3 -c import pkg_resources pkgs = ['requests' , 'urllib3' , 'chardet' , 'idna' , 'certifi' , 'charset-normalizer' ]for pkg in pkgs: try : dist = pkg_resources.get_distribution(pkg) print (f '✓ {pkg}: {dist.version}' ) except: print (f '✗ {pkg}: 未安装' )
Python 3.14最新版本安装和环境配置-腾讯云开发者社区-腾讯云
官方镜像停止维护。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 [root localhost dist]#
这段代码很关键。
1 2 3 4 5 6 7 8 9 try : # 检查串口是否有数据 if _serial and _serial.in_waiting > 0 : # 获取原始指令信息 data = _serial.read(_serial .in_waiting ) time.sleep(0.01 ) # 10ms延迟 # 再读取剩余数据 data += _serial.read(_serial .in_waiting ) self.data = data
加上可能再次读取收费站信息,删掉就读不到完整的收费站信息,两头堵。
阿里云镜像源,两个虚拟机都出现这问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 [root
清华大学 TUNA 源 (推荐)
1 2 3 4 5 6 7 8 sudo mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-7.repo sudo curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.tuna.tsinghua.edu.cn/repo/Centos-8.repo
解决 CentOS 7 报错: “Repository base is listed more than once in the configuration“问题-CSDN博客
立即禁用有问题的仓库
1 2 3 sudo mv CentOS-SCLo-scl.repo CentOS-SCLo-scl.repo.disabled sudo mv CentOS-SCLo-scl-rh.repo CentOS-SCLo-scl-rh.repo.disabled
清理缓存并测试
1 2 3 4 5 6 sudo yum clean all sudo rm -rf /var/cache/yum/* sudo yum makecache
2026 年 1 月 23 日
收费站智能终端。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <select id ="selectByExample" parameterType ="com.tomm.system.domain.ItemsExample" resultMap ="BaseResultMap" > select <if test ="distinct" > distinct </if > <include refid ="Base_Column_List" /> from zabbix.items <if test ="_parameter != null" > <include refid ="Example_Where_Clause" /> </if > <if test ="orderByClause != null" > order by ${orderByClause} </if > <if test ="limit != null" > <if test ="offset != null" > limit ${offset}, ${limit} </if > <if test ="offset == null" > limit ${limit} </if > </if > </select >
获取部门名称和部门ID。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 def load_station_name_dept_id (self ): """获取部门名称和部门ID""" manager = MySQLManager(MySQLConfig()) if manager.connect(): try : station_name_dept_id = manager.execute_query( f"SELECT DISTINCT station_name, dept_id FROM `t_section_host_dept_map`" ) for row in station_name_dept_id: station_name = row.get('station_name' ) dept_id = row.get('dept_id' ) if station_name and dept_id: self.result_dict[station_name] = dept_id finally : manager.close() logger.info(f"获取部门名称和部门ID成功: {self.result_dict} " ) logger.info(f"获取部门名称: {self.result_dict.keys()} " ) logger.info(f"获取部门ID: {self.result_dict.values()} " )
1 2 3 2026-01-23 09:47:06,174 - INFO - 获取部门名称和部门ID成功: {'长治北收费站' : 181, '潞城收费站' : 182, '黎城收费站' : 191, '潞城东收费站' : 192, '壶关收费站' : 193, '西池收费站' : 194, '长治东收费站' : 195, '平顺收费站' : 195, '虹霓峡收费站' : 196, '长子北收费站' : 197, '丰宜收费站' : 198, '西井收费站' : 198} 2026-01-23 09:47:06,174 - INFO - 获取部门名称: dict_keys(['长治北收费站' , '潞城收费站' , '黎城收费站' , '潞城东收费站' , '壶关收费站' , '西池收费站' , '长治东收费站' , '平顺收费站' , '虹霓峡收费站' , '长子北收费站' , '丰宜收费站' , '西井收费站' ])
这个列表在两个地方用到了。
1 2 logger.info(f"获取部门名称: {list (self.result_dict.keys())} " ) logger.info(f"获取部门ID: {list (self.result_dict.values())} " )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def select_dept (self ): """选择部门""" """每次调用选择下一个收费站,循环选择""" station_list = self.result_dict.keys() if len (station_list) <= 1 : return current_station = list (station_list)[self.current_index] self.current_station = current_station self.hmi_connect.send_command(f'b2.txt="{current_station} "' ) self.current_index += 1 print (f"当前选择收费站: {current_station} " ) if self.current_index >= len (station_list): self.current_index = 1 return current_station
1 2 3 dept_id = self.result_dict.get(station) logger.info(f"获取到dept_id: {dept_id} " )
监测页也一样。
妈的,监测页没有这个需求,不用改了。
【超实用】3 分钟,教你用 Docker 部署一个 Python 应用!-腾讯云开发者社区-腾讯云
最佳静态网站托管:3 个免费 + 2 个低成本选项 - HostScore
Vercel Pricing: Hobby, Pro, and Enterprise plans
2026 年 1 月 22 日
监测页同步更新。
控件添加,减少第8条记录,翻页功能,清除记录,全局索引,删除查找数据冗余代码。
1 2026 -01 -22 16 :30 :19 ,306 - ERROR - ❌ 更新概览页面失败: unsupported operand type(s) for /: 'str' and 'int'
1 2 3 4 5 6 7 8 9 10 @staticmethod def update_progress_bars (data ): """更新进度条控件以及对应文本控件""" commands = [f"j1.val='{data['cpu_usage' ]} '" , f"j2.val='{data['memory_usage' ]} '" , f"j3.val='{data['disk_usage' ]} '" ] return commands
2026 年 1 月 21 日
1 2 3 4 5 6 7 List<LatestItemsHistoryVo> selectAllHistoryInfo (@Param("itemIds") List<Long> itemIds, @Param("type") Integer type) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 <select id ="selectAllHistoryInfo" parameterType ="map" resultType ="com.tomm.system.domain.vo.LatestItemsHistoryVo" > SELECT hu.itemid itemId, ROUND(hu.`value`, 2) AS value, hu.clock FROM <if test ="type=='0'.toString()" > zabbix.history hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if > <if test ="type=='1'.toString()" > zabbix.history_str hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history_str h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if > <if test ="type=='2'.toString()" > zabbix.history_log hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history_log h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if > <if test ="type=='3'.toString()" > zabbix.history_uint hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history_uint h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if > <if test ="type=='4'.toString()" > zabbix.history_text hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history_text h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if > GROUP BY hu.itemid</select > <select id ="getDeviceIndexTop" resultType ="com.tomm.system.domain.vo.DeviceIndexTopVo" > SELECT ai.asset_name AS assetName, i.itemid AS itemId, i.name AS itemName, ROUND(COALESCE(hu.`value`, 0.00), 2) AS value FROM asset_info ai LEFT JOIN zabbix.items i ON i.hostid = ai.host_id AND i.name = #{itemName} LEFT JOIN ( SELECT itemid, MAX(clock) AS clock FROM zabbix.history GROUP BY itemid ) h ON h.itemid = i.itemid LEFT JOIN zabbix.history hu ON hu.itemid = h.itemid AND hu.clock = h.clock WHERE ai.host_id IN <foreach collection ="hostIds" item ="hostId" open ="(" separator ="," close =")" > #{hostId} </foreach > ORDER BY ROUND(COALESCE(hu.`value`, 0.00), 2) DESC LIMIT 5;</select >
查询目的
这个查询的目标是:获取多个监控项(item)的最新一条历史记录
具体来说:
对每个 itemid,找到其最近的时间戳(MAX(clock))
然后根据 itemid和时间戳关联回原表,获取该条记录的详细信息
返回每个监控项的最新数值和时间
自连接分析
为什么需要自连接?
子查询(a) :
1 2 3 4 SELECT h.itemid, MAX (h.clock) AS clockFROM zabbix.history hWHERE h.itemid IN (...)GROUP BY h.itemid
作用:找出每个监控项的最大时间戳(最新记录的时间)
主查询 :
1 2 3 SELECT hu.itemid, ROUND(hu.`value `, 2 ), hu.clockFROM zabbix.history huJOIN a ON hu.itemid = a.itemid AND hu.clock = a.clock
作用:用上面找到的 (itemid, 最大clock)关联回原表,获取具体的值
这实际上是两步操作 :
先找”每个监控项的最新时间”
再用”监控项+时间”去匹配具体的数据
type 参数的意义
从代码看,Zabbix 有多个历史表:
history(type=’0’):浮点数数据
history_str(type=’1’):字符串数据
history_log(type=’2’):日志数据
history_uint(type=’3’):无符号整数
history_text(type=’4’):文本数据
type参数决定了查询哪个历史表 ,因为 Zabbix 根据数据类型将历史数据存储在不同的表中。
定义了查询列。
1 2 3 4 <sql id="Base_Column_List" > id ,road_name,station_name,host_ip,host_type ,dept_id,sectionid,stationid,laneid,gantryid,show_item_id, device_type ,create_time,create_by,update_time,update_by,host_id </sql>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <select id ="selectSectionHostDeptMapByHostTypeAndDeptId" parameterType ="java.lang.Byte" resultType ="com.tomm.system.domain.SectionHostDeptMap" > SELECT <include refid ="Base_Column_List" /> FROM t_section_host_dept_map <where > <if test ="deptIds != null and deptIds.size() > 0" > AND dept_id IN <foreach item ="item" collection ="deptIds" open ="(" separator ="," close =")" > # {item} </foreach > </if > <if test ="hostTypes != null and hostTypes.size() > 0" > AND host_type IN <foreach item ="item" collection ="hostTypes" open ="(" separator ="," close =")" > # {item} </foreach > </if > </where > </select >
1 2 3 4 5 6 7 /** * 根据条件查询指标集合 * * @param itemDto 查询条件 * @return 指标集合 */ List<Items> selectItemByExample(ItemDto itemDto );
四舍五入,保留小数位数。
1 2 3 4 5 SELECT hu.itemid itemId, ROUND (hu.`value` , 2 ) AS value , hu.clock FROM
根据指标id(itemId)和指标类型(type),查表 zabbix.history。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 SELECT hu.itemid itemId, ROUND(hu.`value`, 2) AS value, hu.clock FROM <if test ="type=='0'.toString()" > zabbix.history hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history h WHERE h.itemid in <foreach collection ="itemIds" item ="itemid" open ="(" separator ="," close =")" > #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if >
这张表里没有 51025,51039,51036 指标id,也就是没有 CPU使用率,内存使用率和磁盘使用率这三个指标,自然查不到指标值。
只有 48366,指标值还是 100,不晓得这是个什么指标。
我可以在测试数据库添加几条。
不对,库里有几十万条数据,没显示全。
1 select count (*) from history where itemid between 51008 and 51118 ;
查过了,这个范围内没有指标值,自己添加指标值吧。
下午两个任务:概览页面结束。
翻页,保留当前监测主机类型
1 2 3 4 5 6 7 8 9 10 11 12 13 def get_config_data (self ) -> Dict [str , Any ]: """统一数据获取入口""" api_data = self.fetch_data_from_api(self.monitor_host_type.get("station" )) if api_data is not None : result = self.handle_api_data(api_data) self.monitor_type = self.monitor_host_type.get("station" ) return result logger.warning("⚠️ 接口调用失败,尝试从数据库获取数据" ) return self.generate_mock_data()
1 2 3 4 5 6 7 8 self.monitor_type = 2 self.monitor_host_type = { "station" : 2 , "lane" : 3 , "gantry" : 4 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 total_records = len (records) total_pages = (total_records + self.page_size - 1 ) // self.page_size print ("总页数:" , total_pages) self.total_pages = total_pagesif self.current_page > self.total_pages > 0 : self.current_page = 1 logger.info(f"当前页码:{self.current_page} /{self.total_pages} ,总记录数:{total_records} " ) start_idx = (self.current_page - 1 ) * self.page_size end_idx = min (start_idx + self.page_size, total_records) page_records = records[start_idx:end_idx] logger.info(f"当前页记录:{page_records} , 一共{len (page_records)} 条记录" )if self.total_pages > 0 : self.current_page += 1 if self.current_page > self.total_pages: self.current_page = 1
清空控件内容。
1 2 3 4 5 6 7 8 9 10 11 12 for i in range (self.page_size): commands.append(f'{id_controls[i]} .txt=""' ) commands.append(f'{type_controls[i]} .txt=""' ) commands.append(f'{ip_controls[i]} .txt=""' ) commands.append(f'{status_controls[i]} .txt=""' ) commands.append(f'{status_controls[i]} .pco=65535' )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 for i, record in enumerate (page_records[:self.page_size], 0 ): status = '在线' if record['is_online' ] else '离线' update_type_name = "站服务器" if record["type_name" ] == "收费站服务器" else record["type_name" ] commands.append(f'{id_controls[i]} .txt="{i + 1 } "' ) commands.append(f'{type_controls[i]} .txt="{update_type_name} "' ) commands.append(f'{ip_controls[i]} .txt="{record["ip" ]} "' ) commands.append(f'{status_controls[i]} .txt="{status} "' ) status_color = color_map.get(status, 65535 ) commands.append(f'{status_controls[i]} .pco={status_color} ' )
自增提前。
1 2 3 4 5 if self.total_pages > 0 : self.current_page += 1 if self.current_page > self.total_pages: self.current_page = 1
1 2 global_index = (self.current_page - 1 ) * self.page_size + i + 1
饿了,六点多,早点回家去。
这盒子感觉运行几小时就发送信号有问题了,得重启解决,再过几辆车试下看。
2026 年 1 月 20 日
虚拟串口用不了了。
1 2 2026 -01 -20 12 :08 :08 ,041 - INFO - 已跳转到页面 2 2026 -01 -20 12 :08 :09 ,518 - INFO - 收到指令: b'\xb3\xa4\xd6\xce\xb1\xb1\xca\xd5\xb7\xd1\xd5'
接受指令还是不完整。
概览页面接口待完善。
1 2 3 4 5 6 7 def handle_jump_event (self, touch_info ): """处理跳转事件""" page_id = touch_info['page' ] control_id = touch_info['control' ] current_time = time.time() config_page1_updater = ConfigPage1Updater(self.hmi_connect)
1 2 3 4 5 6 7 8 9 10 class TouchEvent : def __init__ (self, hmi_connect ): self.hmi_connect = hmi_connect self._serial = hmi_connect.ser self.data = "" self.last_touch_time = 0 self.hex_data = "" self.if_validate = False self.dept_id = 0 self.config_page1_updater = ConfigPage1Updater(hmi_connect)
增加读取延迟,确保数据完整。
1 2 3 4 5 6 data = _serial.read(_serial.in_waiting) time.sleep(0.01 ) if _serial.in_waiting > 0 : data += _serial.read(_serial.in_waiting)
1 2 3 4 5 current_station = self.stations[self.current_index] self.current_station = current_station self.hmi_connect.send_command(f'b2.txt="{current_station} "' )
加载上一次选择。
1 2 3 4 def load_last_station (self ): """加载上一次选择(收费站)""" self.hmi_connect.send_command(f'b2.txt="{self.current_station} "' )
1 2 self .load_last_station()
监测资产,翻页。
保留当前查询主机类型(2,3,4),分页获取下一页7条数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @staticmethod def _update_config_rows (data: Dict [str , Any ] ) -> List [str ]: """更新配置数据行控件(原有逻辑不变)""" records = data["records" ] commands = [] id_controls = ['t8' , 't9' , 't10' , 't11' , 't12' , 't13' , 't5' ] type_controls = ['t14' , 't15' , 't16' , 't17' , 't18' , 't19' , 't6' ] ip_controls = ['t20' , 't21' , 't22' , 't23' , 't24' , 't25' , 't7' ] status_controls = ['t26' , 't27' , 't28' , 't29' , 't30' , 't31' , 't32' ] color_map = { "在线" : 1696 , "异常" : 63488 , "离线" : 33840 , "警告" : 65504 , } print (f"\n=== 前7条记录示例 ===" ) for i, record in enumerate (records[:7 ], 0 ): print (f"{i} | " f"主机类型: {record['type_name' ]} | " f"IP: {record['ip' ]} | " f"状态: {'在线' if record['is_online' ] else '离线' } | " f"更新时间: {record['update_time_str' ]} " ) status = '在线' if record['is_online' ] else '离线' update_type_name = "站服务器" if record["type_name" ] == "收费站服务器" else record["type_name" ] commands.append(f'{id_controls[i]} .txt="{i + 1 } "' ) commands.append(f'{type_controls[i]} .txt="{update_type_name} "' ) commands.append(f'{ip_controls[i]} .txt="{record["ip" ]} "' ) commands.append(f'{status_controls[i]} .txt="{status} "' ) status_color = color_map.get(status, 65535 ) commands.append(f'{status_controls[i]} .pco={status_color} ' ) return commands
把这个函数修改下,默认是查找前7条数据,现在我要传个参数,用来标记查找1-7,7-14,14-21……这样的数据,直到最后一页没有数据了,那就继续查询前7条数据,其实就是做了个分页,把完整的数据分多次查询展示,通过传参不同,怎么实现?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 page_size = 7 page = 2 # 第二页 start_idx = (page - 1 ) * page_size # (2 -1 )*7 = 7 end_idx = start_idx + page_size # 7 +7 = 14 records_8_14 = records[start_idx:end_idx] # 第8 -14 条 total_records = len(records) total_pages = (total_records + page_size - 1 ) // page_size # 向上取整 page = max(1 , min(page, total_pages if total_pages > 0 else 1 )) # 确保页码在有效范围内 start_idx = (page - 1 ) * page_size end_idx = min(start_idx + page_size, total_records) if start_idx >= total_records > 0 : page = 1 start_idx = 0 end_idx = min(page_size, total_records)
切片。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 page_dict = {} for page_num in range (1 , total_pages + 1 ): start_idx = (page_num - 1 ) * page_size end_idx = min (start_idx + page_size, total_records) page_records = records[start_idx:end_idx] page_dict[page_num] = page_records print (f"\n=== 第{page_num} 页 ({start_idx + 1 } -{end_idx} /{total_records} ) ===" ) for i, record in enumerate (page_records, 0 ): record_num = start_idx + i + 1 print (f"{record_num} | " f"主机类型: {record['type_name' ]} | " f"IP: {record['ip' ]} | " f"状态: {'在线' if record['is_online' ] else '离线' } | " f"更新时间: {record.get('update_time_str' , 'N/A' )} " ) print (page_dict[page_num])
翻页。
1 2 3 4 5 6 7 8 9 10 11 12 13 def update_page(self) -> None: """翻页""" all_commands = [] logger.info(f"---{self.page_dict}" ) all_commands.extend(self._update_config_rows(self.page_dict)) success_count = 0 for command in all_commands: if self.hmi_connect.send_command(command): success_count += 1 else : logger.error(f"❌ 命令发送失败: {command}" )
2026 年 1 月 19 日
不对,我还得把 Python 程序部署在服务器,比如云控盒上,还要考虑上电重启后程序能正常运行。
t17,t18,改为滚动文本g0,g1。
强制跳转。
1 2 3 4 if target_page == self.current_page: logger.debug(f"🔄 已在目标页面 {target_page} ,无需跳转" ) print (f"🔄 已在目标页面 {target_page} ,无需跳转" ) return True
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\python.exe -X pycache_prefix=C:\Users\Lenovo\AppData\Local\JetBrains\PyCharmCE2024.1 \cpython-cache D:/dev/ Pycharm/plugins/ python-ce/helpers/ pydev/pydevd.py --multiprocess --qt-support=auto --client 127.0 .0.1 --port 59310 --file D:\Project \luofeng\touchScreen\code\__init__.py Traceback (most recent call last): File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_console_integration.py" , line 4 , in <module> from code import InteractiveConsole, InteractiveInterpreter ImportError: cannot import name 'InteractiveConsole' from 'code' (D:\Project \luofeng\touchScreen\code\__init__.py) During handling of the above exception, another exception occurred: Traceback (most recent call last): File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\pydevd.py" , line 49 , in <module> from _pydevd_bundle.pydevd_comm import CMD_SET_BREAK, CMD_SET_NEXT_STATEMENT, CMD_STEP_INTO, CMD_STEP_OVER, \ ...<5 lines>... InternalSendCurrExceptionTraceProceeded, CommunicationRole, run_as_pydevd_daemon_thread File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_comm.py" , line 91 , in <module> from _pydevd_bundle import pydevd_console_integration File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_console_integration.py" , line 6 , in <module> from _pydevd_bundle.pydevconsole_code_for_ironpython import IronPythonInteractiveConsole as InteractiveConsole, \ IronPythonInteractiveInterpreter as InteractiveInterpreter File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevconsole_code_for_ironpython.py" , line 305 exec code in self.locals ^^^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: Missing parentheses in call to 'exec' . Did you mean exec(...)?
把工作目录改成:D:/Project/luofeng/touchScreen/,而非D:/Project/luofeng/touchScreen/code,没解决报错。
1 2 3 4 5 6 7 8 9 10 11 Traceback (most recent call last): File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_pep_669_tracing.py", line 238 , in py_start_callback if not is_thread_alive(thread): ~~~~~~~~~~~~~~~^^^^^^^^ File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_is_thread_alive.py", line 18 , in is_thread_alive return t.isAlive() ^^^^^^^^^ AttributeError: 'WriterThread' object has no attribute 'isAlive' . Did you mean: 'is_alive' ? File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_pep_669_tracing.py", line 238 , in py_start_callback if not is_thread_alive(thread): ~~~~~~~~~~~~~~~^^^^^^^^
1 2 3 Python 3 .14 是 2024 年 10 月发布的最新版本PyCharm 2024 .1 是 2024 年 3 月发布的,当时 Python 3 .14 尚未发布JetBrains 在 2024 .2 版本中修复了此兼容性问题
监测页。
默认站服务器,点击查询,参数
1 2 3 4 5 6 7 8 9 10 payload = { "pageSize" : 0 , "pageNum" : 0 , "orderByColumn" : "" , "isAsc" : "" , "deptId" : 179 , "monitorHostTypeAll" : [2 ,3 ,4 ], "monitorHostType" : "2" , "monitorStateType" : "" }
跟我想的有些不太一样。
测试数据库只有长治公司。
今中午不需用睡觉了看来,直接忙活到中午两点多钟了。
1 2 3 4 5 6 print (f"\n=== 前5条记录示例 ===" ) for i, record in enumerate (records[:5 ], 1 ): print (f"{i} . IP: {record['ip' ]} | 名称: {record['name' ] or 'N/A' } | " f"状态: {'在线' if record['is_online' ] else '离线' } | " f"更新时间: {record['update_time_str' ]} " )
1 2 3 4 5 6 7 8 print (f"\n=== 前8条记录示例 ===" )for i, record in enumerate (records[:8 ], 1 ): print (f"{i} | " f"IP: {record['ip' ]} | " f"状态: {'在线' if record['is_online' ] else '离线' } | " f"更新时间: {record['update_time_str' ]} | " f"主机类型: {record['type_name' ]} " )
更新汇总信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @staticmethod def _update_summary (data: Dict [str , Any ] ) -> List [str ]: """更新页面底部的汇总信息(原有逻辑不变)""" summary = data["summary" ] station_hosts = summary['station_hosts' ] lane_hosts = summary['lane_hosts' ] gantry_hosts = summary['gantry_hosts' ] commands = [ f't39.txt="{station_hosts} "' , f't40.txt="{lane_hosts} "' , f't48.txt="{gantry_hosts} "' , ] return commands
更新监测数据行控件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 @staticmethod def _update_monitor_rows (data: Dict [str , Any ] ) -> List [str ]: """更新监测数据行控件(原有逻辑不变)""" records = data["records" ] commands = [] id_controls = ['t8' , 't9' , 't10' , 't11' , 't12' , 't13' , 't5' , 't43' ] type_controls = ['t14' , 't15' , 't16' , 't17' , 't18' , 't19' , 't6' , 't44' ] ip_controls = ['t20' , 't21' , 't22' , 't23' , 't24' , 't25' , 't7' , 't45' ] status_controls = ['t26' , 't27' , 't28' , 't29' , 't30' , 't31' , 't32' , 't46' ] time_controls = ['g0' , 'g1' , 'g2' , 'g3' , 'g4' , 'g5' , 'g6' , 'g7' ] color_map = { "在线" : 1696 , "异常" : 63488 , "离线" : 33840 , "警告" : 65504 , } print (f"\n=== 前8条记录示例 ===" ) for i, record in enumerate (records[:8 ], 0 ): print (f"{i} | " f"主机类型: {record['type_name' ]} | " f"IP: {record['ip' ]} | " f"状态: {'在线' if record['is_online' ] else '离线' } | " f"更新时间: {record['update_time_str' ]} " ) status = '在线' if record['is_online' ] else '离线' commands.append(f'{id_controls[i]} .txt="{i} "' ) commands.append(f'{type_controls[i]} .txt="{record["type_name" ]} "' ) commands.append(f'{ip_controls[i]} .txt="{record["ip" ]} "' ) commands.append(f'{status_controls[i]} .txt="{status} "' ) status_color = color_map.get(status, 65535 ) commands.append(f'{status_controls[i]} .pco={status_color} ' ) commands.append(f'{time_controls[i]} .txt="{record["update_time_str" ]} "' ) return commands
页面修改小问题,列表清空,两个页面列表都清空;汇总信息清空,数字左移;IP地址不可编辑;新增点击校验按钮。
第一次查了8条,定时查询第二页第三页……
资产信息后台没有分页查询,那就每过几秒刷新后面的数据,反正都查出来了。
这个目前比较困难,暂时不做。
如何更改控件的前后图层关系 — 淘晶驰串口屏资料中心 1.1.0-2026-01-16 10:28:24 文档
按钮点击后,必然会置顶,妈的。
直接刷新页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def query_station_server_info (self ) -> bool : """查询站服务器信息""" self.hmi_connect.navigate_to_page(4 ) station_server_info = self.get_station_server_info() if station_server_info is not None : result = self.handle_api_data(station_server_info) update_success = self.update_monitor_data(result) if update_success: logger.info("✅ 查询站服务器信息成功" ) else : logger.error("❌ 查询站服务器信息失败" ) return True
三元表达式。
1 2 update_type_name = "站服务器" if record["type_name" ] == "收费站服务器" else record["type_name" ]
监听页,配置页,基本完善。
没有下拉列表,点击按钮切换路段公司以及收费站,现在点击校验功能还有老问题。
重复刷新的原因找到了,控件里为了调试方便加了跳转,控件操作直接跳转后代码中没有记录,所以再次跳转仍然可以。
1 2 3 4 5 6 2026 -01 -19 18 :28 :20 ,207 - INFO - 原始指令: b'\xc7\xeb\xca\xe4\xc8\xeb\xd7\xf3\xb2\xe0\xd0\xc5\xcf\xa2\xff\xff\xff'2026 -01 -19 18 :28 :20 ,207 - INFO - hex指令: C7 EB CA E4 C8 EB D7 F3 B2 E0 D0 C5 CF A2 FF FF FF2026 -01 -19 18 :28 :20 ,207 - INFO - 数据解析结果: None2026 -01 -19 18 :28 :20 ,207 - INFO - 点击校验2026 -01 -19 18 :28 :20 ,207 - INFO - 初始化配置页1 2026 -01 -19 18 :28 :20 ,229 - INFO - 初始化配置页1 完毕
原因找到了,进入配置页1后立刻发送了“请输入左边信息”,这个逻辑是后来添加的,原本是要将一段段由 FF FF FF 分割开的字符发送来,解析出输入的信息,但现在解析不了了。
现在只需要输入公司和收费站,IP用来校验完毕后自动填充,继续正确的逻辑。
明天完善优化这个功能,点击校验。
点击下一步,校验右侧的结果信息,有且只有一种可能才能跳转至下一页,这个逻辑我之前写明白了。
暂时不会将两个按钮合并一块。
下班。
2026 年 1 月 16 日
这个问题越深究越发现搞不定。
jasypt 加密,必须要有密码,加密时还会有随机密钥,只要有了加密后的密文,现在还看不到密码,那说明密码被隐藏在别的地方了。
这还得问问密码多少,要不解密不了。
再看看程序吧,不纠结密码问题了。
其实监测,配置1,配置2,首页接口没问题的,外加个下拉框看看怎么适配下,不需要纠结概览页。
概览页也没问题,再梳理下代码看看是不是数据库的问题。
在哪里查出来个阳城南站,晋城的。
1 2 3 101 .227 .48 .102 :3306 root rootaxdQ @1121 .1226
路段版本:
1 url: jdbc:mysql:// 14.103 .238.145 :10060 /sx_rmgt
省中心:
1 jdbc:mysql:// 101.227 .48.102 :3306 /sx_monitor
2026 年 1 月 13 日
SSH 密钥验证仍然失败,算了先不搞这个。
拉取路段版本代码分支。
查看下数据库账号密码。
application-dev.yaml
1 2 3 username: ENC(K+PL9ntYPPXO8MBMmlWvOA==) password: ENC(C7n/6K8ktMrJ5vmDnzhZM9A7OjAxgesTpfuQoRBQ/k0=)
1 2 3 4 5 jasypt: encryptor: password: lybgeek algorithm: PBEWithMD5AndDES iv-generator-classname: org.jasypt.iv.NoIvGenerator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 private static final String salt = "lybgeek" ; public static String decode (String ciphertext) { System.out.println("加密字符串:" + ciphertext); ciphertext = "ENC(" + ciphertext + ")" ; if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)) { String plaintext = PropertyValueEncryptionUtils.decrypt(ciphertext, basicTextEncryptor); System.out.println("解密后的字符串:" + plaintext); return plaintext; } System.out.println("解密失败" ); return "" ; }
执行获取数据库解密后的用户名和密码。
1 2 3 4 5 6 加密字符串:K+PL9ntYPPXO8MBMmlWvOA== 解密后的字符串:root root 加密字符串:C7n/6 K8ktMrJ5vmDnzhZM9A7OjAxgesTpfuQoRBQ/k0= 解密后的字符串:LuoFenMysql@89s # LuoFenMysql@89s #
路段版本测试环境,数据库连接信息:
1 2 3 14.103.238.145:10060 root LuoFenMysql@89s#
这样数据库就连接成功了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <select id ="selectSectionHostDeptMapByHostTypeAndDeptId" parameterType ="java.lang.Byte" resultType ="com.tomm.system.domain.SectionHostDeptMap" > SELECT <include refid ="Base_Column_List" /> FROM t_section_host_dept_map <where > <if test ="deptIds != null and deptIds.size() > 0" > AND dept_id IN <foreach item ="item" collection ="deptIds" open ="(" separator ="," close =")" > #{item} </foreach > </if > <if test ="hostTypes != null and hostTypes.size() > 0" > AND host_type IN <foreach item ="item" collection ="hostTypes" open ="(" separator ="," close =")" > #{item} </foreach > </if > </where > </select >
启动项目。
1 Error running 'TommApplication' Error running TommApplication. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun.
似曾相识的问题。
调用成功。
1 http:// 14.103 .238.145 :10058 /dev-api/ smallScreenDispla/monitorSummary
1 2 3 4 5 6 7 { "code" : 500 , "msg" : "获取资产信息有误" , "data" : null , "success" : false , "error" : true }
1 SynchronizationEventTask
1.路段主机 2.收费站主机 3.车道工控机 4.门架工控机 5门架服务器 6网络设备
现在调用测试服务器老是报获取资产信息有误的错误,调用本机部署的服务有出现 Token 认证错误,首先解决下本机问题,再 Debug。
1 2 3 4 5 6 7 8 9 10 11 12 13 at com.tomm .framework .config .SaTokenConfig .lambda$null $0 (SaTokenConfig.java :49 ) at cn.dev33 .satoken .router .SaRouterStaff .check (SaRouterStaff.java :213 ) at com.tomm .framework .config .SaTokenConfig .lambda$addInterceptors $1 (SaTokenConfig.java :47 ) at cn.dev33 .satoken .interceptor .SaRouteInterceptor .preHandle (SaRouteInterceptor.java :60 ) at org.springframework .web .servlet .HandlerExecutionChain .applyPreHandle (HandlerExecutionChain.java :148 ) at org.springframework .web .servlet .DispatcherServlet .doDispatch (DispatcherServlet.java :1067 ) at org.springframework .web .servlet .DispatcherServlet .doService (DispatcherServlet.java :965 ) at org.springframework .web .servlet .FrameworkServlet .processRequest (FrameworkServlet.java :1006 ) ... 68 common frames omitted2026 -01 -13 11 :32 :10 [XNIO-1 task-1] DEBUG c.t .f .i .PlusWebInvokeTimeInterceptor - <0 ><18173075801398208 > [PLUS] 开始请求 => URL[POST /error] ,参数类型[json] ,参数:[] 2026 -01 -13 11 :32 :10 [XNIO-1 task-1] ERROR c.t .f .w .e .GlobalExceptionHandler - <0 ><18173075801398208 > 请求地址'/error' ,认证失败'未能读取到有效Token' ,无法访问系统资源
数据库查询是没问题的。
1 2 3 4 5 6 SELECT * FROM t_section_host_dept_mapWHERE dept_id IN ('192' ) AND host_type IN ('2' , '3' )
$2a$10$NHj9.nG3ekSAOQHdAdYS2eWnQZbiQQrKrJ8A5jxP3IbFI4cjwhJnS
JasyptEncryptorUtils
1 2 3 4 5 6 7 8 9 @ExceptionHandler(NotLoginException.class) public R<Void> handleNotLoginException (NotLoginException e, HttpServletRequest request) { String requestURI = request.getRequestURI(); log.error("请求地址'{}',认证失败'{}',无法访问系统资源" , requestURI, e.getMessage()); return R.fail(HttpStatus.HTTP_UNAUTHORIZED, "认证失败,无法访问系统资源" ); }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package com.tomm.framework.config.properties;import cn.hutool.core.util.ReUtil;import com.tomm.common.annotation.Anonymous;import com.tomm.common.utils.spring.SpringUtils;import lombok.Getter;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.annotation.Lazy;import org.springframework.core.annotation.AnnotationUtils;import org.springframework.stereotype.Component;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.mvc.method.RequestMappingInfo;import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import org.springframework.web.util.pattern.PathPattern;import java.util.*;import java.util.regex.Pattern;@Lazy @Component public class ExcludeUrlProperties implements InitializingBean { private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}" ); @Getter private final List<String> excludes = new ArrayList <>(); @Override public void afterPropertiesSet () { String asterisk = "*" ; RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping" , RequestMappingHandlerMapping.class); Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods(); map.keySet().forEach(info -> { HandlerMethod handlerMethod = map.get(info); Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); Optional.ofNullable(method).ifPresent(anonymous -> { Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns(); patterns.forEach(url -> { excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); }); }); Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); Optional.ofNullable(controller).ifPresent(anonymous -> { Set<PathPattern> patterns = info.getPathPatternsCondition().getPatterns(); patterns.forEach(url -> { excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); }); }); }); } }
自动扫描项目中所有被 @Anonymous注解标记的接口,将它们的URL路径收集到 excludes列表中,用于配置不需要认证的接口 。
如何在GitLab中的个人资料里增加SSH密钥-腾讯云开发者社区-腾讯云
本地启动项目,接口文档地址:OpenAPI definition
1 http:// localhost:10057 /smallScreenDispla/m onitorSummary
通了,注释掉是否有 Token。
要花时间专门来熟悉下路段版本。
1 2 3 4 5 6 7 List<SectionHostDeptMap> sectionHostDeptMapList = sectionHostDeptMapService.selectSectionHostDeptMapByHostTypeAndDeptId( Lists.newArrayList(syncAssetInfoDto.getDeptId()), Lists.newArrayList((byte )10 )); log.info("查询概览参数,获取本机资产数据结果:{}" , JsonUtils.toJsonString(sectionHostDeptMapList)); if (CollUtil.isEmpty(sectionHostDeptMapList) || sectionHostDeptMapList.size() > RmgtMagicValue.ONE) { throw new ServiceException ("获取资产信息有误" ); }
Debug,这里就卡住了。
见鬼了,为什么这里的 hostTypes 列表默认携带参数为 10。
1 2 3 4 @Override public List<SectionHostDeptMap> selectSectionHostDeptMapByHostTypeAndDeptId (List<Long> deptIds, List<Byte> hostTypes) { return sectionHostDeptMapMapper.selectSectionHostDeptMapByHostTypeAndDeptId(deptIds, hostTypes); }
卧艹,这里为什么默认列表第一个值是10.
1 2 3 List<SectionHostDeptMap> sectionHostDeptMapList = sectionHostDeptMapService.selectSectionHostDeptMapByHostTypeAndDeptId( Lists.newArrayList(syncAssetInfoDto.getDeptId()), Lists.newArrayList((byte )10 ));
Lists.newArrayList((byte)10)创建了一个包含单个字节值 10 的 List,表示查询主机类型为 10 的记录。
1 2 3 4 5 6 7 8 XML 中的 parameterType错误 parameterType="java.lang.Byte"<select id ="..." resultType ="..." > <select id ="..." parameterType ="map" resultType ="..." >
1 2 3 if (CollUtil.isEmpty(sectionHostDeptMapList) || sectionHostDeptMapList.size() > RmgtMagicValue.ONE) { throw new ServiceException ("获取资产信息有误" ); }
1 2 3 4 5 6 7 8 List<LatestItemsHistoryVo> selectAllHistoryInfo(@Param("itemIds" ) List<Long > itemIds, @Param("type" ) Integer type);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <if test="type=='3'.toString()"> zabbix.history_uint hu JOIN ( SELECT h.itemid, MAX( h.clock ) AS clock FROM zabbix.history_uint h WHERE h.itemid in <foreach collection="itemIds" item="itemid" open ="(" separator="," close =")"> #{itemid} </foreach > GROUP BY h.itemid ) a on hu.itemid=a.itemid and hu.clock=a.clock </if >
所有 t_section_host_dept_map 表下的部门 id。
1 SELECT DISTINCT dept_id FROM t_section_host_dept_map
返回的接口只有这样的数值,Zabbix 数据库缺失数据,收费站也不应该只有长治的收费站信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 { "code" : 200 , "msg" : "操作成功" , "data" : { "ip" : "10.14.76.66" , "cpu" : "0" , "ram" : "0" , "disk" : "0" , "uploadBytes" : "0" , "downloadBytes" : "0" , "memoryTotal" : "0" , "memoryUsed" : "0.00" , "memoryFree" : "0" , "diskTotal" : "0" , "diskUsed" : "0" , "diskFree" : "0.00" } , "error" : false , "success" : true }
Mysql去重
pycharm控制台输出结果自动换行_pycharm自动换行-CSDN博客
1 2 3 4 curl -X POST http:// localhost:10057 /smallScreenDispla/m onitorSummary \ -H "Content-Type: application/json" \ -d '{"deptId": 192}'
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import jsonimport requestsdef monitor_summary_api (): payload = { "deptId" : 192 , } headers = { 'Content-Type' : 'application/json' } response = requests.post( 'http://localhost:10057/smallScreenDispla/monitorSummary' , data=json.dumps(payload), headers=headers ) print (response.status_code) return response.textif __name__ == '__main__' : monitor_summary_api()
1 2 result = monitor_summary_api()print (result)
写了个这么几把调用,概览页先这么着吧。
首页。
1 http:// localhost:10057 /smallScreenDispla/ homePageMonitorSummary
1 2 3 4 5 6 7 8 9 10 11 { "code" : 200 , "msg" : "操作成功" , "data" : { "monitoredCount" : 27 , "abnormalCount" : 26 , "updateTime" : "2026-01-13 17:37:43" } , "error" : false , "success" : true }
获取部门下拉。
1 2 3 4 5 @Schema(description = "部门类型,0省中心,1公司,2路段,3收费站") String ifDeptType;@Schema(description = "父级id") Long parentId;
1 2 3 4 5 6 7 8 9 10 11 @Override public List<SysDept> getSelectedDept (GetSelectedDeptDto getSelectedDeptDto) { log.info("获取部门下拉入参:{}" , JsonUtils.toJsonString(getSelectedDeptDto)); if (ObjUtil.isEmpty(getSelectedDeptDto) || StrUtil.isBlank(getSelectedDeptDto.getIfDeptType())) { throw new ServiceException ("获取部门下拉入参有误,请联系管理员处理!" ); } List<SysDept> sysDepts = mgtClient.selectSysDeptByIfDeptType(getSelectedDeptDto).getData(); log.info("获取部门下拉返回:{}" , JsonUtils.toJsonString(sysDepts)); return sysDepts; }
1 2 3 4 5 6 7 List<SysDept> selectSysDeptByIfDeptType (@Param("ifDeptType") String ifDeptType) ;
1 2 3 4 5 6 7 <select id="selectSysDeptByIfDeptType" parameterType="java.lang.String" resultType="com.tomm.common.core.domain.entity.SysDept" > SELECT <include refid="Base_Column_List" /> FROM sys_dept WHERE (del_flag = '0' and if_dept_type !='0' and if_dept_type=#{ifDeptType}) ORDER BY parent_id ASC , order_num ASC </select >
1 2 SELECT * FROM sys_deptWHERE if_dept_type = 3
0 省中心,1分公司,2路段,3收费站。
查询部门信息,获取部门下拉列表。
1 2 3 4 5 6 7 8 9 10 @FeignClient( name = MgtClient.MGT, url = "${mgt.url}", path = "/mgt", configuration = FeignBypassSSLConfig.class ) public interface MgtClient {
1 2 3 4 5 6 7 8 @PostMapping(value = "/selectSysDeptByIfDeptType") R<List<SysDept>>selectSysDeptByIfDeptType(@RequestBody GetSelectedDeptDto getSelectedDeptDto);
从省中心调用接口,获取部门信息。
监听页面。
1 2 3 4 5 @Operation(summary = "监测资产接口,通过条件,查询路段、门架、车道、设备等主机列表") @PostMapping("/monitorAsset") public R<MonitorAssetVo> monitorAsset (@RequestBody MonitorAssetDto monitorAssetDto) { return R.ok(smallScreenDisplayService.monitorAsset(monitorAssetDto)); }
1 2 3 4 5 @Operation(summary = "查询省中心资产信息,通过条件,控制查询公司、路段、收费站层级的数据") @PostMapping("/selectAssetInfo") public R<MonitorAssetVo> selectAssetInfo (@RequestBody MonitorAssetDto monitorAssetDto) { return R.ok(smallScreenDisplayService.selectAssetInfo(monitorAssetDto)); }
1 2 3 4 5 6 7 Page<MonitorAssetHost> monitorAssetHostList = sectionHostDeptMapService.selectAssetHostListPage(deptIds, hostTypes, monitorAssetDto.getMonitorStateType(), monitorAssetDto.build()); for (MonitorAssetHost monitorAssetHost : monitorAssetHostList.getRecords()) { monitorAssetHost.setHostTypeName(HostTypeEnum.getValue(monitorAssetHost.getHostType())); }
查询主机列表,主机列表有记录,但详细记录为空。
1 2 3 4 5 6 7 8 9 Page<MonitorAssetHost> selectAssetHostListPage (List<Long> deptIds, List<Byte> hostTypes, String monitorStateType, Page<MonitorAssetHost> page) ;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <select id="selectAssetHostListPage" parameterType="map" resultType="com.tomm.system.domain.vo.MonitorAssetHost" > SELECT shdm.host_ip, shdm.host_type, shdm.update_time, h.name as hostName, if (h.`status`='0' ,'1' ,'0' ) monitorState FROM t_section_host_dept_map shdm left JOIN zabbix.hosts h ON h.hostid = shdm.host_id <where> <if test="deptIds != null and deptIds.size() > 0" > AND shdm.dept_id IN <foreach item="item" collection="deptIds" open="(" separator="," close=")" > #{item} </foreach> </if > <if test="hostTypes != null and hostTypes.size() > 0" > AND shdm.host_type IN <foreach item="item" collection="hostTypes" open="(" separator="," close=")" > #{item} </foreach> </if > <if test="monitorStateType != null and monitorStateType != ''" > AND h.`status`!= #{monitorStateType} </if > </where> </select>
1 2 3 4 FROM t_section_host_dept_map shdmleft JOIN zabbix.hosts h ON h.hostid = shdm.host_id
初步判断同样的问题。
zabbix.hosts,监测平台表数据缺失。
2026 年 1 月 12 日
一晃眼一个月时间都快过去了。
这工作安排真够有意思的,看看串口屏开发到了什么地步,接下来先测试 Python 程序调用 Java 接口文档获取接口数据。
小屏显示数据接口,不太完善。
1 2 3 4 5 6 7 8 @GetMapping("/test") public String test () { System.out.println("Hello World" ); return "Hello World" ; }
1 2 3 4 5 6 7 8 9 def main (): response = requests.get('http://localhost:8080/api/test' ) print (response.status_code) print (response.text)if __name__ == '__main__' : print (sys.path) main()
调用接口。
1 2 3 4 5 6 C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\python.exe D:\Project\luofeng\t ouchScreen\code\t est\t est.py ['D:\\ Project\\ luofeng\\ touchScreen\\ code\\ test', 'D:\\ Project\\ luofeng\\ touchScreen', 'C:\\ Users\\ Lenovo\\ AppData\\ Local\\ Programs\\ Python\\ Python314\\ python314.zip', 'C:\\ Users\\ Lenovo\\ AppData\\ Local\\ Programs\\ Python\\ Python314\\ DLLs', 'C:\\ Users\\ Lenovo\\ AppData\\ Local\\ Programs\\ Python\\ Python314\\ Lib', 'C:\\ Users\\ Lenovo\\ AppData\\ Local\\ Programs\\ Python\\ Python314', 'C:\\ Users\\ Lenovo\\ AppData\\ Local\\ Programs\\ Python\\ Python314\\ Lib\\ site-packages'] 200 Hello World Process finished with exit code 0
什么几把接口,每个接口都得我自己实现一遍么,连一个能用的接口都没有。
高速公路联网收费运行监测管理平台
在这里呆着太特么无聊了。
接口得自己写,数据库账号密码都不晓得,写新接口比较费劲,代码都不一定能推的上去,接口写完再调试接口调用赋值。
最后再研究部署,这些活儿都得自己完成,现在连截至时间都没弄明白,下午正好有个周会,有问题能沟通下看能不能解决。
2025 年 12 月 16 日
智能物联终端-蓝湖
一大早就收到了最新的智能物联终端UI最终效果图。
用PS导出纯色色块,所有文字都用 USART HMI 添加文字控件,要不文字分辨率太低。
做完五个页面,怎么一调试就全乱套了,他妈的。
五点四十分,搞定全部五个页面,再次尝试能不能顺利下载,该删的图片都删了。
成功下载,除监测页面获取数据并赋值给对应控件,完成。
明天去郑州,妈的。
2025 年 12 月 15 日
一晃两天过去了,这两天啥也没干。
单片机发送数据给串口屏 — 淘晶驰串口屏资料中心 1.1.0-2025-12-04 09:17:37 文档
改造点击下一步;优化首页、监测页、概览页和配置页的数据获取逻辑,主要整理下返回格式化数据。
1 2 3 4 5 't3.txt="编号"' ,'t4.txt="类型"' ,'t5.txt="IP"' ,'t6.txt="监测状态"' ,'t7.txt="更新时间"'
上周就发现这个诡异现象了,t7 控件更新失败。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def handle_validate_event (self ): """处理校验事件""" logger.info('点击校验' ) config = ConfigPage1Updater(self.hmi_connect) result, commands = config.validate(self.hex_data) logger.info(f"校验结束, 标记结果状态:{result} ; 校验结果信息: {commands} " ) logger.info("=" * 50 ) self.if_validate = result for command in commands: self.hmi_connect.send_command(command)
1 2 3 4 5 6 7 8 9 class ConfigPage1Updater : """简化版配置页面处理""" def __init__ (self, hmi_connect ): self.hmi_connect = hmi_connect self.current_page = 2 self.next_page = 3 self.hmi_connect.send_command(f't7.pco=1055' ) self.hmi_connect.send_command(f't7.txt="请输入信息"' )
问题可能出在这了。
问题出个几把,删了这段都没反应。
点击下一步。
点击下一步,跳转业务逻辑全部封装点击校验,校验成功就显示校验成功信息,显示再点击一次下一步就成功跳转配置页2;校验失败就显示校验错误信息,跟之前的点击校验逻辑是一样的。
把点击校验的功能封装到点击下一步,
【腾讯文档】加班统计表https://docs.qq.com/sheet/DTEFLY3p2R0tQV0pU?tab=000001
新增 api_pages 页面,初步完善从后台接口文档获取真实数据的功能。
问题不在于 config_page_2 或者 monitor_page 页面编码,不需要在这里排查了。
1 2 3 4 logger.info("初始化配置页1" ) self.hmi_connect.send_command(f't7.pco=1055' ) self.hmi_connect.send_command(f't7.txt="请输入信息"' ) logger.info("初始化配置页1完毕" )
1 2 3 4 5 6 7 8 9 10 11 2025 -12 -15 10 :59 :05 ,839 - INFO - 点击下一步前,校验结果:True2025 -12 -15 10 :59 :05 ,839 - INFO - 已跳转到页面 3 2025 -12 -15 10 :59 :05 ,839 - INFO - 📊 获取到 9 条监测数据2025 -12 -15 10 :59 :05 ,913 - INFO - 📊 监测页面更新完成: 71 /71 条命令成功 (100 .0 %)2025 -12 -15 10 :59 :05 ,913 - INFO - ✅ 监测页面更新成功2025 -12 -15 10 :59 :06 ,398 - INFO - 点击校验2025 -12 -15 10 :59 :06 ,398 - INFO - 初始化配置页1 2025 -12 -15 10 :59 :06 ,398 - INFO - 初始化配置页1 完毕2025 -12 -15 10 :59 :06 ,398 - INFO - 🔍 校验输入: IP=$, 公司=, 收费站=2025 -12 -15 10 :59 :06 ,398 - INFO - 校验结束, 标记结果状态:False; 校验结果信息: ['t7.txt="校验未通过\r\n路段公司不\r\n能为空"', 't7.pco=63488'] 2025 -12 -15 10 :59 :06 ,398 - INFO - ==================================================
这特么什么原因。
点击下一步,怎么接下来还监听到校验事件了。
1 2 3 4 5 6 7 2025 -12 -15 11 :05 :25 ,433 - INFO - ✅ 监测页面更新成功2025 -12 -15 11 :05 :25 ,916 - INFO - 校验前检查下受到了什么数据:b'$\xff\xff\xff'2025 -12 -15 11 :05 :25 ,916 - INFO - 点击校验2025 -12 -15 11 :05 :25 ,916 - INFO - 初始化配置页1 2025 -12 -15 11 :05 :25 ,917 - INFO - 初始化配置页1 完毕2025 -12 -15 11 :05 :25 ,917 - INFO - 🔍 校验输入: IP=$, 公司=, 收费站=2025 -12 -15 11 :05 :25 ,917 - INFO - 校验结束, 标记结果状态:False; 校验结果信息: ['t7.txt="校验未通过\r\n路段公司不\r\n能为空"', 't7.pco=63488']
24 FF FF FF 串口缓冲区溢出 — 淘晶驰串口屏资料中心 1.1.0-2025-12-12 10:12:30 文档
找到原因了。
1 2 3 4 5 2025 -12 -15 11 :20 :00 ,349 - INFO - 📊 监测页面更新完成: 72 /72 条命令成功 (100 .0 %)2025 -12 -15 11 :20 :00 ,349 - INFO - ✅ 监测页面更新成功2025 -12 -15 11 :20 :00 ,892 - INFO - 数据解析结果: None2025 -12 -15 11 :20 :00 ,892 - INFO - 校验前检查下受到了什么数据:b'$\xff\xff\xff'2025 -12 -15 11 :20 :00 ,892 - INFO - 校验前检查下受到了什么数据:24 FF FF FF
当串口缓冲区被占满以后会返回此数据
缓冲区溢出以后,缓冲队列里的指令执行完成后会为缓冲区腾出空间以继续接收指令,在此之前,串口收到的数据将会丢弃
常见原因:
发送的速度太快了,建议每条指令间隔100毫秒 。
发送了太多无关的指令,串口屏无法进行解析,导致串口缓冲区被占满。
1 2 3 4 5 full_command = command.encode('gbk' ) + b'\xFF\xFF\xFF' self.ser.write(full_command) time.sleep(0.1 )
设置指令发送间隔 100 毫秒。
1 2 3 2025 -12 -15 11 :25 :27 ,796 - INFO - 数据解析结果: None2025 -12 -15 11 :25 :27 ,796 - INFO - 校验前检查下受到了什么数据:b'\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff\x1a\xff\xff\xff'2025 -12 -15 11 :25 :27 ,796 - INFO - 校验前检查下受到了什么数据:1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF
又出现了新的问题。
1 2 3 4 5 total_commands = len (all_commands) success_rate = (success_count / total_commands) * 100 if total_commands > 0 else 0 logger.info(f"📊 监测页面更新完成: {success_count} /{total_commands} 条命令成功 ({success_rate:.1 f} %)" )return success_count == total_commands
1 2 3 4 try : if self.ser and self.ser.is_open: self.clear_buffer()
1 2 3 4 5 6 7 8 9 success_count = 0 for command in all_commands: if self.hmi_connect.send_command(command): success_count += 1 else : logger.error(f"❌ 命令发送失败: {command} " ) self.hmi_connect.ser.read_all()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def send_command (self, command: str ) -> bool : """发送指令到串口屏""" try : if self.ser and self.ser.is_open: self.clear_buffer() full_command = command.encode('gbk' ) + b'\xFF\xFF\xFF' self.ser.write(full_command) self.clear_buffer() time.sleep(0.01 ) return True
这清空缓冲区都写烂了,串口屏还是会收到 1A FF FF FF。
1 2 3 4 5 6 7 8 9 10 def update_monitor_data (self, data: List [Dict [str , Any ]] ): """更新监测页面所有控件数据""" try : all_commands = [] all_commands.extend(self._update_header_controls())
找到问题了,问题出在更新监测数据行和更新汇总统计后。
1 2 # 统计信息文本(如果有对应控件的话) # f't_summary.txt="正常率: {normal_rate:.1f}% 异常: {status_count.get(" 异常", 0)}个" ',
他妈的这里有个更新统计信息文本。。。
1 2 3 4 5 if status == "异常" : commands.append(f'{status_controls[i]} .blink=1' )else : commands.append(f'{status_controls[i]} .blink=0' )
他妈的这里还有个状态异常添加闪烁效果。。。
问题全部排除。
各条命令之间休眠 100 毫秒是很有必要的。
1 2 3 4 5 6 7 if data == b'query' : return { 'type' : constants.Constants.QUERY_EVENT, 'data' : touch_info, }
your-backend-api.com
他妈的这么个随便生成的 API 接口地址,竟然是真实存在的,怪不得调用还真花了点时间。
1 2 3 4 5 6 API_CONFIG = { "url" : "http://your-backend-api.com/system/overview" , "timeout" : 5 , "method" : "GET" }
云里雾里优化到下午四点多钟,完善各个页面的请求接口文档获取真实数据功能,他妈的接口文档还不知道呢,等明天慧敏来了再问问。
Docker 部署 Python 服务。
1 2 3 update_count = 0 HomePageUpdater(self.hmi_connect).run()
他妈的这怎么又行了。
1 2 3 4 5 6 7 8 9 10 11 def get_monitor_data (self ) -> List [Dict [str , Any ]]: """统一数据获取入口""" api_data = self.fetch_data_from_api() if api_data is not None : result = self.handle_api_data(api_data) return result logger.warning("⚠️ 接口调用失败" ) return self.generate_mock_data()
1 2 3 4 def handle_api_data (self, api_data: List [Dict [str , Any ]] ) -> List [Dict [str , Any ]]: """处理接口返回数据""" data = [] return data
先把三个查询接口写完整了,再想想怎么处理分页查询。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 elif page_id == 1 and control_id == 6 : logger.info('点击查询站服务器信息' ) monitor = MonitorPageUpdater(self.hmi_connect) monitor.query_station_server_info()elif page_id == 1 and control_id == 7 : logger.info('点击查询车道信息' ) monitor = MonitorPageUpdater(self.hmi_connect) monitor.query_lane_info()elif page_id == 1 and control_id == 8 : logger.info('点击查询门架信息' ) monitor = MonitorPageUpdater(self.hmi_connect) monitor.query_door_info()
1 2 3 4 5 6 7 def query_station_server_info (self ) -> bool : """查询站服务器信息""" data = self.get_station_server_info() self.update_monitor_data(data) return True
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 @staticmethod def get_station_server_info () -> List [Dict [str , Any ]] | None : """查询站服务器信息""" try : logger.info(f"📡 正在调用查询站服务器信息接口: {API_CONFIG['url' ]} " ) if API_CONFIG["method" ].upper() == "GET" : response = requests.get(API_CONFIG["url" ], timeout=API_CONFIG["timeout" ]) else : response = requests.post( API_CONFIG["url" ], json={}, timeout=API_CONFIG["timeout" ] ) response.raise_for_status() api_data = response.json() logger.info("✅ 站服务器信息获取成功" ) return api_data except requests.exceptions.RequestException as e: logger.error(f"❌ 站服务器信息获取失败: {e} " ) return None except ValueError as e: logger.error(f"❌ 站服务器信息数据解析失败: {e} " ) return None
查询功能基本完善,跟页面查询一样,就剩对接真实的后台接口文档以及处理并返回真实数据了,接下来搞搞分页查询。
分页思路不好操作。
不像前端框架那样有很方便的分页插件啥的。
算了,分页不做了,监测页面获取数据后定时查询,初步想法是每隔三秒查询下一页数据,循环查询。
2025 年 12 月 12 日
1 咱们屏幕上的软件,是有java后台的,你只要用python调用http api就可以了,不用重新操作数据库
Python调用java接口_python 使用json调取java接口-CSDN博客
调试结束。
Memory/touch-screen
1 git@gitee .com :deng-2022 /touch-screen.git
项目换个目录,他妈的怎么就导入包不成功了。
1 2 from code .utils.touch_event import TouchEventfrom code .utils.hmi_connect import HMIConnect
(亲测解决)PyCharm 从目录下导包提示 unresolved reference(完整图解)_unresolved reference怎么解决-CSDN博客
他妈的解决了,新增 code 目录必须要勾选 new Python Package 选项,而不能勾选 new Directory 选项。
点击下一步,先点击校验,校验成功的信息是固定的,判断校验信息是否为"校验通过\r\n点击下一步",则跳转,反之显示需校验通过。
进入配置页,前初始化事件发送校验结果文本。
1 2 3 4 5 6 7 8 if (t7.txt!="" ) { prints t7.txt,30 //发送ip地址 printh ff ff ff //发送帧尾 }else { printh ff ff ff //发送空数据 }
touch-screen: 基于上位机软件 USART HMI 开发的 淘晶驰 T1 系列 4.3 寸 tft 液晶显示屏(串口屏)
1 2 3 4 5 6 7 8 9 def handle_validate_event (self ): """处理非触摸事件""" logger.info('点击校验' ) config = ConfigPage1Updater(self.hmi_connect) commands = config.validate(self.hex_data) print (f"结果:{commands} " ) for command in commands: self.hmi_connect.send_command(command)
这里的 self.hex_data 是不合理的,进入配置页抓取校验文本信息,抓取方法不应该放在全局监听下,应该独立写一个方法。
重新捋逻辑。
任何操作都会被监听,处理监听事件目前分为处理触摸事件(这个触摸是指同简单的页面更新绑定,因为触摸意味着跳转页面)、处理文本校验事件,后续完善处理跳转事件、处理其他事件。
把文本校验放在全局监听中,获取校验文本值,保存至 Config1updater 的 self 值中,在处理文本校验事件以及其他时间中,直接引用。
设计是合理的。
1 2 3 4 5 6 def __init__ (self, hmi_connect ): self.hmi_connect = hmi_connect self.current_page = 2 self.next_page = 3 self.hmi_connect.send_command(f't7.pco=1055' ) self.hmi_connect.send_command(f't7.txt="请输入信息"' )
妈的,默认数据直接在 USART HMI 中默认指定不就行了,哪里还用用得着解析前初始化事件发来的文本数据。
接下来处理点击下一步逻辑。
1 2 3 4 5 6 7 8 if (t7.txt!="" ) { prints t7.txt,30 printh ff ff ff }else { printh ff ff ff }
前初始化事件也不应该发送文本,发送了之后他妈的就监听到文本校验事件了。
后续需要考虑下跳转事件,校验事件以及查询事件的区别。
为什么,用Python程序实现跳转页面,只有第一次有效,之后就无效了,都走了同样的函数逻辑为什么第二次点击按钮后,串口屏页面就不跳转了。
他妈的,日志输出害我不浅,这条 DEBUG 日志就没打印出来。
1 2 3 4 5 6 elif (page_id == 1 and control_id == 3 or page_id == 2 and control_id == 3 or page_id == 3 and control_id == 3 or page_id == 4 and control_id == 3 ): logger.info('返回至主页' )
点击返回,返回上一页。
点击配置2页面的上一页后,用 Python 程序实现跳转,保留 current_page 属性为 2,再次跳转页面 3 就没问题。
点击配置1页面的上一页后,用 Python 程序实现跳转,保留 current_page 属性为 0,……
不对,不能重复跳转是逻辑问题,理论上应该用 Python 程序实现所有页面跳转。
1 2 3 4 5 if page_id == 0 and control_id == 3 : logger.info('跳转至概览页' ) overview = OverviewPageUpdater(hmi_connect) overview.run()
1 2 3 elif page_id == 4 and control_id == 3 : logger.info('概览页返回至主页' ) self.hmi_connect.navigate_to_page(0 )
要重新写个启动类了,影响 home_page 的导入。
1 2 3 4 from code.pages.monitor_page import MonitorPageUpdaterfrom code.pages.overview_page import OverviewPageUpdaterfrom code.pages.config_page_1 import ConfigPage1Updaterfrom code.pages.config_page_2 import ConfigPage2Updater
1 2 3 4 if __name__ == '__main__' : # 使用示例 init = InitControl(HMIConnect(port ='COM5' , baudrate =115200)) init.main()
新增启动类,直接负责启动系统,但首页首次渲染有问题,不应该有问题啊,暂时解决返回至首页的页面刷新问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 elif page_id == 1 and control_id == 3 : logger.info('监测页返回至首页' ) HomePageUpdater(self.hmi_connect).run() elif page_id == 2 and control_id == 3 : logger.info('配置页1返回至首页' ) HomePageUpdater(self.hmi_connect).run() elif page_id == 3 and control_id == 3 : logger.info('配置页2返回至主页' ) HomePageUpdater(self.hmi_connect).run() elif page_id == 4 and control_id == 3 : logger.info('概览页返回至主页' ) HomePageUpdater(self.hmi_connect).run()
点击下一步。
1 2 3 4 5 6 7 8 9 if (t7.txt!="" ) { prints t7.txt,30 printh ff ff ff }else { printh ff ff ff }
不行,太混乱了,直接选择在点击校验完毕后保存校验结果,保存到服务端,点击下一步不用紊乱调用处理校验事件的函数了。
1 2 3 4 5 logger.info("✅ 输入校验通过" ) self.validate_success = f't7.txt="校验通过\r\n点击下一步"' commands.append(self.validate_success) commands.append(f't7.pco=1696' )
那这个方法就算白写了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @staticmethod def get_validate_result_value (hex_data ) -> dict : """解析校验结果输入值""" separator = 'FF FF FF' hex_parts = hex_data.split(separator) hex_parts = hex_parts[:-1 ] cleaned_parts = [p.strip() for p in hex_parts] result = {} if len (cleaned_parts) > 0 : result['validate' ] = cleaned_parts[0 ] else : result['validate' ] = "" return result
校验结束,校验成功后标记,
1 2 3 4 5 self.if_validate = True print (f"标记校验成功,{self.if_validate} " )for command in commands: self.hmi_connect.send_command(command)
点击下一步前,检查校验结果。
1 2 3 4 5 6 7 8 9 elif page_id == 2 and control_id == 9 : logger.info('点击下一步' ) print (f"点击下一步前,校验结果: {self.if_validate} " ) if self.if_validate: ConfigPage2Updater(self.hmi_connect).run() else : logger.info('请先完成配置' )
启用监听程序,把对象实例化放在循环监听外,解决问题,正常运行逻辑。
1 2 3 4 5 touch_event = TouchEvent(self.hmi_connect)while True : try : touch_event.display_touch_listener()
正常个几把,重新优化代码,校验结果返回元组,校验结果标记。
1 2 3 4 5 6 7 8 9 result, commands = config.validate(self.hex_data) logger.info(f"校验结束, 标记结果状态:{result} ; 校验结果信息: {commands} " ) logger.info("=" * 50 ) self.if_validate = resultfor command in commands: self.hmi_connect.send_command(command)
慢着。
点击下一步。如果校验结果成功,那就跳转,如果不成功呢,校验结果为任何未通过校验的信息,默认无法跳转,此时保留校验结果;那如果是初始默认的请输入信息 呢。
去他妈的,只要校验没通过,就固定提醒没有校验通过,改个黄色的字体。
点击下一步基本完成,但还是有点不太方便。
整合成一个按钮,就点击下一步。
点击下一步,先校验字段,如果未通过校验,那就显示失败原因
2025 年 12 月 11 日
单片机发送数据给串口屏 — 淘晶驰串口屏资料中心 1.1.0-2025-12-04 09:17:37 文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 if (t1.txt!="" ) { prints t1.txt,30 printh ff ff ff }else { printh ff ff ff }if (t6.txt!="" ) { prints t6.txt,30 printh ff ff ff }else { printh ff ff ff }if (t5.txt!="" ) { prints t5.txt,30 printh ff ff ff }else { printh ff ff ff }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 @staticmethod def get_input_value (hex_data ) -> dict : print (f"原始数据: {hex_data} " ) separator = 'FF FF FF' hex_parts = hex_data.split(separator) print (f"去掉分隔符: {hex_parts} " ) hex_parts = hex_parts[:-1 ] print (f"删掉最后一个空串: {hex_parts} " ) cleaned_parts = [p.strip() for p in hex_parts] print (f"去掉两端空格: {cleaned_parts} " ) result = {} if len (cleaned_parts) > 0 : result['ip' ] = cleaned_parts[0 ] else : result['ip' ] = "" if len (cleaned_parts) > 1 : result['company' ] = cleaned_parts[1 ] else : result['company' ] = "" if len (cleaned_parts) > 2 : result['station' ] = cleaned_parts[2 ] else : result['station' ] = "" return result
1 2 3 4 5 6 7 8 9 10 11 input_value = self.get_input_value(hex_data) if not input_value: logger.error("输入不能为空" ) return "输入为空" ip = self.reverse_hex_to_text(input_value["ip" ], encoding='utf-8' ) company = self.reverse_hex_to_text(input_value["company" ], encoding='gbk' ) station = self.reverse_hex_to_text(input_value["station" ], encoding='gbk' ) logger.info(f"🔍 校验输入: IP={ip} , 公司={company} , 收费站={station} " )
1 2 3 4 5 原始数据: D0 A3 D1 E9 CE B4 CD A8 B9 FD 0 D 0 A 49 50 B2 BB C4 DC CE AA BF D5 FF FF FF 去掉分隔符: ['D0 A3 D1 E9 CE B4 CD A8 B9 FD 0D 0A 49 50 B2 BB C4 DC CE AA BF D5 ' , ''] 删掉最后一个空串: [' D0 A3 D1 E9 CE B4 CD A8 B9 FD 0 D 0 A 49 50 B2 BB C4 DC CE AA BF D5 '] 去掉两端空格: [' D0 A3 D1 E9 CE B4 CD A8 B9 FD 0 D 0 A 49 50 B2 BB C4 DC CE AA BF D5'] 结果:[' t7 .txt="校验未通过\r\n路段公司不\r\n能为空" ', ' t7 .pco=63488 ']
点击校验,核心功能完善结束。
下一步。
点击下一步,获取提示信息状态,结果符合预期则正常跳转,反之点击无效吧,不用搞什么花里胡哨的了。
2025 年 12 月 10 日
单片机发送数据给串口屏 — 淘晶驰串口屏资料中心 1.1.0-2025-12-04 09:17:37 文档
将一个变量或常量从串口发送出去。
每条数据发送出去后,添加帧尾结束符,Python程序读取比较方便。
1 2 3 4 5 6 7 8 9 10 prints t1.txt,30 printh ff ff ff prints t6.txt,30 printh ff ff ff prints t5.txt,30 printh ff ff ff page config_2
配置页,点击校验,监听,解析数据,校验数据(校验不通过,返回错误信息;校验通过,返回校验成功信息),下一步,跳转页面。
1 2 3 4 5 6 def test (hex_data ): print ("测试" ) hex_str = hex_data.replace(' ' , '' ) data_bytes = bytes .fromhex(hex_str) print (f"-----{data_bytes} -----" )
最后测试一遍接受串口屏发来的数据。
1 2 3 4 hex_str = hex_data.replace(' ' , '' )hex_parts = hex_data.split(' FF FF FF ' )
1 -----['65 02 09 00', '31 39 32 2E 31 36 38 2E 32 2E 37 35', 'D4 CB B3 C7 B9 AB CB BE', 'D4 CB B3 C7 CA D5 B7 D1 D5 BE FF FF FF']-----
1 2 3 4 5 6 7 8 9 10 11 12 13 @staticmethod def get_input_value (hex_data ) -> str : """获取输入框的值(这里用模拟值)""" hex_str = hex_data.replace(' ' , '' ) hex_parts = hex_data.split(' FF FF FF ' ) print (f"-----{hex_parts} -----" ) for part in hex_parts: print (f"数据含义: {part} " ) return ""
他妈的发送键值,发送的是触发按钮事件吗,把点击校验触发指令默认不接受,要不然点击后收不到接下来的配置页面输入文本内容了。
取消勾选点击校验->发送键值。
1 2 3 4 5 6 7 8 9 elif page_id == 2 and control_id == 11 : logger.info('点击校验' ) hex_data = self.get_serial_data() print (f"原始数据: {hex_data} " ) config = ConfigPage1Updater(hmi_connect) result = config.validate(self.hex_data) print (f"结果: {'成功' if result else '失败' } " )
取消发送键值的话,这个监听就判断不到点击校验按钮有没有被按到了,逻辑在这里没有通过。
需要考虑下两种方案,接受发送键值能否获取到输入内容;不接受发送键值又该如何让逻辑走通。
1 2 3 4 5 6 7 8 else :try : text = data.decode('utf-8' , errors='ignore' ).strip()if text: logger.info(f"文本内容: {text} " )except Exception as e: logger.info(f"无法解析数据格式: {e} " )
这里改一下,不是标准触摸事件,在这个串口屏下就只有一种可能,那就是校验文本输入。
返回个特殊值,返回 None 还不行。
返回一个对象,再根据返回数据类型判断是不是标准触摸事件,校验文本输入归为其他事件,正常调用。
1 2 3 4 return { 'type' : 'touch_event' , 'data' : touch_info, }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 def display_touch_listener (self ): """监听触摸事件并处理页面跳转""" try : result = self.listen_for_touch_event() if result is None : return event_type = result["type" ] data = result["data" ] if event_type == "touch_event" : self.handle_touch_event(self.hmi_connect, data) if event_type == "raw_data" : self.handle_other_event(self.hmi_connect, data) except Exception as e: logger.error(f"❌ 触摸监听出错: {e} " ) return
1 2 3 4 5 6 7 8 def handle_other_event (self, hmi_connect, data ): """处理非触摸事件""" logger.info('点击校验' ) config = ConfigPage1Updater(hmi_connect) result = config.validate(self.hex_data) print (f"结果: {'成功' if result else '失败' } " )
2025 年 12 月 9 日
重新优化一遍触摸监听模块。
控件发送的信号只有:页面id,控件id,按下/弹起,所有信号包括页面跳转都应该由Python脚本发送,而不应该绑定到控件上。
我研究下控件信号还有什么名堂,发送键值是什么意思。
他妈的,这就是将来Python脚本要做的,控制页面跳转 ,页面文本控件赋值 。
页面跳转实现:硬编码,监听指定页面id 下的按钮控件id,根据业务逻辑硬编码跳转至指定页面;
文本控件赋值:
淘晶驰资料中心 — 淘晶驰串口屏资料中心 1.1.0-2025-12-04 09:17:37 文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def send_command (self, command: str ) -> bool : """发送指令到串口屏""" try : if self.ser and self.ser.is_open: full_command = command.encode('gbk' ) + b'\xFF\xFF\xFF' self.ser.write(full_command) logger.debug(f"发送指令: {command} " ) time.sleep(0.1 ) return True else : logger.error("串口未连接" ) return False except Exception as e: logger.error(f"发送指令失败: {e} " ) return False
1 这样的Python发送指令程序,默认都是在所有控件刷新之后才执行,我要实现这样的指令在跳转页面后所有控件刷新之前执行,怎么实现,怎么改造Python代码
AI 没法交流。
1 command = f'{control_id} .txt="{escaped_text} "'
文本控件赋值,只能尝试以下两种方案里的一种:
跳转页面之前,跳转页面之前执行所有控件赋值,这个得看下上面的赋值命令能不能改,没有尝试过指定页面id下的控件id赋值的。
照旧,页面控件默认值全部清空,刷新慢就刷新慢吧。
怪了,为什么刷新慢呢。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def navigate_to_page (self, target_page: int ) -> bool : """跳转到指定页面""" try : if target_page == self.current_page: logger.debug(f"🔄 已在目标页面 {target_page} ,无需跳转" ) return True command = f"page {target_page} " success = self.send_command(command) if success: self.current_page = target_page logger.info(f"已跳转到页面 {target_page} " ) time.sleep(1 ) return success
他妈的谁写的代码,就是这里跳转页面之后,还休眠了一秒钟才继续执行的,,。正常执行控件内容赋值很快的。
还是得清空页面控件默认值,以前是用来做测试数据的,相当于用假数据填充完毕基本实现原型图来着。
1 首页 ——> 启动监听 ——> 监听串口屏触摸事件(页面id | 控件id | 事件) ——> 执行指令(跳转页面 | 返回数据)
1 CPU35 % 内存90 %(容量32 G|已用25 G|剩余17 G) 磁盘70 %(容量32 G|已用25 G|剩余17 G) 网络流量(上行1 M/s|下行1 M/s)
1 2 3 4 if not self.hmi_connect.navigate_to_page(0 ): logger.error("无法跳转到主页面" ) return
神经了,这代码,跳转所有页面都可以,就是不能跳转页面0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 2025 -12 -09 16 :44 :36 ,911 - INFO - 跳转至概览页2025 -12 -09 16 :44 :36 ,911 - INFO - 📊 生成模拟数据完成2025 -12 -09 16 :44 :36 ,918 - INFO - ✅ 概览页面更新完成: 26 /26 命令成功 (100 .0 %)2025 -12 -09 16 :44 :36 ,924 - INFO - 🕒[16 :44 :36 ] 收到数据: 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF2025 -12 -09 16 :44 :36 ,924 - INFO - 文本内容: 2025 -12 -09 16 :44 :36 ,934 - INFO - 🕒[16 :44 :36 ] 收到数据: 1 A FF FF FF2025 -12 -09 16 :44 :36 ,934 - INFO - 文本内容: 2025 -12 -09 16 :44 :36 ,936 - INFO - 🕒[16 :44 :36 ] 收到数据: 1 A FF FF FF2025 -12 -09 16 :44 :36 ,936 - INFO - 文本内容: 2025 -12 -09 16 :44 :37 ,001 - INFO - 🕒[16 :44 :37 ] 收到数据: 1 A FF FF FF2025 -12 -09 16 :44 :37 ,001 - INFO - 文本内容: 2025 -12 -09 16 :44 :37 ,002 - INFO - 🕒[16 :44 :37 ] 收到数据: 1 A FF FF FF2025 -12 -09 16 :44 :37 ,002 - INFO - 文本内容: 2025 -12 -09 16 :44 :37 ,004 - INFO - 🕒[16 :44 :37 ] 收到数据: 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF 1 A FF FF FF
搞不清楚为什么会出现这种问题。
用Python程序控制页面跳转,妈的返回首页后就无效了,跳转不成功但获取数据成功了。
不消耗时间了,暂时用控件执行跳转,Python只负责获取并返回数据。
1 2 3 4 if not self.hmi_connect.navigate_to_page("index" ): logger.error("无法跳转到主页面" ) return
改成这样。
1 2 3 4 5 6 7 8 9 10 if __name__ == "__main__" : config = MySQLConfig( host="localhost" , port=3306 , database="test" , username="root" , password="Dw990831" )
随便写个 MySQL 数据库配置测试类,连接数据库没问题。
1 2 3 4 5 6 7 8 9 10 if __name__ == "__main__" : manager = MySQLManager(MySQLConfig()) if manager.connect(): user_info = manager.execute_query("SELECT * FROM user" ) print (f"用户信息: {user_info} %" ) manager.close()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 def execute_query (self, query: str , params: tuple = None ) -> Optional [List [Dict ]]: """执行查询并返回结果""" if not self.connection: if not self.connect(): return None try : with self.connection.cursor(pymysql.cursors.DictCursor) as cursor: cursor.execute(query, params or ()) result = cursor.fetchall() return result except Exception as e: logger.error(f"❌ 查询执行失败: {e} " ) return None
1 2 3 user_info = manager.execute_query("SELECT * FROM user where age = 20" )print (f"用户信息: {user_info} %" )
执行数据库查询,结果如下。
1 2 3 4 C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\python.exe D:\Project\python\HMI\touchScreen\config\mysql_config.py 2025-12-09 18:03:05,662 - INFO - ✅ 已连接到MySQL数据库: localhost:3306/test 2025-12-09 18:03:05,664 - INFO - 🔌 MySQL连接已关闭 用户信息: [{'id' : 3, 'name' : '邓嘻嘻' , 'age' : 20, 'sex' : '男' , 'job' : '运维工程师' , 'current_page' : None, 'page_size' : None}]%
2025 年 12 月 5 日
今天务必把所有必须的 Python 程序全部编写运行并测试完毕。
罢了,今中午得去一趟调试顶棚灯,这程序谁爱写谁写去,看有时间再完善下吧,目前都是模拟数据没有从指定数据库中获取。
2025 年 12 月 4 日
他妈的刚发现电脑的USB转TTL模块怎么不亮了,这样接笔记本的串口屏也跟着亮不起来了对吧。
昨天下半前不整挺好的么,我拿着鼠标和转录模块的USB口调换一下,妈的现在连鼠标都动不了了,电脑USB口给这个插口搞坏掉了吧。
艹。
折腾了快一个小时,这个模块上有个黑色的滑块按钮,分别是用来开关USB转TTL模块电源的,开了就没事了。
用手机充电器也行,还是买个专用的 12V2A 电源适配器,四十块钱左右。
encode 选择 gbk 和 gb2312,这两个字体竟然有细微差别吗,选择 gbk 编码的汉字字体至少在模拟器和串口屏上显示更清晰点。
用手机充电器也行,还是买个专用的 12V2A 电源适配器,四十块钱左右。
十一点半,基本完善全部五个页面,接下来就是Python脚本了,今早听他们沟通结果应该是要调整串口屏尺寸大小,完事了还得写什么测试文档开发文档。
明天去车道干啥。。
2025 年 12 月 3 日
新增字库,指定字符,要不这字库文件加起来就有10MB,下载到串口屏都报错了。
1 File is too large for destination device.
报错:file is too large for destination device — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
数据库还没有拿到,先编写除了数据库连接以外的 Python 监听程序吧。
python出现PEP 8: E302 expected 2 blank lines, 问题和IndentationError:unexpected indent问题_pep 8: e302 expected 2 blank lines, found 1-CSDN博客
基本完善了首页指令收发逻辑。
启动监听。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 def main (): hmi_filler = HMIDataFiller(port='COM5' , baudrate=115200 ) try : if not hmi_filler.connect(): return if not hmi_filler.navigate_to_page(0 ): logger.error("无法跳转到主页面" ) return logger.info("开始更新页面数据..." ) success = hmi_filler.update_all_controls() if success: logger.info("数据更新完成" ) user_input = input ("是否启动定时更新?(y/n): " ) if user_input.lower() == 'y' : interval = int (input ("请输入更新间隔(秒): " ) or "30" ) hmi_filler.start_periodic_update(interval) else : logger.error("数据更新失败" ) except Exception as e: logger.error(f"程序执行出错: {e} " ) finally : hmi_filler.close()
今下午把所有页面基本写完,模拟数据也搞上,还可以进一步尝试下把 Python 程序给部署到服务器上,还没试过。
1 我有个问题还想问,就是现在本机编写的Python程序能够监听到本机串口屏,能发送信号到串口屏也能接受来自串口屏的信号,那么将来呢,将来在生产环境下,是不是得在连接串口屏的那台主机上把这套Python代码运行起来呢,思路是这样的吧。
docker 部署python项目(实战)_docker部署python项目-CSDN博客
1 CPU35 % 内存90 %(容量32 G|已用25 G|剩余17 G) 磁盘70 %(容量32 G|已用25 G|剩余17 G) 网络流量(上行1 M/s|下行1 M/s)
1 2 3 4 5 6 7 commands.append(f't8.txt="{services[0 ]["name" ]} "' ) status_text1 = f'{services[0 ]["status" ]} ' status_color1 = color_map.get(services[0 ]["status" ]) commands.append(f't25.txt="{status_text1} "' ) commands.append(f't25.pco={status_color1} ' )
2025 年 12 月 2 日
1 写了些测试页面,笔记本用转接模块连接串口屏,本地Python程序能监听到串口屏控件发来的触发信号,Python程序也能发送指令操作串口屏
1 你找找产品,我们有个触摸屏的软件,原来是普通web项目,要改成串口屏
串口屏开发应该选择什么编码?
编码格式
适用场景
优点
缺点
推荐指数
GB2312
简体中文环境
兼容性好,体积小
不支持繁体,字符集有限
⭐⭐⭐⭐
GBK
中文字符扩展
支持更多汉字,兼容GB2312
非国际标准
⭐⭐⭐⭐⭐
UTF-8
国际化项目
全球通用,支持所有语言
体积稍大,部分老设备兼容性差
⭐⭐⭐⭐
ASCII
纯英文环境
体积最小,兼容性最好
不支持中文
⭐⭐
Big5
繁体中文环境
台湾香港地区标准
不支持简体中文
⭐⭐
Shift-JIS
日文环境
日本地区专用
仅限日文项目
⭐
包图网-正版商用视频音乐素材库,AI设计图片|PPT模板|海报|背景元素,会员免费下载
千图网-免费在线设计图片素材网站-正版商用素材图库模板大全
ps快速修改尺寸和分辨率 超级简单版
妈的这个尺寸下的字体大小,最小字体高度也得是16,屏幕尺寸不大这字体显得就臃肿了,先按照这样的大小设置吧。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def send_command (self, command: str ) -> bool : """发送指令到串口屏""" try : if self.ser and self.ser.is_open: full_command = command.encode('gbk' ) + b'\xFF\xFF\xFF' self.ser.write(full_command) return True else : logger.error("串口未连接" ) return False except Exception as e: logger.error(f"发送指令失败: {e} " ) return False
1 2 3 4 5 2025 -12 -10 17 :19 :22 ,379 - ERROR - 💥 处理失败: list index out of range2025 -12 -10 17 :19 :22 ,383 - INFO - 🕒[17 :19 :22 ] 收到数据: 1 A FF FF FF2025 -12 -10 17 :19 :22 ,383 - INFO - 点击校验2025 -12 -10 17 :19 :22 ,383 - ERROR - 💥 处理失败: list index out of range2025 -12 -10 17 :19 :22 ,386 - INFO - 🕒[17 :19 :22 ] 收到数据: 1 A FF FF FF
又出现串口屏发来的特殊指令了。
1 2025 -12 -10 17 :24 :57 ,736 - INFO - 🕒[17 :24 :57 ] 收到数据: 1 A FF FF FF
校验结束返回校验结果,串口品那个自动相应信息,就是这么个信息被监听程序归为其他触摸指令,反复监听解析没有通过。
解决两个问题:
为什么变量无效呢?
1 return f"t7.txt=校验通过\n点击下一步"
1 return f't7.txt="校验通过\r\n点击下一步"'
这样也能正常换行,这里的编码暂时硬编码吧:
1 2 3 4 commands.append(f't7.txt="校验通过\r\n点击下一步"' ) commands.append(f't7.pco=1696' ) return commands
1 2 3 4 5 6 config = ConfigPage1Updater(self.hmi_connect) commands = config.validate(self.hex_data) print (f"结果:{commands} " ) for command in commands: self.hmi_connect.send_command(command)
那出现了特殊指令又该怎么解析呢?暂时不处理,要处理也是在这里添加代码:
1 2 3 4 5 6 7 if event_type == "touch_event" : self.handle_touch_event(self.hmi_connect, data) if event_type == "raw_data" : self.handle_other_event()
1C FF FF FF 赋值操作失败 — 淘晶驰串口屏资料中心 1.1.0-2025-12-10 10:22:10 文档
1A FF FF FF 变量名称无效 — 淘晶驰串口屏资料中心 1.1.0-2025-12-10 10:22:10 文档
当ip为空时,报错未按预期,是无效指令,其实三个文本输入竟然都不能为空,为空串口屏就发来无效指令。
00 FF FF FF 无效指令 — 淘晶驰串口屏资料中心 1.1.0-2025-12-10 10:22:10 文档
1 32 2 E 32 2 E 38 2 E 38 FF FF FF FF FF FF D4 CB B3 C7 CA D5 B7 D1 D5 BE
路段公司为空时,两个 FF FF FF 挨在一块儿了。
1 2 3 4 5 prints t1.txt,30 printh ff ff ff prints t6.txt,30 printh ff ff ff prints t5.txt,30
1 2 3 4 5 6 7 8 9 10 11 12 if (t1.txt!="" ) { prints t1.txt,30 printh ff ff ff }else if (t6.txt!="" ) { prints t6.txt,30 printh ff ff ff }else if (t1.txt!="" ) { prints t5.txt,30 }
这样发送之前判空,填写为空就不发送了,看下发送的数据格式指令是
1 2 3 4 from HMI.touchScreen.pages.monitor_page import MonitorPageUpdaterfrom HMI.touchScreen.pages.overview_page import OverviewPageUpdaterfrom HMI.touchScreen.pages.config_page_1 import ConfigPage1Updaterfrom HMI.touchScreen.pages.config_page_2 import ConfigPage2Updater
更新代码后,全部输入,出现报错:
1 输入: ['31 39 32 2E 31 36 38 2E 32 2E 37 35 FF FF FF' ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (t1.txt!="" ) { prints t1.txt,30 printh ff ff ff }if (t6.txt!="" ) { prints t6.txt,30 printh ff ff ff }if (t1.txt!="" ) { prints t5.txt,30 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 prints t1.txt,30 if (t1.txt!="" ) { printh ff ff ff } prints t6.txt,30 if (t6.txt!="" ) { printh ff ff ff } prints t5.txt,30 if (t5.txt!="" ) { printh ff ff ff }
最终版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 if (t1.txt!="" ) { prints t1.txt,30 printh ff ff ff }else { prints "" ,30 printh ff ff ff }if (t6.txt!="" ) { prints t6.txt,30 printh ff ff ff }else { prints "" ,30 printh ff ff ff }if (t5.txt!="" ) { prints t5.txt,30 }else { prints "" ,30 printh ff ff ff }
不对。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 if (t1.txt!="" ) { prints t1.txt,30 printh ff ff ff }else { printh ff ff ff }if (t6.txt!="" ) { prints t6.txt,30 printh ff ff ff }else { printh ff ff ff }if (t5.txt!="" ) { prints t5.txt,30 printh ff ff ff }else { printh ff ff ff }
这里的编码从一开始就错了,我为了从原始数据中获取十六进制数据中更省事,最后一条数据没有增加结束帧标志,导致现在解析数据混乱。
无论是否为空,都要有明显的结束帧,接下来解析数据的逻辑又要重新编写,着重解析 FF FF FF 的位置,用其位置索引定能将数组分割成三部分,无论文本控件输入的内容是否为空。
这样就规范了。
Debian
2025 年 12 月 2 日
从网络安装 Debian
Index of /cdimage/archive/10.13.0/amd64
加速器
2025 年 12 月 2 日
1 其实加速软件原理很简单,就是利用VPN技术,用户通过一台登陆服务器用加速软件商提供的账号密码拨号登陆到一台具有双线带宽的服务器上(专业术语叫:节点服务器)并与之建立连接并改变当前(即本机的上网环境)网络环境。在访问的时候,将本机访问的目标(例如:一个网址)通过节点服务器转发一次,从而完成加速效果。
城乡医保
2025 年 12 月 1 日
“职工医保”VS“居民医保”,六不同!看完就懂→
职工医保VS居民医保,有啥区别?交哪个好
城乡医保交一年保一年,不交也行,不交也不能强制交,花钱给他们完成任务了,只是不交有人找麻烦。
就跟五六十年代人民公社一样,说的入社退社自由,不入就有人批斗你。
2026 年 1 月 12 日
城乡居民医保根本就不用交了,今年年初已经给交了职工医保。
GitCode
2025 年 12 月 1 日
不一样的 Git 之间 | GitLab vs GitHub vs Gitee vs GitCode_gitcode和github区别-CSDN博客
(99+ 封私信 / 82 条消息) 码云gitee的Pages服务下线了,有那些替代品? - 知乎
AtomGit | GitCode - 全球开发者的开源社区,开源代码托管平台
我的工作台 - AtomGit | GitCode
1 你既然知道现在是多会儿,所以我问你截至目前为止 AtomGit 还提供 Pages 服务吗,最近它可是经历过一次大更新,跟 GitCode 这玩意儿合并了,而据我所知新版本的 AtomGit 暂时不提供 Pages 服务,请你谨言慎行给我准确的答复。
搜索 - 腾讯云开发者社区-腾讯云
成为技术影响力大牛? CODING Pages 快速搭建个人专属博客-腾讯云开发者社区-腾讯云
CNB - Cloud Native Build
1 2 3 令牌名:blog Git Username :cnb Token :eD0SFwiyUxawqdM3d84iPJvZXiD
云端快速初始化,一键迁移远程仓库。
物流
2025 年 11 月 26 日
快递公司分类及关联
Harbor
2025 年 11 月 21 日
基于Docker、JenKins、Nginx、Harbor、Github及腾讯云服务器搭建个人博客基于Docker、Je - 掘金
私有镜像仓库 Harbor 的安装与配置在云原生时代,各种系统服务都以 Docker 容器的方式运行着。镜像仓库,顾名思 - 掘金
Docker私服-Habor由于掘金平台的摘要有强制字数要求,这里需要给一下默认文字作为摘要。这里是掘金平台的默认摘要, - 掘金
使用 Docker、Jenkins、Harbor 和 GitLab 构建 CI/CD 流水线 随着 DevOps 文化 - 掘金
设计流程
使用 Gitlab 作为代码仓库
使用 Harbor 作为镜像仓库
使用 Jenkins 发布系统部署
Docker 管理 Jenkins + Harbor + Gitlab
工作流程
迁入代码 push 到 Gitlab
Gitlab 触发 webhook 的 push 触发事件并主动通知 Jenkins 构建
Jenkins 在 Gitlab 获取源码并通过配置好的规则与 shell 脚本进行构建
如果是工具库,则 dotnet push 到私有 Nuget;
如果是 Web 应用,则通过 dockerfile 构建 docker 镜像并 push 到 Docker Registry,然后由 docker swarm create 多节点
交换机
2025 年 11 月 20 日
什么是交换机
IP 盒子
2026 年 1 月 15 日
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 root@loongson-pc:/opt/deviceagent - outCommunicator: type: GBOutCommunicator options: serverIp: "192.168.2.34" serverPort: 9547 laneHex: "1401240121" certificationInfo: "Trawe" deviceAgents: "feeInfoBoard_01,alarm_01,trafficLight_01": type: feeInfoBoard options: type: ShanXiStdFeeInfoBoard portName: /dev/ttyS4 "barrierMachine_01": type: barrierMachine options: type: ShanXiXinTongIODevice inputIoNumber: -1 openIOBit: "0" closeIOBit: "1" needSimulatingInput: "False" ipAddress: 192.168.2.75 port: 502 "vehicleDetector_01": type: vehicleDetector options: type: ShanXiXinTongIODevice inputIoNumber: 6 needSimulatingInput: "False" ipAddress: 192.168.2.75 port: 502 "vehicleDetector_02": type: vehicleDetector options: type: ShanXiXinTongIODevice inputIoNumber: 7 needSimulatingInput: "False" ipAddress: 192.168.2.75 port: 502 "vehicleDetector_03": type: vehicleDetector options: type: ShanXiXinTongIODevice inputIoNumber: 5 needSimulatingInput: "False" ipAddress: 192.168.2.75 port: 502 "vehicleDetector_04": type: vehicleDetector options: type: ShanXiXinTongIODevice inputIoNumber: 4 needSimulatingInput: "False" ipAddress: 192.168.2.75 port: 502 "plateRecognizer_01": type: plateRecognizer options: type: ShanXiStdPlateRecognizer libraryPath: "./devlib/camera/zhongweiob/lpr.so" mediaUploadUrl: http://192.168.2.34:8080/pic/picImage
2026 年 1 月 13 日
1 2 3 4 5 6 7 1 .国标后台服务端ip 和端口2 .lanehex3 .唯一标识码4 .牌识图片http上传的url1 . 3 . 4 . 帮忙提供下吧
1 2 3 192.168.2.34:9528 Trawe http://192 .168 .2 .34 :8080 /axle/axlelmage
1 2 3 4 1 .国标后台服务端ip和端口,192.168 .2.34 :9528 2 .lanehex,1401 DD01263 .唯一标识码,Trawe4 .牌识图片http上传的url,http:// 192.168 .2.34 :8080 /axle/ axlelmage
明天中午正式环境测试,特微的也会在现场协助。
2026 年 1 月 12 日
1 今天看能不能跟孙工确认一下正式环境的测试,以及开道试用@回忆如初
2026 年 1 月 8 日
1 2 测试工具发的顶棚屏的控制命令能收到, 对接没问题; 不过, 控制顶棚牌的串口发了后没反应, 我再看看发送的命令, 或找厂家看看.
1 2 3 4 5 那今天先这样吧, 顶棚牌,车检器跟特微的对接没问题 顶棚牌的串口协议可能要另外时间调一下 牌识的抓拍命令跟特微对接没问题, 但出车牌可能要车辆 小黄人的, 先拿ip , 然后进网页看看怎么配置国标协议的服务端和端口, 然后也需要车来测试.
1 2 3 4 费显联调正常;IO输入接口正常;折叠屏,牌识跟特微的对接没问题; 折叠屏的串口协议需要另外时间再调,目前向串口发命令后没反应,得检查下命令或者问问厂家; 牌识的抓拍指令正常,用牌识纸不好抓车牌,后续调试最好过车抓拍测试; 联调IO,IO的控制命令跟国标不一致,待解决
多问两句,这小黄人还有折叠屏就不用调了。
1 现场折叠屏串口还没接,现在是用桌子上的小键盘控制的,后续应该会转成网口,这个暂时不用调了
调试进度。
1 2 3 栏杆: 国标控制命令问题 牌识: 没车识别不到车牌,需确认图片http接口 小黄人: 没条件测试
2026 年 1 月 6 日
[linux vi全选并复制粘贴 - 腾讯云开发者社区 - 腾讯云](https://cloud.tencent.com/developer/information/linux vi全选并复制粘贴)
Linux Vim撤销和恢复撤销快捷键-腾讯云开发者社区-腾讯云
1 cd /opt/ scaner/lib/ config
1401DD0114
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 [LaneId] laneId =1401 DD0126[Log] ManageLogMode =0 DelJudgeHour =2 [Factory] Enable =1 WSServerPort =9902 [Env] Test =0 [HttpCfg] PicImageUrl =http://127.0 .0.1 :8080 /pic/picImage[Holiday] holidaymode =1 holidaytimer =6 NeedAuth =0 PaperTicketHours =6 [LaneType] NoBody =1 LaneType =2 [CardSettings] CardAlarmThres1 =10 CardAlarmThres2 =10 CardAlarmThres3 =10 [Device] MaxCardNum =200 [Dip] ip =https://10.14 .210.189 :3004 /[Ws] monitorurl =ws://10.14 .210.188 :16660 /charges-lane-monitor/monitor/lane?laneId=BakMode =1 [IcReader] ReaderCnt =2 libPath1 =/opt/scaner/lib/libReaderApi_kezhuan.socom1 =/dev/ttysWK23libPath2 =/opt/scaner/lib/libReaderApi_kezhuan.socom2 =/dev/ttysWK30libPath3 =/opt/scaner/lib/libReaderApi_kezhuan.socom3 =/dev/ttysWK31Reader3 =/dev/ttysWK31IndexReader1 =1 PSAMSockID1 =1 IndexReader2 =2 PSAMSockID2 =1 [IssuanceMode] throwcardmode =0 issuancemode =4 [Mode] RobotMode =0 [MobilePay] EnableAutoCancelOder =0 EnableShowDetail =1 [CashPay] EnableShowDetail =1 [CustomOption] WaitInit =0 [GUI] FastInputPlate =[Screen] InnerScreenIndex =0 ExScreenIndex =1 [Log] [Server] ListenCnt = 2 ListenPort1 = 9547 ListenPort2 = 8085 [SysParams] DevType =5 DevList =E2|E6|E9|EABusiServIp =192.168 .131.135 BusiServPort =9547 CertInfo =Trawe[ModuleSwitch] CardReader =1 HardwareApp =1 [LaneInfo] CertInfo =TraweHardwareControlUrl =ws://10.0 .23.75 :9091 OutFieldUrl =ws://10.0 .23.75 :9209 [Coil] CoilIndex1 =4 CoilIndex2 =2 CoilIndex3 =3 [TopBoard] DevType =2 IP =172.32 .204.13 Port =5200 LoginShowText =ETC/自助|山西高速欢迎您LogoutShowText =车道关闭|山西高速欢迎您[FeeBoard] FeeBoardIndex1 =0 FeeBoardIndex2 =1 EnableClearFeeBoardCtrl =0 DevType =1 [LaneClose] DevType =1 IP =172.32 .204.14 Port =2929 [Funtion] CacheRegVehTypeOverTimeMin =30 [DriveCarLight] com =/dev/ttysWK31BaudRate =9600 [Weight] DevType =2 com =/dev/ttyUSB3BaudRate =9600 Library =./lib/devlib/weightctrl/libWtDevDll.soProtocolType =0 [MobilePay] DevType =1 PayUrl =http://10.14 .3.227 :8031 /pay.htmDevNo =ADAAAACYGLaneNo =54 ExStationNo =1422101 [Printer] UpPrinterIndex =1 DownPrinterIndex =2 [StdDev] PreUploadTailCaptureResult =1
2026 年 1 月 5 日
盒子问题解决了,改成自动配置再重新手动配置下,要不紊乱了。
1 2 3 4 5 6 7 8 9 以太网适配器 以太网 3 : 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::e92a:234:e120:5608%20 IPv4 地址 . . . . . . . . . . . . : 192.168.1.228 子网掩码 . . . . . . . . . . . . : 255.255.255.0 IPv4 地址 . . . . . . . . . . . . : 192.168.2.11 子网掩码 . . . . . . . . . . . . : 255.255.255.255 默认网关. . . . . . . . . . . . . : 192.168.2.1
2025 年 12 月 12 日
1 @SZH 折叠屏的部标服务端,要配置为ip 盒子的ip 和端口,端口可以配9901
2025 年 12 月 5 日
1 sudo chown loongson:loongson /home/ loongson/package/
1 sudo chown root:root /home/ loongson/package/
1 dpkg -i ./i386-runtime-base_1.2 .1 ~20230714 .lnd.1 _loongarch64.deb
1 tar -zxvf lat-new -c4055e9.tar.gz
1 export LD LIBRARY_PATH =`pwd`:$LD_LIBRARY_PATH
2025 年 11 月 27 日
1 sudo systemctl status ssh
**如果看到 Unit ssh.service not found**:说明系统未安装SSH服务器。需要安装:
1 2 sudo apt update sudo apt install openssh-server
https://mirrors.aliyun.com/ubuntu-ports/pool/main/o/openssh/
ubuntu-ports-pool-main-o-openssh安装包下载_开源镜像站-阿里云
Index of /pool/main/o/openssh
银河麒麟桌面操作系统V10(SP1)离线升级SSH(OpenSSH)服务_麒麟系统离线安装ssh-CSDN博客
1 2 sudo apt update sudo apt install net-tools
1 ssh loongson@192.168.1.112
网工必懂!路由器、光猫、交换机三大设备大揭秘,区别你分得清吗?-腾讯云开发者社区-腾讯云
分不清路由器、交换机、光猫的概念,一文带你迅速搞懂!
光猫路由器傻傻分不清?看完这篇稳如老狗
分不清路由器、交换机、光猫的概念,一文带你迅速搞懂!-阿里云开发者社区
2025 年 11 月 26 日
麒麟服务器操作系统–网络配置的五种方式_麒麟系统配置网卡ip地址-CSDN博客
2025 年 11 月 25 日
本机网段:192.168.2.209
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 C:\WINDOWS\system32>ssh root@192.168.2.11 The authenticity of host '192.168.2.11 (192.168.2.11)' can't be established. ED25519 key fingerprint is SHA256:wp0SoWD7JGL0Ce2wZcmRpRROghrusveXUGXs+Kj1ex4. This key is not known by any other names. Are you sure you want to continue connecting (yes/no/[fingerprint])? y Please type ' yes ', ' no' or the fingerprint: yes Warning: Permanently added ' 192.168.2.11' (ED25519) to the list of known hosts. root@192.168.2.11' s password: Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.70-00002-g5d231ff aarch64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage This system has been minimized by removing packages and content that are not required on a system that users do not log into. To restore this content, you can run the 'unminimize' command . Last login: Tue Nov 25 13:08:34 2025
查看已识别的串口设备。
1 2 3 4 5 6 7 8 9 10 11 12 13 root@imx8mp:~ /dev/tty /dev/tty19 /dev/tty3 /dev/tty40 /dev/tty51 /dev/tty62 /dev/ttyp6 /dev/ttyS2 /dev/ttysWK22 /dev/tty0 /dev/tty2 /dev/tty30 /dev/tty41 /dev/tty52 /dev/tty63 /dev/ttyp7 /dev/ttyS3 /dev/ttysWK23 /dev/tty1 /dev/tty20 /dev/tty31 /dev/tty42 /dev/tty53 /dev/tty7 /dev/ttyp8 /dev/ttysWK00 /dev/ttysWK30 /dev/tty10 /dev/tty21 /dev/tty32 /dev/tty43 /dev/tty54 /dev/tty8 /dev/ttyp9 /dev/ttysWK01 /dev/ttysWK31 /dev/tty11 /dev/tty22 /dev/tty33 /dev/tty44 /dev/tty55 /dev/tty9 /dev/ttypa /dev/ttysWK02 /dev/ttysWK32 /dev/tty12 /dev/tty23 /dev/tty34 /dev/tty45 /dev/tty56 /dev/ttymxc1 /dev/ttypb /dev/ttysWK03 /dev/ttysWK33 /dev/tty13 /dev/tty24 /dev/tty35 /dev/tty46 /dev/tty57 /dev/ttyp0 /dev/ttypc /dev/ttysWK10 /dev/ttyUSB0 /dev/tty14 /dev/tty25 /dev/tty36 /dev/tty47 /dev/tty58 /dev/ttyp1 /dev/ttypd /dev/ttysWK11 /dev/tty15 /dev/tty26 /dev/tty37 /dev/tty48 /dev/tty59 /dev/ttyp2 /dev/ttype /dev/ttysWK12 /dev/tty16 /dev/tty27 /dev/tty38 /dev/tty49 /dev/tty6 /dev/ttyp3 /dev/ttypf /dev/ttysWK13 /dev/tty17 /dev/tty28 /dev/tty39 /dev/tty5 /dev/tty60 /dev/ttyp4 /dev/ttyS0 /dev/ttysWK20 /dev/tty18 /dev/tty29 /dev/tty4 /dev/tty50 /dev/tty61 /dev/ttyp5 /dev/ttyS1 /dev/ttysWK21
通常,系统串口名称如 /dev/ttyS0, /dev/ttyS1(原生串口)或 /dev/ttyUSB0, /dev/ttyUSB1(USB转串口)。您需要查看这些设备哪个存在。
拔掉插在 ip 盒子上的顶棚灯转USB串口线,再次执行命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 root@imx8mp:~ /dev/tty /dev/tty19 /dev/tty3 /dev/tty40 /dev/tty51 /dev/tty62 /dev/ttyp6 /dev/ttyS2 /dev/ttysWK22 /dev/tty0 /dev/tty2 /dev/tty30 /dev/tty41 /dev/tty52 /dev/tty63 /dev/ttyp7 /dev/ttyS3 /dev/ttysWK23 /dev/tty1 /dev/tty20 /dev/tty31 /dev/tty42 /dev/tty53 /dev/tty7 /dev/ttyp8 /dev/ttysWK00 /dev/ttysWK30 /dev/tty10 /dev/tty21 /dev/tty32 /dev/tty43 /dev/tty54 /dev/tty8 /dev/ttyp9 /dev/ttysWK01 /dev/ttysWK31 /dev/tty11 /dev/tty22 /dev/tty33 /dev/tty44 /dev/tty55 /dev/tty9 /dev/ttypa /dev/ttysWK02 /dev/ttysWK32 /dev/tty12 /dev/tty23 /dev/tty34 /dev/tty45 /dev/tty56 /dev/ttymxc1 /dev/ttypb /dev/ttysWK03 /dev/ttysWK33 /dev/tty13 /dev/tty24 /dev/tty35 /dev/tty46 /dev/tty57 /dev/ttyp0 /dev/ttypc /dev/ttysWK10 /dev/tty14 /dev/tty25 /dev/tty36 /dev/tty47 /dev/tty58 /dev/ttyp1 /dev/ttypd /dev/ttysWK11 /dev/tty15 /dev/tty26 /dev/tty37 /dev/tty48 /dev/tty59 /dev/ttyp2 /dev/ttype /dev/ttysWK12 /dev/tty16 /dev/tty27 /dev/tty38 /dev/tty49 /dev/tty6 /dev/ttyp3 /dev/ttypf /dev/ttysWK13 /dev/tty17 /dev/tty28 /dev/tty39 /dev/tty5 /dev/tty60 /dev/ttyp4 /dev/ttyS0 /dev/ttysWK20 /dev/tty18 /dev/tty29 /dev/tty4 /dev/tty50 /dev/tty61 /dev/ttyp5 /dev/ttyS1 /dev/ttysWK21
这个差别,这就是顶棚灯串口设备路径了:
2025 年 11 月 20 日
IP机顶盒_百度百科
(99+ 封私信 / 82 条消息) 公网ip盒子? - 知乎
Figma
2025 年 11 月 18 日
Home – Figma
没设计也能很漂亮,非常适合独立开发:Trae + 飞个马MCP 因为团队规模比较小,没有专门的设计师,就尝试使用Trae - 掘金
Introduction | Developer Docs
1 figd_HoRi7 tW3 q5 MlBxcoxP5 N3 UUVBERHSiAEtfXcMH9 x
模型上下文协议(MCP) - 文档 - TRAE CN
Node 版本过低,得重新下载新版本。
1 2 3 4 5 6 7 8 9 10 D: \softWare\nvm\nvm\v18.16.1 \node_cache\_npx\e05028111420be70\node_modules\sharp\lib \sharp.js:120 throw new Error (help.join ( ^Error: Could not load the "sharp" module using the win32-x64 runtime Possible solutions: - Please upgrade Node.js: Found 16.19 .0 Requires ^18.17 .0 || ^20.3 .0 || >=21.0 .0 - Consult the installation documentation:
又出问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 D:\softWare\nvm\nvm\v18.16.1\node_cache\_npx\e05028111420be70\node_modules\sharp\lib\sharp.js:120 throw new Error(help.join('\n' )); ^ Error: Could not load the "sharp" module using the win32-x64 runtime Possible solutions: - Ensure optional dependencies can be installed: npm install --include=optional sharp - Ensure your package manager supports multi-platform installation: See https://sharp.pixelplumbing.com/install - Add platform-specific dependencies: npm install --os=win32 --cpu=x64 sharp - Consult the installation documentation: See https://sharp.pixelplumbing.com/install at Object.<anonymous> (D:\softWare\nvm\nvm\v18.16.1\node_cache\_npx\e05028111420be70\node_modules\sharp\lib\sharp.js:120:9) at Module._compile (node:internal/modules/cjs/loader:1706:14) at Object..js (node:internal/modules/cjs/loader:1839:10) at Module.load (node:internal/modules/cjs/loader:1441:32) at Function._load (node:internal/modules/cjs/loader:1263:12) at TracingChannel.traceSync (node:diagnostics_channel:328:14) at wrapModuleLoad (node:internal/modules/cjs/loader:237:24) at Module.require (node:internal/modules/cjs/loader:1463:12) at require (node:internal/modules/helpers:147:16) at Object.<anonymous> (D:\softWare\nvm\nvm\v18.16.1\node_cache\_npx\e05028111420be70\node_modules\sharp\lib\constructor.js:10:1) Node.js v22.21.1
1 npm install --include=optional sharp
1 npm install --os=win32 --cpu=x64 sharp
怎么还是报错。。
Docker
2025 年 12 月 3 日
1 WORKDIR 工作目录,是容器内部的工作目录,还是宿主机?
WORKDIR 的作用范围
指令
作用范围
示例
效果
WORKDIR
容器内部
WORKDIR /app
设置容器内工作目录
-v 挂载
宿主机↔容器
-v /host:/container
目录映射
COPY
宿主机→容器
COPY . .
文件复制
-w 参数
覆盖WORKDIR
-w /newdir
运行时设置工作目录
1 我不明白啊,根据镜像文件构建容器,那这个容器内部的目录结构是什么样子,我完全没概念。
基础镜像的目录结构
以 python:3.9-slim为例,它内部的目录结构是这样的:
1 2 3 4 5 6 7 8 9 10 11 / (根目录) ├── bin/ (可执行文件) ├── etc/ (配置文件) ├── home/ (用户目录) ├── root/ (root用户目录) ├── tmp/ (临时文件) ├── usr/ (用户程序) │ ├── bin/ (用户命令) │ └── local / (本地安装程序) ├── var / (可变数据) └── opt/ (可选应用软件)
1 都说Dockerfile镜像文件第一行必须是From 指定根据哪个镜像构建,那到底应该根据哪个镜像构建呢,这里编码有什么名堂吗,基于不同的镜像构建又有什么区别?
基础镜像的选择策略。
官方镜像 vs 非官方镜像
1 2 3 4 5 6 7 8 FROM python:3.9 -slimFROM node:16 -alpineFROM nginx:latestFROM someuser/random-imageFROM unknown-registry/app
不同标签的区别
1 2 3 4 5 6 7 8 9 FROM python:3.9 FROM python:3.9 -slim FROM python:3.9 -alpine FROM node :16 FROM node :16-slim FROM node :16-alpine
📊 主流基础镜像对比
镜像类型
大小
特点
适用场景
示例
完整版
300MB-1GB
包含完整工具链
开发环境、需要编译
python:3.9
精简版
100-300MB
只含运行时
生产环境
python:3.9-slim
Alpine版
5-100MB
极简、安全
微服务、资源敏感
python:3.9-alpine
Distroless
20-50MB
无shell、最安全
安全要求高的生产
gcr.io/distroless/python3
2025 年 12 月 1 日
Docker入门到实践(一)docker简介和安装docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及 - 掘金
2025 年 11 月 21 日
基于Docker、JenKins、Nginx、Harbor、Github及腾讯云服务器搭建个人博客基于Docker、Je - 掘金
2025 年 11 月 20 日
查找并删除特定镜像。
1 docker images | grep "nginx" | awk '{print $3}' | xargs docker rmi
docker images:列出所有镜像
grep "nginx":过滤出包含”nginx”的行
awk '{print $3}':提取第三列(镜像ID)
xargs docker rmi:将镜像ID作为参数传递给docker rmi删除
xargs命令从标准输入读取数据,并将这些数据作为参数传递给指定的命令。在上面的命令中,它用于将前一个命令(如awk、grep等)输出的结果(通常是多个ID)作为参数传递给docker命令(如rmi、stop、rm等)。
这样可以避免手动逐个处理,实现批量操作 。
1 2 3 4 5 6 7 8 9 10 11 docker images | grep "nginx" | awk '{print $3}' | xargs docker rmi docker ps -q | xargs docker stop docker ps -a | grep "Exited" | awk '{print $1}' | xargs docker rm docker ps --format "table {{.Names}}\t{{.Ports}}" | grep "80"
Docker常用命令大全:一篇文章让你掌握所有技巧-腾讯云开发者社区-腾讯云
管道操作,批量操作,条件过滤与格式化,设置别名和快捷命令,脚本自动化管理,常见问题排查命令……
组合命令和高效技巧,等今后用到了再过头来总结吧。
2025 年 11 月 19 日
Linux K8S(Kubernetes)常用命令一个完备的分布式系统支撑平台,具有完备的集群管理能力,多扩多层次的安全 - 掘金
开发运维们,肯巴尔斯(K8s)驾到。对于K8s这种涉及领域广、知识面杂的技术,一上来就想抠细节、要吃透,多少有点盲目。本 - 掘金
最详细的 K8S 学习笔记总结(2021最新版)虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集 - 掘金
2025 年 11 月 18 日
有哪些常见的Docker容器操作命令?掌握这些Docker命令,让容器管理事半功倍-腾讯云开发者社区-腾讯云
Docker入门到实践(三)Dockerfile解析与镜像制作在上一篇文章中已经介绍了 docker 常用命令的讲解, - 掘金
最详细的 K8S 学习笔记总结(2021最新版)虽然 Docker 已经很强大了,但是在实际使用上还是有诸多不便,比如集 - 掘金
下午重温了监测系统项目架构,目前需要学习的主要是 Docker,串口屏。
Docker命令可以按功能分为五大类:
镜像管理命令 :pull、push、build、images、rmi等
容器生命周期命令 :run、start、stop、rm、exec等
网络管理命令 :network create、network ls等
存储管理****命令 :volume create、volume ls等
系统信息命令 :info、stats、system等
远程调试
2025 年 11 月 24 日
周五调IO卡,自己鼓捣了一下午都没能ping通,晚上七点半才蹭车回到家,周六还得去一趟协助调试顶棚灯。
周六,中午十二点半起身出发,一点钟开始调试,他妈的一直到晚八点钟才作罢,调试的结果还不在预期,浪费我宝贵的周末时间。
周日休息。
周一。
2025 年 11 月 21 日
周三,费显调试结束,晚六点后离开前才确认声光报警有问题。
周四,调IO调不了,反复确认IO卡不是串口就是网口,就是网口,掰扯了三天总算罢休,中午不调了,得等之后再调试IO卡和顶棚灯。
周五,不清楚今中午还能调什么。
2025 年 11 月 20 日
中午回去得取个邮政快递,接下来的安排基本跟昨天一样,希望今天中午的调试工作能顺利完成吧,就能空余出时间来由自己折腾。
2025 年 11 月 19 日
早上十点钟下楼,回家里躺一会儿,煮面吃,十二点钟打个车子去车道。
1 2 3 4 5 6 7 8 IO读 发送到设备:01 02 00 00 00 08 79 CC 01 02 00 C8 00 08 F8 32 设备回复:01 02 01 02 20 49,第四个字节(02)是返回的设备IO状态 IO写 发送到设备:01 05 00 00 FF 00 8C 3A,第四个字节(00)表示第一位,第N位=N-1,第五(FF)表示高电平,(00)表示低电平。 01 05 00 00 FF 00 8C 3A 01 05 00 64 00 00 8C 15
1 @matty 现场恢复后测过了,费显正常,但声光报警不工作,之后他们得检查下
下午六点多钟蹭车回单位,坐电梯直接上一层大厅回家。
2025 年 11 月 18 日
自上周三开始,周五、周六、周日、周一各跑了一趟去车道协助远程调试云收费系统,连续几天都没睡过安稳的午觉。
周三跟着维修人员,中午用串口线调试费用显示器,晚六点前回到单位,他们还发了个动态库给我。
周四在工位坐了一天,下午又接到通知让周五跟他们一块儿去车道现场,周五从早去到现场一直到晚六点半才回单位,直接回家了。
周五就没有调试任务,得周末才开始调。
周六,早十点钟打车到车道现场,一直到下午快六点钟才调试结束,接内网看ETC工控机ip搞出了一堆破事,调试效率太低。
周日,中午一点钟临时协商好去车道现场,把刚买回的键盘取到手后就能配合调试,结果一搞就到了晚八点钟才回,车牌识别还没测完。
周一,早十一点钟打个车子现场,半小时后封车道协调完毕,中午十二点去餐厅吃了顿饱饭,两点前结束车牌识别调试,调试费额显示器的时候因为串口线有问题,从两点半折腾到下午四点半才确定是芯片老旧的问题,买根新线再试应该没问题。
周二,估计不去了,妈的昨晚又给我发消息问今天能不能测,新线上午到不了就周三调试,我估摸着肯定到不了了,京东快递撑死了一天内给送到,得今天晚些甚至明天早上才能取到了。
亲测有效!WIN10系统PL2303 USB转串口驱动兼容问题解决指南-CSDN博客
1 接下来要调io ,需要一块铁板压地感,有时垃圾斗就可以,最好一块大一点的铁,比如栏杆机的门,或机箱的侧面铁板之类的。
单片机
2025 年 11 月 24 日
什么是单片机?
1 单片机(Single - Chip Microcomputer )是一种集成电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU 、随机存储器RAM 、只读存储器ROM 、多种I / O 口和中断系统、定时器/ 计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A / D 转换器等电路)集成到一块硅片上构成的一个小而完善的微型计算机系统,在工业控制领域广泛应用。从上世纪80 年代,由当时的4 位、8 位单片机,发展到现在的300 M 的高速单片机。
1 单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上。相当于一个微型的计算机,和计算机相比,单片机只缺少了I / O 设备。概括的讲:一块芯片就成了一台计算机。它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件。同时,学习使用单片机是了解计算机原理与结构的最佳选择。
什么是单片机?它由哪几部分组成?组成、特点与发展趋势解读
单片机的应用领域。
由于单片机具有体积小、功耗低、可靠性高、开发方便等特点,因此被广泛应用于各个领域:
1. 智能仪表 :如电能表、水表、气表等,用于实现数据的采集、处理和显示。
2. 实时测控 :如温度控制、压力控制等工业测控系统。
3. 通讯设备 :如手机、无线对讲机等通讯设备中,用于实现信号的处理和传输。
4. 导航系统 :如GPS导航系统,用于实现定位和导航功能。
5. 家用电器 :如空调、冰箱、洗衣机等家用电器中,用于实现智能化控制和节能管理。
1 串口屏开发需要用到 USART HMI 编辑器,那么单片机开发呢,常用的编辑器有哪些?
单片机开发的核心是集成开发环境(IDE) ,它把代码编辑、编译、调试、烧录等功能集成在一起,下面这个表格汇总了不同单片机常用的主流IDE,方便你快速了解。
单片机系列/架构
主流IDE选择
STM32 (ARM Cortex-M)
STM32CubeIDE , Keil MDK-ARM , IAR Embedded Workbench
ESP32/ESP8266
ESP-IDF , Arduino IDE , PlatformIO (支持多种框架)
51单片机
Keil C51
PIC单片机
MPLAB X IDE
AVR单片机
Microchip Studio (原Atmel Studio) , Arduino IDE
嵌入式开发_百度百科
一个典型的嵌入式系统通常包括硬件和软件两部分:
硬件 :以嵌入式微处理器 (如ARM Cortex-M系列芯片)为核心,配以存储器、输入/输出设备及电源管理等。
软件 :包括可选的嵌入式操作系统 (如FreeRTOS、Linux)和专用的应用程序 ,这些软件通常被固化在存储芯片中。
串口屏
2025 年 12 月 4 日
基本通信协议格式。
指令格式
1 2 3 4 5 6 7 # 基本格式:指令 + 结束符"指令内容\xFF\xFF\xFF" # 示例:"page 1\xFF\xFF\xFF" # 页面切换"t0.txt=\"Hello World\"\xFF\xFF\xFF" # 设置文本"j0.val=50\xFF\xFF\xFF" # 设置进度条值
通信方向
1 2 Python程序 → 串口屏:发送控制指令 串口屏 → Python程序:发送触摸事件、传感器数据等
📋 完整协议规范
下行协议(Python → 串口屏)
页面控制指令
1 2 3 4 5 6 # 页面跳转"page 0\xFF\xFF\xFF" # 跳转到页面0 "page main\xFF\xFF\xFF" # 跳转到名为main的页面 # 页面刷新"ref 0\xFF\xFF\xFF" # 刷新页面0
控件操作指令
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # 文本控件"t0.txt=\"温度:25℃\"\xFF\xFF\xFF" # 设置文本内容"t1.txt=\"湿度:60%\"\xFF\xFF\xFF" # 进度条/仪表控件 "j0.val=75\xFF\xFF\xFF" # 设置进度条值(0 -100 )"z0.val=50\xFF\xFF\xFF" # 设置仪表值 # 按钮控件"b0.txt=\"确定\"\xFF\xFF\xFF" # 设置按钮文本"b0.bco=63488\xFF\xFF\xFF" # 设置按钮背景色(RGB565) # 显示/隐藏控件"vis t0,1\xFF\xFF\xFF" # 显示文本控件t0"vis b1,0\xFF\xFF\xFF" # 隐藏按钮b1
系统指令
1 2 3 4 5 6 7 8 9 # 背光控制"dim=100\xFF\xFF\xFF" # 背光亮度100 %"sleep=0\xFF\xFF\xFF" # 禁止休眠 # 声音提示"beep\xFF\xFF\xFF" # 蜂鸣器响一声 # 系统重启"restart\xFF\xFF\xFF" # 重启串口屏
上行协议(串口屏 → Python)
触摸事件格式
1 2 3 4 5 6 7 8 # 触摸按下事件:65 PP CC 01 FF FF FF # 触摸释放事件:65 PP CC 00 FF FF FF # 其中: # 65 : 固定头(触摸事件) # PP: 页面ID # CC: 控件ID # 01 /00 : 状态(01 =按下, 00 =释放)
数据上报格式
1 2 3 4 # 控件值变化上报"t0.txt=\"新值\"\xFF\xFF\xFF" # 文本内容变化"j0.val=50\xFF\xFF\xFF" # 进度条值变化"n0.val=123\xFF\xFF\xFF" # 数值变化
2025 年 12 月 1 日
怪不得本机 Python 监听程序失效,在编辑界面的按钮按下事件里勾选发送键值 选项,模拟器在用户MCU输入 选项下的串口配置中启动。
这样在模拟器点击按钮后就能接收到返回的数据,如图所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 def advanced_button_listener (): """监听按钮点击事件的完整程序""" try : ser = serial.Serial('COM4' , 115200 , timeout=1 ) print ("🎯 按钮监听程序已启动" ) print ("📡 监听COM4,等待COM3的模拟器信号" ) print ("请在模拟器中点击配置了'触摸发送'的按钮" ) print ("按Ctrl+C停止监听\n" ) print ("-" * 60 ) receive_count = 0 while True : if ser.in_waiting > 0 : data = ser.read(ser.in_waiting) receive_count += 1 current_time = datetime.now().strftime("%H:%M:%S" ) print (f"\n🕒 [{current_time} ] 第{receive_count} 次收到数据:" ) hex_data = ' ' .join([f'{b:02X} ' for b in data]) print (f"🔢 原始数据: {hex_data} " ) try : text_utf8 = data.decode('utf-8' , errors='ignore' ) text_gb = data.decode('gb2312' , errors='ignore' ) clean_utf8 = '' .join(c if 32 <= ord (c) <= 126 else f'[{ord (c):02X} ]' for c in text_utf8) clean_gb = '' .join(c if 32 <= ord (c) <= 126 else f'[{ord (c):02X} ]' for c in text_gb) if clean_utf8.strip(): print (f"📝 UTF-8文本: {clean_utf8} " ) if clean_gb.strip() and clean_gb != clean_utf8: print (f"📝 GB2312文本: {clean_gb} " ) except Exception as e: print (f"❌ 解码错误: {e} " ) if len (data) >= 6 and data[0 ] == 0x65 : page_id = (data[1 ] << 8 ) | data[2 ] control_id = (data[3 ] << 8 ) | data[4 ] state = data[5 ] if state == 0x01 : print (f"🟢 按钮按下! 页面{page_id} 控件{control_id} " ) elif state == 0x00 : print (f"🔴 按钮释放! 页面{page_id} 控件{control_id} " ) else : print (f"❓ 未知状态: {state:02X} " ) if b'button' in data.lower() or b'click' in data.lower(): print ("🎯 检测到按钮相关指令!" ) print ("-" * 50 ) time.sleep(0.05 ) except KeyboardInterrupt: print (f"\n🛑 监听结束,共收到 {receive_count} 次数据" ) except Exception as e: print (f"❌ 错误: {e} " ) finally : if 'ser' in locals () and ser.is_open: ser.close() print ("🔒 串口已关闭" )
1 2 3 4 🕒 第3次收到数据: 🔢 原始数据: 65 00 07 01 FF FF FF 📝 UTF-8文本: e ❓ 未知状态: FF
还得优化下 Python 对串口发来指令的分析。
1 2 3 4 5 6 7 8 9 10 Traceback (most recent call last): File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_pep_669_tracing.py" , line 238, in py_start_callback if not is_thread_alive(thread): ~~~~~~~~~~~~~~~^^^^^^^^ File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydev_bundle\pydev_is_thread_alive.py" , line 18, in is_thread_alive return t.isAlive() ^^^^^^^^^ AttributeError: 'ReaderThread' object has no attribute 'isAlive' . Did you mean: 'is_alive' ? Traceback (most recent call last): File "D:\dev\Pycharm\plugins\python-ce\helpers\pydev\_pydevd_bundle\pydevd_pep_669_tracing.py" , line 238, in
PyCharm 调试器内部代码使用了旧的线程方法名 isAlive(),但新版本Python中线程对象使用 is_alive()。
解决方案:以普通模式运行,不要使用调试模式,直接点击运行按钮。
妈的。
完整的触摸事件监听程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import serialimport timefrom datetime import datetimedef parse_touch_data (data ): print ("接收到的数据:" + str (data)) if len (data) >= 7 and data[0 ] == 0x65 and data[-3 :] == b'\xFF\xFF\xFF' : print ("数据格式正确,开始解析..." ) page_id = data[1 ] control_id = data[2 ] state = data[3 ] return { "page" : page_id, "control" : control_id, "state" : "按下" if state == 0x01 else "弹起" } return None def display_touch_listener (): """按照图片格式显示触摸事件""" try : ser = serial.Serial('COM4' , 115200 , timeout=1 ) print ("触摸事件监听程序已启动" ) print ("监听COM4端口,等待触摸事件..." ) print ("=" * 50 ) while True : if ser.in_waiting > 0 : data = ser.read(ser.in_waiting) current_time = datetime.now().strftime("%H:%M:%S" ) touch_info = parse_touch_data(data) hex_data = ' ' .join([f'{b:02X} ' for b in data]) print (f"[{current_time} ] 收到数据: {hex_data} " ) if touch_info: print (f"数据含义: 页面:{touch_info['page' ]} 控件:{touch_info['control' ]} {touch_info['state' ]} " ) else : try : text = data.decode('utf-8' , errors='ignore' ).strip() if text: print (f"文本内容: {text} " ) except : print ("无法解析数据格式" ) print ("-" * 50 ) time.sleep(0.05 ) except KeyboardInterrupt: print ("\n监听结束" ) except Exception as e: print (f"错误: {e} " ) finally : if 'ser' in locals () and ser.is_open: ser.close()if __name__ == '__main__' : display_touch_listener()
触摸监听后的反馈信息如下:
1 2 3 4 5 6 -------------------------------------------------- 接收到的数据:b'e\x03\x07\x00\xff\xff\xff' 数据格式正确,开始解析... [10:15:31] 收到数据: 65 03 07 00 FF FF FF 数据含义: 页面:3 控件:7 弹起 --------------------------------------------------
1 我这样刷新该页面后,返回上一页竟然把lastpage设置成当前页面了吗,原因是刷新页面后确实执行了页面离开事件,应该怎么优化一下,刷新后不影响返回到上一页?
很简单,在需要刷新的页面的页面离开事件中,不需要加以下代码即可:
以上是最简单粗暴的解决方法,还有比较优雅的解决方法,首先在 Program.s 全局文件中定义刷新标记。
刷新按钮控件编码如下。
1 2 3 isRefreshing=1 page dp isRefreshing=0
该页面的页面离开事件这样写:
1 2 3 4 5 if (isRefreshing==0 ) { lastpage=dp }
1 使用Python能监听串口屏发来的触发事件信号,执行Python程序也能主动发送信号到串口屏,比如修改某个文本框的内容,那Python程序如何能在监听的过程中也能主动发送信号呢,怎么编码,反正两个Python程序不能监听同一个串口。
同一个串口不能同时被两个Python程序监听。解决方案是使用单程序多线程 或异步编程 来实现同时监听和发送。以下是几种实现方式。
异步实现。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 import serialimport asyncioimport threadingimport timeclass AsyncHMICommunicator : def __init__ (self, port='COM4' , baudrate=115200 ): self.port = port self.baudrate = baudrate self.ser = None self.running = False async def start (self ): """异步启动""" try : self.ser = serial.Serial(self.port, self.baudrate, timeout=0.1 ) self.running = True asyncio.create_task(self._listener()) print (f"✅ 异步HMI通信器已启动" ) return True except Exception as e: print (f"❌ 启动失败: {e} " ) return False async def _listener (self ): """异步监听""" while self.running: try : if self.ser.in_waiting > 0 : data = self.ser.read(self.ser.in_waiting) await self._process_data(data) await asyncio.sleep(0.01 ) except Exception as e: print (f"监听错误: {e} " ) await asyncio.sleep(0.1 ) async def send_command (self, command ): """异步发送指令""" if not self.running: print ("❌ 通信器未启动" ) return try : if isinstance (command, str ): if not command.endswith('\xFF\xFF\xFF' ): command += '\xFF\xFF\xFF' command = command.encode('gb2312' ) self.ser.write(command) print (f"✅ 指令已发送: {command} " ) except Exception as e: print (f"❌ 发送失败: {e} " ) async def _process_data (self, data ): """异步处理数据""" hex_data = ' ' .join([f'{b:02X} ' for b in data]) print (f"📥 收到数据: {hex_data} " )async def async_main (): hmi = AsyncHMICommunicator(port='COM4' , baudrate=115200 ) if await hmi.start(): await hmi.send_command('t0.txt="异步通信测试"' ) async def periodic_sender (): counter = 0 while True : await asyncio.sleep(3 ) counter += 1 await hmi.send_command(f't1.txt="计数: {counter} "' ) asyncio.create_task(periodic_sender()) await asyncio.Future() if __name__ == "__main__" : asyncio.run(async_main())
1 2 3 4 5 Traceback (most recent call last): File "D:\Project\python\python通讯\python测试\asyncio.py" , line 88, in <module> asyncio.run(async_main()) ^^^^^^^^^^^ AttributeError: module 'asyncio' has no attribute 'run' (consider renaming 'D:\Project\python\python通讯\python测试\asyncio.py' since it has the same name as the standard library module named 'asyncio' and prevents importing that standard library module)
文件命名与标准库asyncio模块冲突了,请 Python 文件重命名 ,不能使用asyncio.py这个文件名。
1 2 3 4 5 6 7 8 9 ✅ 异步HMI通信器已启动 ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 15 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence ❌ 发送失败: 'gb2312 ' codec can't encode character '\xff' in position 14 : illegal multibyte sequence
实现不了真正意义上的异步,本来 Python 程序就是作为后台服务的角色,只需要监控控件指令即可。
1 2 3 4 ✅ HMI通信器已启动,端口: COM4 ✅ 发送: t0.txt ="Hello World" ✅ 发送: page 2 ✅ 发送: t1.txt ="计数: 1"
完整代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 import serialimport threadingimport timeimport queueclass FixedHMICommunicator : def __init__ (self, port='COM4' , baudrate=115200 ): self.port = port self.baudrate = baudrate self.ser = None self.send_queue = queue.Queue() self.running = False def start (self ): """启动通信""" try : self.ser = serial.Serial(self.port, self.baudrate, timeout=1 ) self.running = True listener_thread = threading.Thread(target=self._listener, daemon=True ) listener_thread.start() sender_thread = threading.Thread(target=self._sender, daemon=True ) sender_thread.start() print (f"✅ HMI通信器已启动,端口: {self.port} " ) return True except Exception as e: print (f"❌ 启动失败: {e} " ) return False def _listener (self ): """监听线程""" while self.running: try : if self.ser and self.ser.in_waiting > 0 : data = self.ser.read(self.ser.in_waiting) self._process_received_data(data) time.sleep(0.01 ) except Exception as e: print (f"监听错误: {e} " ) time.sleep(0.1 ) def _sender (self ): """发送线程""" while self.running: try : if not self.send_queue.empty(): command = self.send_queue.get_nowait() self._send_command(command) time.sleep(0.01 ) except Exception as e: print (f"发送错误: {e} " ) time.sleep(0.1 ) def send_command (self, command ): """发送指令""" if self.running: self.send_queue.put(command) else : print ("❌ 通信器未启动" ) def _send_command (self, command ): """实际发送指令 - 修复编码问题""" try : if isinstance (command, str ): if command.endswith('\xFF\xFF\xFF' ): command = command[:-9 ] text_encoded = command.encode('gb2312' , errors='ignore' ) full_command = text_encoded + b'\xFF\xFF\xFF' self.ser.write(full_command) print (f"✅ 发送成功: {command} " ) elif isinstance (command, bytes ): self.ser.write(command) print (f"✅ 发送字节数据: {command.hex ()} " ) except Exception as e: print (f"❌ 发送失败: {e} " ) def send_command_safe (self, command_text ): """安全的发送方法 - 推荐使用""" try : if not isinstance (command_text, str ): command_text = str (command_text) text_bytes = command_text.encode('gb2312' , errors='ignore' ) full_command = text_bytes + b'\xFF\xFF\xFF' if self.running and self.ser: self.ser.write(full_command) print (f"✅ 发送: {command_text} " ) else : print ("❌ 通信器未就绪" ) except Exception as e: print (f"❌ 发送失败: {e} " ) def _process_received_data (self, data ): """处理接收数据""" hex_data = ' ' .join([f'{b:02X} ' for b in data]) print (f"📥 收到: {hex_data} " ) if len (data) >= 7 and data[0 ] == 0x65 and data[-3 :] == b'\xFF\xFF\xFF' : page_id = data[1 ] control_id = data[2 ] state = data[3 ] state_text = "按下" if state == 0x01 else "弹起" print (f"🔄 触摸: 页面{page_id} 控件{control_id} {state_text} " ) def stop (self ): """停止""" self.running = False if self.ser: self.ser.close() print ("🛑 通信器已停止" )def main (): hmi = FixedHMICommunicator(port='COM4' , baudrate=115200 ) if hmi.start(): try : hmi.send_command_safe('t0.txt="Hello World"' ) time.sleep(3 ) hmi.send_command_safe('page 2' ) time.sleep(3 ) counter = 0 while True : time.sleep(3 ) counter += 1 hmi.send_command_safe(f't1.txt="计数: {counter} "' ) except KeyboardInterrupt: print ("\n用户中断" ) finally : hmi.stop()if __name__ == "__main__" : main()
我特么服了,记得二十八号晚些时候写过 Python 联调串口屏的经验来着,连接串口屏后同一时间 USART HMI 编辑器和 Python 程序只能有一个监听 COM5。
要么在模拟器连接到本机串口 COM5,在 USART HMI 软件接收串口屏发来的数据;要么使用 Python 监听串口屏端口 COM5,监听串口屏控件发来的指令,或者使用 Python 程序主动朝串口屏发送信号。
下午,优化完毕串口屏测试程序,接下来可以继续熟悉下串口屏控件编码,以及 Python 联调如何编码。
不想看了,看会儿 Docker。
2025 年 11 月 28 日
执行模拟串口通信测试程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def test_virtual_ports (): """测试虚拟串口通信""" print ("🔧 测试虚拟串口通信..." ) try : ser_send = serial.Serial('COM3' , 115200 , timeout=1 ) print ("✅ 已连接COM3(发送端)" ) ser_recv = serial.Serial('COM4' , 115200 , timeout=1 ) print ("✅ 已连接COM4(接收端)" ) test_data = b"Hello from COM3!\xFF\xFF\xFF" print (f"📤 向COM3发送: {test_data} " ) ser_send.write(test_data) time.sleep(0.5 ) if ser_recv.in_waiting > 0 : received = ser_recv.read(ser_recv.in_waiting) print (f"📥 从COM4收到: {received} " ) print ("✅ 虚拟串口通信正常!" ) else : print ("❌ 没有收到数据,虚拟串口可能有问题" ) ser_send.close() ser_recv.close() except Exception as e: print (f"❌ 测试失败: {e} " )
测试结果:
1 2 3 4 5 6 send.py::test_virtual_ports PASSED [100 ✅ 已连接COM3(发送端) ✅ 已连接COM4(接收端) 📤 向COM3发送: b'Hello from COM3!\xff\xff\xff' 📥 从COM4收到: b'Hello from COM3!\xff\xff\xff' ✅ 虚拟串口通信正常!
执行监听按钮点击事件完整程序:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 def advanced_button_listener (): """监听按钮点击事件的完整程序""" try : ser = serial.Serial('COM4' , 115200 , timeout=1 ) print ("🎯 按钮监听程序已启动" ) print ("📡 监听COM4,等待COM3的模拟器信号" ) print ("请在模拟器中点击配置了'触摸发送'的按钮" ) print ("按Ctrl+C停止监听\n" ) print ("-" * 60 ) receive_count = 0 while True : if ser.in_waiting > 0 : data = ser.read(ser.in_waiting) receive_count += 1 current_time = datetime.now().strftime("%H:%M:%S" ) print (f"\n🕒 [{current_time} ] 第{receive_count} 次收到数据:" ) hex_data = ' ' .join([f'{b:02X} ' for b in data]) print (f"🔢 原始数据: {hex_data} " ) try : text_utf8 = data.decode('utf-8' , errors='ignore' ) text_gb = data.decode('gb2312' , errors='ignore' ) clean_utf8 = '' .join(c if 32 <= ord (c) <= 126 else f'[{ord (c):02X} ]' for c in text_utf8) clean_gb = '' .join(c if 32 <= ord (c) <= 126 else f'[{ord (c):02X} ]' for c in text_gb) if clean_utf8.strip(): print (f"📝 UTF-8文本: {clean_utf8} " ) if clean_gb.strip() and clean_gb != clean_utf8: print (f"📝 GB2312文本: {clean_gb} " ) except Exception as e: print (f"❌ 解码错误: {e} " ) if len (data) >= 6 and data[0 ] == 0x65 : page_id = (data[1 ] << 8 ) | data[2 ] control_id = (data[3 ] << 8 ) | data[4 ] state = data[5 ] if state == 0x01 : print (f"🟢 按钮按下! 页面{page_id} 控件{control_id} " ) elif state == 0x00 : print (f"🔴 按钮释放! 页面{page_id} 控件{control_id} " ) else : print (f"❓ 未知状态: {state:02X} " ) if b'button' in data.lower() or b'click' in data.lower(): print ("🎯 检测到按钮相关指令!" ) print ("-" * 50 ) time.sleep(0.05 ) except KeyboardInterrupt: print (f"\n🛑 监听结束,共收到 {receive_count} 次数据" ) except Exception as e: print (f"❌ 错误: {e} " ) finally : if 'ser' in locals () and ser.is_open: ser.close() print ("🔒 串口已关闭" )
测试结果:
1 2 3 4 5 6 send.py::test_virtual_ports PASSED [100 ✅ 已连接COM3(发送端) ✅ 已连接COM4(接收端) 📤 向COM3发送: b'Hello from COM3!\xff\xff\xff' 📥 从COM4收到: b'Hello from COM3!\xff\xff\xff' ✅ 虚拟串口通信正常!
Python 对COM3串口发送指令正常,监听COM4接受指令也正常,那就是模拟器操作控件肯定没有正常发送信号,估计得先编码控件。
这个AI的回复不能信服。
今天晚些时候再测。
2025 年 11 月 27 日
考虑到生产环境下的应用场景,使用 Python 脚本在后台监听模拟器或串口屏操作信号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 def diagnose_connection (): print ("=== 串口连接诊断 ===" ) ports = serial.tools.list_ports.comports() print ("1. 可用串口列表:" ) if not ports: print (" ❌ 没有找到任何串口设备" ) return False for port in ports: print (f" ✅ {port.device} - {port.description} " ) target_port = 'COM4' print (f"\n2. 尝试连接 {target_port} " ) try : ser = serial.Serial(target_port, 9600 , timeout=2 ) print (f" ✅ 成功连接到 {target_port} " ) ser.close() return True except Exception as e: print (f" ❌ 连接失败: {e} " ) return False if __name__ == "__main__" : diagnose_connection()
1 2 3 4 5 6 7 8 9 Traceback (most recent call last): File "D:\Project\python\python通讯\python测试\test1127.py" , line 85, in <module> diagnose_connection() ~~~~~~~~~~~~~~~~~~~^^ File "D:\Project\python\python通讯\python测试\test1127.py" , line 58, in diagnose_connection ports = serial.tools.list_ports.comports() ^^^^^^^^^^^^ AttributeError: module 'serial' has no attribute 'tools'
1 2 import serialfrom serial.tools import list_ports
2025 年 11 月 26 日
今天继续抽时间进一步优化串口屏调试。
串口助手软件(sscom)和屏幕联调 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
1 USART (Universal Synchronous/Asynchronous Receiver/Transmitter)是一种全双工通用同步/异步串行收发模块,作为高度灵活的串行通信设备,支持相互独立的收发数据操作。其核心功能涵盖同步/异步双模式运行,可配置5 至9 位数据位及1 -2 位停止位,内置硬件奇偶校验、数据溢出检测、帧错误检测等机制,并具备三级中断支持。
妈的昨天看串口调试助手看走眼了,还以为有官方提供的虚拟串口设备,结果只是提供了同串口屏协作的调试助手而已。
这些调试助手包括但不限于:sscom,uartassist,xcom,llcom。
1 串口屏与单片机联调,与Arduino联调,与MicroPython联调,与Python联调,这些都是什么。
这些都是在不同环境下与淘晶驰串口屏进行通信和调试的场景。它们的目标一致:让外部设备或程序能够控制串口屏的显示,并接收串口屏的触摸等事件。但使用的工具和编程语言不同。
单片机 :如STM32、51系列等,是嵌入式设备的核心控制芯片。
Arduino :一种开源的电子原型平台,使用C++风格的Arduino语言,编程简单。
MicroPython :是运行在微控制器上的Python语言。
Python :这里通常指在电脑上运行的Python程序。
本质上都是通过串口协议与屏幕通信,只是编程语言和运行环境不同。
晚十点半,下载周一编码完成的控件到串口屏,执行操作发送到本机模拟器和串口屏,成功了,他妈的联调成功。
本机启动模拟器,确保正确下载完成控件程序到串口屏后,HMI 提供的模拟器调试键盘输入,能正确操作连接在本机上的串口屏。
停止模拟器调试,只是单纯把串口屏插在本机上,我的串口屏联机用到的串口号是COM5,注意这里只有一个串口号,那就是串口屏的串口号,启动Python程序直接发送信号到COM5,翻页成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import serial try : ser=serial.Serial(port="COM5" ,baudrate=115200 ,timeout=5 ) command = b"page page0\xff\xff\xff" ser.write(command) print ("发送页面切换指令" )except Exception as e: print ("---异常---:" ,e)
同样的,改写文本字符也成功了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import serial try : ser=serial.Serial(port="COM5" ,baudrate=115200 ,timeout=5 ) print ("串口详情参数:" , ser) result=ser.write("t0.txt=\"淘晶驰电子!\"" .encode("GB2312" )) ser.write(bytes .fromhex('ff ff ff' )) ser.close()except Exception as e: print ("---异常---:" ,e)
今天的调试结束。
2025 年 11 月 25 日
淘晶驰资料中心 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
与 Python 联调。
Python 发送数据给屏幕工程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import serial try : ser=serial.Serial(port="COM9" ,baudrate=115200 ,timeout=5 ) print ("串口详情参数:" , ser) result=ser.write("t0.txt=\"淘晶驰电子!\"" .encode("GB2312" )) ser.write(bytes .fromhex('ff ff ff' )) ser.close()except Exception as e: print ("---异常---:" ,e)
这段代码是一个串口通信程序 ,主要用于与淘晶驰串口屏(HMI人机界面) 进行通信和控制。
代码执行流程:
打开COM9串口
发送显示文本指令
发送结束标志
关闭串口
Python 获取电脑状态。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 import timeimport psutilimport serial time.sleep(3 )def getCPUstate (interval=1 ): return (" CPU: " + str (psutil.cpu_percent(interval)) + "%" )def getMemorystate (): phymem = psutil.virtual_memory() line = "Memory: %5s%% %6s/%s" % ( phymem.percent, str (int (phymem.used / 1024 / 1024 )) + "M" , str (int (phymem.total / 1024 / 1024 )) + "M" ) return linedef bytes2human (n ): """ >>> bytes2human(10000) '9.8 K' >>> bytes2human(100001221) '95.4 M' """ symbols = ('K' , 'M' , 'G' , 'T' , 'P' , 'E' , 'Z' , 'Y' ) prefix = {} for i, s in enumerate (symbols): prefix[s] = 1 << (i + 1 ) * 10 for s in reversed (symbols): if n >= prefix[s]: value = float (n) / prefix[s] return '%.2f %s' % (value, s) return '%.2f B' % (n)def poll (interval ): """Retrieve raw stats within an interval window.""" tot_before = psutil.net_io_counters() pnic_before = psutil.net_io_counters(pernic=True ) time.sleep(interval) tot_after = psutil.net_io_counters() pnic_after = psutil.net_io_counters(pernic=True ) cpu_state = getCPUstate(interval) memory_state = getMemorystate() return (tot_before, tot_after, pnic_before, pnic_after, cpu_state, memory_state)def refresh_window (tot_before, tot_after, pnic_before, pnic_after, cpu_state, memory_state ): str = "t0.txt=\"" + time.asctime() + " | " + cpu_state + " | " + memory_state + "\"" serial.write(str .encode("GB2312" )) serial.write(bytes .fromhex('ff ff ff' )) nic_names = pnic_after.keys() for name in nic_names: if name == "以太网" : stats_before = pnic_before[name] stats_after = pnic_after[name] templ = "%-15s %15s %15s" str = "t1.txt=\"上传数据总量" + bytes2human(stats_after.bytes_sent) + " 上传速度:" + bytes2human(stats_after.bytes_sent - stats_before.bytes_sent) + '/s\"' serial.write(str .encode("GB2312" )) serial.write(bytes .fromhex('ff ff ff' )) str = "t2.txt=\"下载数据总量" + bytes2human(stats_after.bytes_recv) + " 下载速度:" + bytes2human(stats_after.bytes_recv - stats_before.bytes_recv) + '/s\"' serial.write(str .encode("GB2312" )) serial.write(bytes .fromhex('ff ff ff' )) try : interval = 0 portx = "COM9" bauds = 115200 timex = 5 serial = serial.Serial(port=portx,baudrate=bauds,timeout=timex) while 1 : args = poll(interval) refresh_window(*args) interval = 1 except (KeyboardInterrupt, SystemExit): pass
1 pip uninstall serial pyserial
1 2 print (serial.__file__)print (dir (serial))
1 2 3 C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\site-packages\serial\__init__.py ['CR' , 'EIGHTBITS' , 'FIVEBITS' , 'LF' , 'PARITY_EVEN' , 'PARITY_MARK' , 'PARITY_NAMES' , 'PARITY_NONE' , 'PARITY_ODD' , 'PARITY_SPACE' , 'PortNotOpenError' , 'SEVENBITS' , 'SIXBITS' , 'STOPBITS_ONE' , 'STOPBITS_ONE_POINT_FIVE' , 'STOPBITS_TWO' , 'Serial' , 'SerialBase' , 'SerialException' , 'SerialTimeoutException' , 'Timeout' , 'VERSION' , 'XOFF' , 'XON' , '__builtins__' , '__cached__' , '__doc__' , '__file__' , '__loader__' , '__name__' , '__package__' , '__path__' , '__spec__' , '__version__' , 'absolute_import' , 'basestring' , 'importlib' , 'io' , 'iterbytes' , 'os' , 'protocol_handler_packages' , 'serial_for_url' , 'serialutil' , 'serialwin32' , 'sys' , 'time' , 'to_bytes' , 'unicode' , 'win32' ]
pyserial库已正确安装,Python 正在使用正确版本的 serial`模块,模块路径指向标准的 site-packages 目录。
妈的,又不报错了,执行结果如下。
1 ---异常---: could not open port 'COM2' : FileNotFoundError(2 , '系统找不到指定的文件。' , None , 2 )
先把控件详解和基本指令集看完。
控件详解。
控件详解,挨个把所有控件用途和属性大概过一遍。
Python 通信。
[嵌入式] USART HMI智能串口屏 一篇就够!保姆级教程
虚拟串口驱动详解与应用实践指南-CSDN博客
1 2 3 File "C:\Users\Lenovo\AppData\Local\Programs\Python\Python314\Lib\site-packages\serial\serialwin32.py", line 64 , in open raise SerialException("could not open port {!r}: {!r}".format(self.portstr, ctypes.WinError()))serial .serialutil.SerialException: could not open port 'COM9' : FileNotFoundError(2 , '系统找不到指定的文件。' , None , 2 )
com0com。
com0com虚拟串口使用教程-CSDN博客
Download Null-modem emulator
安装之后有人会出现带黄色感叹号这种,操作系统设置-高级启动-禁用强制驱动程序签名就可以,或者找其他博主的解决方案,因为我的电脑没出现,所以没办法验证方法的可行性。
虚拟串口com0com安装后设备管理器是感叹号的解决办法_安装虚拟com 黄色感叹号-CSDN博客
直接在设置/Windows更新/高级选项/可选更新下面选择。
1 安装com0 com软件后在设备管理器中虚拟串口黄色感叹号
win11在安装com0com软件后,在设备管理器中虚拟串口黄色感叹号得解决方法_com0com 黄色感叹号-CSDN博客
虚拟串口com0com安装后设备管理器是感叹号的解决办法_安装虚拟com 黄色感叹号-CSDN博客
解决了。
下载串口调试工具,测试虚拟串口能不能正常工作,USART HMI 程序尝试联机虚拟串口失败,试下重启软件和重启电脑后管不管用。
应该没什么问题。
1 点击连接本机虚拟串口后,左下角显示尝试联机COM3 :2400 ,这是什么意思,为什么点击联机后软件卡死了呢。
触摸屏PPI通信如何更改波特率_百度知道
虚拟串口是成对出现的。com0com创建了一对虚拟串口,比如COM3和COM4。这两个端口是相互连接的:发送到COM3的数据会被COM4接收,反之亦然。
所以,正确的做法是:
将USART HMI程序连接到其中一个虚拟串口(例如COM3)
将Python程序连接到另一个虚拟串口(例如COM4)
这样,当Python程序向COM4写入数据时,USART HMI程序从COM3读取数据;当USART HMI程序向COM3写入数据时,Python程序从COM4读取数据。
测试成功。
1 2 3 4 5 6 7 8 9 10 11 12 13 import serial try : ser=serial.Serial(port="COM4" ,baudrate=115200 ,timeout=5 ) print ("串口详情参数:" , ser) result=ser.write("t0.txt=\"淘晶驰电子!\"" .encode("GB2312" )) ser.write(bytes .fromhex('ff ff ff' )) ser.close()except Exception as e: print ("---异常---:" ,e)
模拟器勾选用户MCU输入,自定义波特率 115200 并选择本机虚拟串口号COM3,点击开始监听;本机启动 Python 程序向虚拟串口号COM4发送数据,模拟器响应正常。
今天的工作结束了。
串口助手软件(sscom)和串口屏模拟器联调1 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
串口助手软件可以下载安装官网推荐的 sscom。
2025 年 11 月 24 日
1 2 1. 硬件建设 基于信创技术路线,研发一套适配监测运维系统的专用设备。要求处理器、操作系统都在信创名录,支持4.3 英寸480 x1920分辨率的TFT 显示屏,具备常用的IO输入输出功能。
usart hmi(串口屏)介绍-CSDN博客
前言 — 三易串口屏开发指南 1.4.0 文档
淘晶驰资料中心 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
快速入门 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
淘晶驰串口屏官网,下载安装 USART HMI 上机位开发软件。
下载安装。
USB 转 TTL 模块还没到,估计这个模块物流到了之后就能正常连接串口屏进行开发了,先看官网学习下怎么开发。
1 2 3 4 总可用内存:3584 全局内存占用:16 错误:页面:page0 失败:t0.font 初始值无效:字库ID无效 错误:编译失败! 1个错误, 0个警告
先解决下这个问题。
工具栏下点击字库制作,解决问题。
到手测试 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
1 用 USART HMI 软件开发串口屏应用,用到了什么语言?能使用python 脚本帮助开发吗
了解USART HMI串口屏应用的开发语言以及Python的辅助开发方式很有用。简单来说,核心的界面设计和逻辑控制使用了一套类似C语言的专用脚本,而Python则可以作为强大的辅助工具,在特定场景下大显身手 。
下面这个表格能帮你快速了解不同语言在USART HMI开发中的角色。
开发环节/用途
主要使用语言/技术
Python的可参与性
串口屏界面逻辑
USART HMI专用脚本 (类C语言)
无法直接使用 。屏幕固件只解析专用指令。
下位机(单片机)程序
C / C++ (如STM32的Arduino、HAL库)
可以 。通过PySerial 库控制串口与屏幕通信。
上位机(PC)测试工具
通常为C++(Qt)/C#(WinForm)等
非常适合 。Python(PyQt/PySerial)可快速搭建调试助手。
嵌入式脚本控制器
通常为C/C++
可以 。在运行MicroPython的ESP32/ESP8266等单片机上,可直接用Python驱动屏幕。
1 那么使用 Pycharm 编辑器能达到跟 USART HMI 一样的开发效果吗?
特性维度
USART HMI 软件
PyCharm
核心定位
串口屏专用集成开发环境
通用Python IDE
界面设计
可视化拖拽 ,专有控件,所见即所得
需借助 PyQt、Tkinter 等库编写代码 来创建图形界面
通信逻辑
内建串口通信协议,自动生成指令帧
需手动调用 pyserial等库编写底层串口通信代码
程序运行
代码最终下载到串口屏硬件 中运行
Python 代码在电脑 上运行
适用场景
专注于为嵌入式设备开发人机交互界面
通用软件开发,如Web后端、数据分析、AI、脚本工具等
1 实时时钟的缩写是RTC (Real_Time Clock)。RTC 是集成电路,通常称为时钟芯片。
1 实时时钟芯片是日常生活中应用最为广泛的消费类电子产品之一。它为人们提供精确的实时时间,或者为电子系统提供精确的时间基准,实时时钟芯片大多采用精度较高的晶体振荡器作为时钟源。有些时钟芯片为了在主电源掉电时,还可以工作,需要外加电池供电。
配置文件常用的系统变量:
请注意:page是跳转页面的指令,page指令后面的代码将不会执行。
Program.s 配置文件内容:
1 2 3 4 5 6 7 int sys0=0 ,sys1=0 ,sys2=0 baud=9600 dim=100 recmod=0 printh 00 00 00 ff ff ff 88 ff ff ff page 0
下午再研究下代码编写吧,中午吃完饭顺便把串口屏带上,对照着官网引导看看这屏幕的构造啥的。
午饭后。
书写语法。
滑块实现调节屏幕亮度:
按钮实现跳转至新的页面:
实现一个定时器:
1 2 错误:全局变量定义必须放在Program .c文件中所有代码之前:int timer_count = 0 (双击此处定位代码) 错误:编译失败
1 2 3 4 5 6 7 8 9 10 int sys0=0 ,sys1=0 ,sys2=0 int timer_count = 0 baud=9600 dim=100 recmod=0 printh 00 00 00 ff ff ff 88 ff ff ff page 0
1 2 3 4 5 timer_count++if (timer_count==10 ) { page main }
这个编译器报错后的代码定位功能真不错。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 n0.val=1 n1.val=h0.val dim=90 bauds=115200 n2.val=bauds p0.pic=0 p1.pic=n0.val
运算操作。
1 2 3 所有运算不支持乘除法优先,也不支持括号优先级,统一从左到右的顺序,请特别注意。 所有的运算操作可以在上位编辑状态下写入控件事件中,也可以串口传输过来 所有的运算操作都不支持多余空格,添加进任何空格,编译都会报错
跨页面赋值,全局变量。
多数情况下,我们都是在操作当面页面的控件属性,如果需要操作其他页面的控件属性需要提前将对应的控件设置为全局。
[页面].[控件].[属性]=XXX。
逻辑语句。
1 2 所有的逻辑语句只能在上位编辑状态下写入控件的事件中,不支持串口传输逻辑语句。 所有的判断语句都不支持多余空格,添加进任何空格,编译都会报错
1 2 3 4 5 6 7 if (b0.txt=="开始" ) { b0.txt="停止" }else { b0.txt="开始" }
n0.val一直自加到100为止,在自加过程中屏幕会一直不断的刷新n0控件的显示。
1 2 3 4 5 while (n0.val<100 ) { n0.val++ doevents }
串口屏返回数据格式。
取消设备开机固定发送开机信息,转为Program.s中由代码发送开机信息(用户可自行注释或者删除)。
1 2 printh 00 00 00 ff ff ff 88 ff ff ff page 0
1 2 3 4 00 00 00 - 帧头或预留字段(可能是设备地址或命令类型) ff ff ff - 分隔符(USART HMI协议中常用0xFF 作为分隔)88 - 核心数据:上电状态码(136 的十六进制) ff ff ff - 结束符(USART HMI协议要求每条指令以3 个0xFF 结束)
系统变量。
在program.s中只能使用int来定义全局变量,无法定义char,float,double等类型,使用int定义的语句必须写在program.s的最前面
返回上一页。
某些情况下,可能从多个不同的页面跳转到同一个页面,这时如果在“返回”按钮中直接跳转到某一个页面,就会造成逻辑混乱,此时可以使用以下方法解决:
在program.s中新建一个lastpage变量。
在每一个页面的离开事件中添加以下代码,将dp的值赋值给 lastpage 变量。
添加一个“返回上一页”按钮,在按钮中跳转到 lastpage 所保存的值。
刷新当前页面。
volume,体积;卷,合订本;容积,容量;量,额;音量,响度;大量,许多;书;(成套书籍中的)一卷,一册;最大音量;唱片;一套录音磁带。
背光亮度值。
1 2 3 dim 和dims区别dim :不会自动关机保存 dims:会自动保存,下次开机时还是此亮度值
通过滑块设置亮度。
在前初始化事件中将dim赋值给进度条。
在滑动事件中将进度值赋值给dim。
在弹起事件中将进度值赋值给dims。
进度值的最小值建议设置为5,避免完全黑屏后没有办法调回来。
配置波特率值。
无串口数据自动睡眠时间,无触摸操作自动睡眠时间。
睡眠。
随机数。
1 2 3 4 5 6 7 8 randset 0 ,9999 n0.val=rand n1.val=rand n2.val=rand n3.val=rand n4.val=rand
修改颜色。
1 2 3 4 5 6 t0.txt="白色字体黑色背景" t1.txt="绿色字体红色背景" t0.pco=WHITE t0.bco=BLACK t1.pco=GREEN t1.bco=RED
串口屏调试。
淘晶驰串口屏的模拟器功能非常强大,您可以在没有串口屏实物的情况下通过模拟器进行调试,上位机模拟器几乎可以完全模拟真实的设备,在指令输入区可以直接输入指令,不需要结束符。
在指令输入区可输入指令给文本赋值,不需要对引号进行转义。
跳转页面,给文本/数字赋值,设置屏幕背光。
1 2 3 page page1 n0.val=10000 dim=90
也可以修改文本控件的背景颜色,可以通过指令修改的是控件的“绿色属性”。
调整控件大小。
t0.txt=”淘晶驰电子”和t0.bco=YELLOW的区别是一个加了引号,一个没有加引号,这是因为txt是字符串,bco则是整形,目前只txt,path,dir,filter是字符串,其他均为整形。
黑色属性和绿色属性。
如下图所示:属性栏中显示为绿色的属性都可以在运行中修改,黑色的属性只能在编辑时修改,不能在运行中修改。
USB转TTL的接线说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 串口屏的TX(发送)接USB转TTL 的RX(接收) 串口屏的RX(接收)接USB转TTL 的TX(发送) 串口屏的GND要和USB转TTL 的GND连接在一起(共地) 如果上电时发现串口屏不断重启(4 .3 寸以上的屏幕以及带喇叭的屏幕),可能是供电不足,这时候需要并联一个电源来提高电流 需要额外找一个电源引出电源正负极,注意正负极之间的电压应该在屏幕的供电范围内 将电源正极接到屏幕的VCC上(请注意电压范围) 电源负极接到GND(共地) 这样就实现了对屏幕的额外供电
单片机和串口屏的关系就像是 “大脑” 和 “脸” 的关系。
单片机 是大脑 :负责核心的逻辑计算、数据处理、控制决策。
串口屏 是脸 :负责信息显示和人机交互(触摸),并把用户的指令反馈给大脑。
它们各司其职,共同构成一个完整的嵌入式人机交互系统。下面这个表格清晰地展示了两者的分工与合作。
模块
角色
核心任务
相当于
单片机
大脑/主控
执行核心逻辑、运算、控制外设、与传感器/执行器通信
汽车的发动机、ECU
串口屏
脸/交互界面
显示图形界面、接收触摸指令、将指令转发给单片机
汽车的仪表盘、方向盘、中控屏
这种设计带来的优势:
优势
说明
降低开发难度
单片机程序员无需编写复杂的图形驱动和触摸识别代码,只需通过简单的串口指令即可控制精美界面。
专业分工
硬件工程师专注于单片机功能,UI设计师专注于屏幕界面设计,两者通过串口协议对接,协作高效。
灵活更换
只要通信协议不变,可以轻易更换不同尺寸、不同厂家的串口屏,而无需修改单片机的主程序。
通俗地解释单片机开发:
Web开发
单片机开发
思维转换
处理数据
控制电流
你写的代码会直接影响物理世界的电压和电流。
逻辑错误导致页面报错
逻辑错误可能导致短路、冒烟
对硬件要心存敬畏,连接电路前务必检查!
崩溃了可以刷新页面
代码写死可能导致芯片“变砖”
需要掌握如何通过“烧录器”来救援。
1 串口屏开发需要用到 USART HMI 编辑器,那么单片机开发呢,常用的编辑器有哪些?
什么是单片机?
什么是嵌入式开发?
和USB转TTL的接线说明 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
和单片机的接线说明 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
1 2 3 - 模拟器(电脑)与串口屏实物连接- 模拟器(电脑)与单片机连接- 串口屏与单片机连接
任意两个设备之间连接,均是TX接对方的RX,RX接对方的TX,GND接对方的GND,如果双方都有独立的供电,可以不接5V线
电脑与串口屏连接。
必须保证下面选择的是“键盘输入”,上面才能选择模拟器和串口,与串口屏进行联机。
当模拟器和一个串口屏实物连接成功时,底部将会显示联机成功,以及联机获取到的串口屏参数。
此时输入指令,指令会被同时发送到模拟器和串口屏实物上
除此之外,如果屏幕是带RTC的(例如X5/K0系列),可以校准RTC(必须是在联机成功的状态下),校准前请安装串口屏实物背部的RTC电池,型号是CR1220
1 淘晶驰强大的模拟器功能几乎能够实现与实体屏幕几乎一样的功能,除外部IO,电阻屏校准等实物特有的少数功能外,几乎都可以在屏幕上完全仿真。您可以提前通过模拟器和单片机之间进行通讯,在屏幕样品快递之前就能完成大部分功能的开发和调试,大大降低开发和选型成本。
电脑与单片机连接。
这个连接方式在这里不再详述。
单片机与串口屏连接。
淘晶驰官方的USB转TTL转接板,其作用有以下两种:
1、电脑通过USB转TTL连接串口屏进行下载或者调试。
2、电脑通过USB转TTL连接单片机进行通讯。
如果不使用电脑时,请勿通过USB转TTL工具连接单片机和串口屏,怎么接都不行!
部分客户使用的是正点原子、野火等公司的开发板,看到板子上有USB口,就直接把USB转TTL工具插上去。
或者是开发板有microUSB接口或者typec接口,把自己的手机充电线插进去,这是万万不行的。
因为这时候你的单片机开发板是接入了一个USB设备而不是USART设备,除非你去驱动这个USB外设先与这个USB转TTL进行通讯,否则是不能跟屏幕进行通讯的。
1 USART (Universal Synchronous/Asynchronous Receiver/Transmitter)是一种全双工通用同步/异步串行收发模块,作为高度灵活的串行通信设备,支持相互独立的收发数据操作。其核心功能涵盖同步/异步双模式运行,可配置5 至9 位数据位及1 -2 位停止位,内置硬件奇偶校验、数据溢出检测、帧错误检测等机制,并具备三级中断支持。
1 模块结构包含时钟发生器、数据发送器与接收器三大组件,其中时钟发生器由同步逻辑电路和波特率发生器组成,发送器采用缓冲器实现连续传输,接收器则集成两级缓冲器和噪声滤波器。USART与UART保持寄存器位定义、波特率生成等基础兼容性,同时在接收缓冲器设计和错误标志处理方面有所改进。
串口屏与单片机连接 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
所有单片机与串口屏连接的注意事项,直接点击上文的官网链接查看即可。
串口屏通信协议。
串口屏通讯协议 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
这方面稍后再做了解。
其他联调方案暂且放过,重点可以看看与 Python 之间的联调。
与python联调 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
python发送数据给屏幕 — 淘晶驰串口屏资料中心 1.1.0-2025-11-21 14:36:46 文档
2025 年 11 月 18 日
(99+ 封私信 / 82 条消息) 「笔记分享」迪文串口屏基础GUI开发流程 - 知乎
串口屏介绍及开发环境搭建-CSDN博客
2025 年 11 月 17 日
什么是串口屏?串口屏该怎么选?
串口屏介绍及开发环境搭建-CSDN博客
串口屏入门-CSDN博客
迪文串口屏例程-CSDN博客
[ Arduino+Python ] 做一个串口屏,显示CPU使用率_python做硬件显示屏-CSDN博客
Python串口调试-CSDN博客
Python 读取串口并在终端显示,界面虽然不好看,但是有时候可以用来调试程序。
右键菜单
2025 年 11 月 20 日
更新下注册表中 command 的参数配置
1 "D:\dev\Visual Studio Code\Microsoft VS Code\Code.exe" "%1"
在注册表命令中添加正确的参数后,成功让 VSCode 基于选定的文件夹打开,其他所有程序的参数配置类似。
2025 年 11 月 18 日
在以下关键路径下逐一查找 :路径1:文件/文件夹通用菜单 计算机\HKEY_CLASSES_ROOT*\shell``计算机\HKEY_CLASSES_ROOT*\shellex\ContextMenuHandlers路径2:文件夹背景菜单(最可能的位置) 计算机\HKEY_CLASSES_ROOT\Directory\Background\shell``计算机\HKEY_CLASSES_ROOT\Directory\Background\shellex\ContextMenuHandlers路径3:驱动器菜单 计算机\HKEY_CLASSES_ROOT\Drive\shell``计算机\HKEY_CLASSES_ROOT\Drive\shellex\ContextMenuHandlers
搜索方法 :逐个展开上述路径。例如,展开 Directory\Background\shell,您会看到很多子项。
搜狗的 彻底粉碎文件 和 清理大文件/重复文件 两个篡改右键菜单项,我在这两个目录下成功删除了:
1 计算机\HKEY_CLASSES _ROOT \Directory \Background \shellex \ContextMenuHandlers
1 计算机\HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers
夸克云盘也一样。
1 注册表里有这些数据是什么意思啊:{A470F8CF-A1E8-4 f65-8335 -227475 AA5C46}
这个 GUID 在哪里?
根据我们之前的对话上下文,您很可能是在以下路径中找到它的:
1 HKEY_CLASSES _ROOT \Directory \Background \shellex \ContextMenuHandlers
在这个路径下,您会看到一个或多个以 GUID 命名的子项。您截图中编辑的,正是某个此类子项下的 (默认)值。
这个结构是什么意思?
这种结构代表右键菜单的一种注册方式 :
方式A:简单菜单(我们之前讨论的) 路径:...\shell\某个名称特点:直接在 (默认)值里填写要显示的文字(如“上传到夸克网盘”),并在其下建立 command子项来指定要运行的程序。这种是直接、简单的命令。
方式B:复杂菜单(您截图中的方式) 路径:...\shellex\ContextMenuHandlers\某个GUID特点:(默认)值里不填菜单文字,而是填一个 GUID。这种是告诉系统:“去调用这个编号的组件来生成菜单”。 优点:功能强大,可以实现动态菜单(如“使用Notepad++打开”的子菜单)、图标、条件判断等复杂逻辑。
这个特定的 GUID 是什么?
您截图中的 GUID {85212cfd-77ed-4add-8e24-a0a39e3dbfc3}经过查询,是 Microsoft 自家组件 的标识符,通常与 “设置”或“个性化” 等相关。它很可能是系统自带的某个右键菜单项(例如在新版Windows中,桌面右键菜单里的“显示设置”或“个性化”)。
这很重要,因为它意味着这个菜单项大概率是系统核心功能,而不是您想删除的第三方软件(如搜狗捆绑的软件)添加的。
在这个目录下有这个注册表文件:
1 计算机\HKEY_CLASSES_ROOT\Directory\shell\YunShellExplorerCommand
1 计算机\HKEY_CLASSES_ROOT\AllFilesystemObjects\shellex\ContextMenuHandlers\SendTo
1 计算机\HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\YunShellExt
依次删除以上目录,我把第三条注册表目录删除以后,右键点击文件 后百度网盘的菜单项竟然消失了。
1 计算机\HKEY_CLASSES_ROOT\*\shell\YunShellExplorerCommand
1 计算机\HKEY_CLASSES_ROOT\Directory\shellex\ContextMenuHandlers\YunShellExt
依次删除以上目录,我把第而二条注册表目录删除以后,右键点击文件夹 后百度网盘的菜单项也消失了。
清爽。
windows10系统下以管理员身份进入CMD(命令提示符)的三种方法_管理员身份win 10进入命令方法-CSDN博客
搜索栏直接搜索:点击任务栏上的「搜索框」(Win10 在左侧,Win11 在中间),输入 “cmd” 或 “命令提示符”,搜索结果中会显示 “命令提示符”,点击即可打开(若需管理员权限,右键选择 “以管理员身份运行”);
开始菜单查找:点击桌面左下角「开始菜单」(Win 图标),Win10 在 “Windows 系统” 文件夹中找到 “命令提示符”,Win11 需展开 “所有应用”,在字母 “W” 分类下的 “Windows 工具” 里找到 “命令提示符”,点击打开;
快捷键 “Win+R” 调用:按下键盘上的 “Win 键 + R 键”(Win 键即带 Windows 图标的按键),弹出 “运行” 对话框,输入 “cmd”,点击 “确定” 或按回车,即可快速打开命令提示符(若需管理员权限,在 “运行” 对话框中输入 “cmd” 后,按住 “Ctrl+Shift + 回车”)。
2025 年 11 月 17 日
自今年夏天七月初格式化C盘之后,之前自定义过的开始菜单磁铁、系统环境变量以及右键菜单都被重置了,给日常使用添了不少麻烦。
今早花时间搞搞这个。
夸克网盘,右键文件夹篡改的注册表目录在这里:
1 计算机\HKEY_CLASSES_ROOT \Directory \shell
这是任意空白处点击右键的注册表目录:
1 计算机\HKEY_CLASSES _ROOT \Directory \Background
针对所有文件夹的:计算机\HKEY_CLASSES_ROOT\Directory\shell。
针对空白处的:计算机\HKEY_CLASSES_ROOT\Directory\Background\shell。
针对所有文件(包括文件夹)的:计算机\HKEY_CLASSES_ROOT\AllFilesystemObjects\shell。
以上是系统用户的,部分配置也可能在当前用户下:计算机\HKEY_CURRENT_USER\Software\Classes\Directory\shell
百度网盘,夸克云盘,搜狗,这三个注册表菜单都是自定义的吗,放在计算机\HKEY_CLASSES_ROOT目录下的话就不好找了。
还是先考虑添加任意空白处的注册表策略吧。
主要是常用的编译器。
PING
2025 年 11 月 17 日
1 "C:\Windows\System32\PING.EXE"
系统环境变量里新增如下一条即可:
云盘
2025 年 11 月 17 日
查看一下D盘磁盘空间,妈的都爆红了,D盘磁盘空间一共275GB 现在就剩19G多了,不知道给我电脑里装了些什么玩意儿。
sofware 占用空间大小17GB,blog 占用空间大小3.5GB,dev 占用空间大小70GB,project 占用空间55GB,program 占用空间ji5GB。
四个主要文件夹一共占用空间150.5GB 。
隐藏文件夹里,视频占用空间14.6GB,图片占用空间32.3GB,文档占用空间29GB,桌面将近2GB。
这些都是占大头的,一共占用空间77.9GB 。
CI/CD
2025 年 11 月 13 日
我一个写Java的,怎么就开始玩K8s和Jenkins了?!前几天接到一个新任务,要求把以前部署在私有服务器上的项目,全 - 掘金
Jasypt
2026 年 1 月 16 日
[springboot 之 使用jasypt加密解密插件通俗易懂]-腾讯云开发者社区-腾讯云
用同一个密码加密同样的内容,每次生成的密文都不一样 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 String password = "mySecretKey" ;String text = "123456" ;String encrypted1 = encryptor.encrypt(text); String encrypted2 = encryptor.encrypt(text); String encrypted3 = encryptor.encrypt(text); System.out.println(encryptor.decrypt(encrypted1)); System.out.println(encryptor.decrypt(encrypted2)); System.out.println(encryptor.decrypt(encrypted3));
为什么能这样?
Jasypt 使用了 盐(Salt) 技术:
每次加密时,会生成一个随机的盐值
盐值和密文一起存储
解密时,从密文中提取盐值,然后用相同的盐值解密
加密过程:
1 明文 "123456" + 随机盐值 → 加密 → 密文(包含盐值)
解密过程:
1 密文(包含盐值) → 提取盐值 → 解密 → 明文 "123456"
2025 年 11 月 12 日
JAVA集成Jasypt进行加密、解密(SpringBoot)_jasypt在线加密解密工具-CSDN博客
集成步骤总结:
引入 Jasypt 依赖。
1 2 3 4 5 <dependency > <groupId > com.github.ulisesbocchio</groupId > <artifactId > jasypt-spring-boot-starter</artifactId > <version > 3.0.4</version > </dependency >
配置加密密钥。
1 2 3 jasypt: encryptor: password: mysecretkey
对敏感数据进行加密,并在配置文件中使用 ENC() 包裹加密值。
使用 Jasypt 命令行工具加密,Jasypt 提供了命令行工具来加密数据,执行以下命令加密数据库密码:
1 java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input="your_password" password="mysecretkey" algorithm=PBEWithMD5AndDES
其中:
input 是要加密的文本(例如数据库密码)
password 是加密密钥(与我们在配置文件中设置的 mysecretkey 一致)
algorithm 是加密算法,这里使用 PBEWithMD5AndDES。
执行后,将得到类似以下的加密文本输出:
1 5MG1sSxAx+EeJsBdmcVdKg ==
将加密后的文件写入配置文件:
1 2 3 spring: datasource: password: ENC(5MG1sSxAx+EeJsBdmcVdKg==)
当 Spring Boot 项目启动时,Jasypt 会自动识别 ENC() 包裹的加密内容,并使用密钥进行解密,无需额外的代码逻辑。这意味着在运行时,应用能够使用解密后的值。
可根据需求自定义加密器,选择适合的加密算法和配置。
分支
2025 年 11 月 11 日
1 Merge incoming changes into the current branch
1 Rebase the current branch on top of incoming changes
在更新分支时,选择“Merge incoming changes”还是“Rebase the current branch”会带来截然不同的项目历史记录。为了帮你快速把握核心区别,下面这个表格汇总了它们的主要特性。
特性
Merge (合并)
Rebase (变基)
历史记录结构
保留分叉与合并点,形成图状结构
生成线性历史记录,隐藏分叉
操作原理
创建一个新的合并提交 ,将两个分支的历史联系在一起
将当前分支的提交“移动”到目标分支的最新提交之后
提交哈希值
原有提交的哈希值不变
被移动的提交会生成全新的哈希值
适用分支
公共分支 (如main、develop)
本地分支 或未推送的分支
冲突处理
在合并提交时一次性解决 所有冲突
在“移动”每个提交时都可能遇到冲突,需逐个解决
用 Rebase 来清理本地历史,用 Merge 来将工作成果集成到公共代码库。
安装部署
2025 年 11 月 10 日
下午锦浩给我拿U盘提供了几份安装部署文档。
DBeaver(数据库管理工具),FileZilla(FTP/SFTP文件传输工具), MobaXterm(全能终端工具), Notepad++(代码编辑器),oCam(屏幕录制软件),Postman(API测试工具),Xshell(SSH终端客户端)。
1 公司加班是有补贴的,平时20 元/小时,周末30元/ 小时,下班了可以在公司继续学习,提升专业能力,进而涨工资,这才是提高收入的正道。
JDK 安装配置。
1 2 3 4 [admin@localhost ~]$ java -version openjdk version "1.8.0_131" OpenJDK Runtime Environment (build 1 .8 .0 _131-b12) OpenJDK 64 -Bit Server VM (build 25 .131 -b12, mixed mode)
Docker 安装配置。
查看 Docker 版本。
查看 CentOS 虚拟机版本,经尝试后执行以下五个命令 任意一个都可以。
1 2 [admin@localhost ~]$ cat /etc/centos-release CentOS Linux release 7.4.1708 (Core)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [admin@localhost ~]$ cat /etc/os-release NAME="CentOS Linux" VERSION="7 (Core)" ID="centos" ID_LIKE="rhel fedora" VERSION_ID="7" PRETTY_NAME="CentOS Linux 7 (Core)" ANSI_COLOR="0;31" CPE_NAME="cpe:/o:centos:centos:7" HOME_URL="https://www.centos.org/" BUG_REPORT_URL="https://bugs.centos.org/" CENTOS_MANTISBT_PROJECT="CentOS-7" CENTOS_MANTISBT_PROJECT_VERSION="7" REDHAT_SUPPORT_PRODUCT="centos" REDHAT_SUPPORT_PRODUCT_VERSION="7"
1 centos-release-7-4.1708.el7.centos.x86_64
1 2 [admin@localhost ~]$ uname -r 3.10.0-693.el7.x86_64
1 2 [admin@localhost ~]$ cat /etc/redhat-release CentOS Linux release 7.4.1708 (Core)
1 arm64 文件夹里也有个 docker 安装包,docker-24 .0 .6 .tgz,这与 docker-20 .10 .24 .tgz 有什么区别呢,我的 CentOS7 应该安装哪个?
对于 CentOS 7 系统,您应该安装 docker-20.10.24.tgz这个版本 。
不建议尝试安装 arm64文件夹下的 docker-24.0.6.tgz,主要原因有两个,其中第一个是致命错误:
架构不兼容(最关键原因) :arm64文件夹下的安装包是专门为 ARM 架构 的CPU(例如苹果M系列芯片、某些国产化平台、树莓派等)编译的。而您的CentOS 7系统几乎可以肯定是在 x86_64(即AMD64)架构 的服务器上运行的。强行安装会导致程序根本无法执行。
版本兼容性 :即使架构匹配,Docker 24.x 这样的新版本对旧操作系统的支持也可能不佳,容易遇到依赖库版本等问题。
Linux安装Docker详细教程! 本文已参与「新人创作礼」活动,一起开启掘金创作之路。 前置条件 前置知识 1、 - 掘金
Docker 万字入门教程Docker 使用 Google 公司推出的 Go 语言进行开发实现,对进程进行封装隔离,属于 - 掘金
Centos安装Docker的详细安装步骤,Docker相关组件:docker-ce-cli、docker-ce和containerd.io的区别 - 掘金
1、使用官方便捷脚本安装(最快速,适用于测试)
1 2 3 4 5 6 7 8 9 curl -fsSL https ://get .docker .com -o get-docker.sh sudo sh get-docker.sh
2、配置 yum 源在线安装(最有网络环境下的首选) ,详见卓越之旅栏目下的详细安装过程。
3、使用现有的 .tgz压缩包安装(离线/内网环境首选)
将 docker 安装包 docker-20.10.24.tgz 上传到服务器上
解压,执行以下命令:
1 tar -zxvf docker-20 .10 .24 .tgz
复制,执行以下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [admin@localhost ~]$ cp docker/* /usr/bin/cp : 无法创建普通文件"/usr/bin/containerd" : 权限不够cp : 无法创建普通文件"/usr/bin/containerd-shim" : 权限不够cp : 无法创建普通文件"/usr/bin/containerd-shim-runc-v2" : 权限不够cp : 无法创建普通文件"/usr/bin/ctr" : 权限不够cp : 无法创建普通文件"/usr/bin/docker" : 权限不够cp : 无法创建普通文件"/usr/bin/dockerd" : 权限不够cp : 无法创建普通文件"/usr/bin/docker-init" : 权限不够cp : 无法创建普通文件"/usr/bin/docker-proxy" : 权限不够cp : 无法创建普通文件"/usr/bin/runc" : 权限不够 [admin@localhost ~]$ sudo cp docker/* /usr/bin/ 我们信任您已经从系统管理员那里了解了日常注意事项。 总结起来无外乎这三点: [sudo] admin 的密码: admin 不在 sudoers 文件中。此事将被报告。
切换到 root 用户即可避免。
上传 docker.service,上传 docker.service 到 /etc/systemd/system。
1 cp docker.service /etc/systemd/system
授权,执行以下命令:
1 chmod +x /etc/systemd/system/docker.service
重新加载,执行以下命令:
配置开机启动,执行以下命令:
1 2 [root@localhost system] Created symlink from /etc/ systemd/system/mu lti-user.target.wants/docker.service to / etc/systemd/ system/docker.service.
启动,执行以下命令:
安装成功,查看 Docker 版本。
1 2 [root@localhost system] Docker version 20.10.24, build 297e128
MySQL 安装配置。
SELinux 关闭,查看SELinux 是否开启:
关闭当前会话的 SELinux ,重启之后无效:
永久关闭 SELinux ,需要重启:
1 sed -i 's/enforcing/disabled/' /etc/selinux/config
上传安装包,将 mysql 安装包 mysql-8.0.30.tar 上传到服务器上。
加载 mysql 镜像。
1 docker load <mysql-8.0.30.tar
1 2 3 4 5 6 7 8 9 10 11 12 13 [root@localhost admin] 553b196ea5e8: Loading layer [==================================================>] 106.8MB/106.8MB 7b1b5089c4c8: Loading layer [==================================================>] 11.26kB/11.26kB 3bf157422b00: Loading layer [==================================================>] 2.293MB/2.293MB dc4bc61c37e8: Loading layer [==================================================>] 13.9MB/13.9MB 3db93db6878c: Loading layer [==================================================>] 7.168kB/7.168kB 91679720f8d1: Loading layer [==================================================>] 3.072kB/3.072kB 7cd76e295a75: Loading layer [==================================================>] 154.4MB/154.4MB feee68c33bd4: Loading layer [==================================================>] 3.072kB/3.072kB 43c8ca9cd771: Loading layer [==================================================>] 183MB/183MB b670df5ea093: Loading layer [==================================================>] 17.41kB/17.41kB e24224578084: Loading layer [==================================================>] 1.536kB/1.536kB Loaded image: mysql:8.0.30
Shell 重定向机制:
1 2 3 4 5 # 实际上发生了这些步骤: # 1. Shell 打开 mysql-8.0.30.tar 文件 # 2. Shell 将文件描述符重定向到标准输入(stdin) # 3. docker load 命令从标准输入读取数据 # 4. Docker 解析镜像数据并存储到本地仓库
创建本地数据和配置目录。
1 2 mkdir -p /data/mysql/data /data/mysql/logs /data/mysql/conf
1 2 chown -R 999:999 /data/mysql/data /data/mysql/logs
1 2 chmod -R 755 /data/mysql/data /data/mysql/logs
创建MySQL容器需要的三个核心目录,并设置用户所有权以及目录权限。
/data/mysql/data:数据库文件目录 (表数据、索引等)
/data/mysql/logs:日志文件目录 (错误日志、慢查询日志等)
/data/mysql/conf:配置文件目录 (my.cnf等)
1 2 3 4 5 6 7 8 9 10 /data/mysql/ ├── data/ │ ├── ibdata1 │ ├── ib_logfile0 │ └── database/ ├── logs/ │ ├── error .log │ └── slow.log └── conf/ └── my .cnf
创建 MySQL 配置文件。
1 cat > /data/mysql/conf/my.cnf <<EOF
创建文件并写入内容,用于多行文本输入,文件将保存在:/data/mysql/conf/my.cnf。
1 2 3 4 5 6 7 8 9 10 11 12 13 [mysqld] port=3306 datadir=/var/lib/mysql socket=/tmp/mysql.sock pid-file=/var/run/mysqld/mysqld.pid character-set-server=utf8mb4 symbolic-links=0 user=mysql lower-case-table-names=1 log-error=/var/log/mysql/error.log sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' default_authentication_plugin=mysql_native_password EOF
1 2 3 4 5 6 7 8 9 10 11 12 13 [mysqld] port=3306 datadir=/var/lib/mysql socket=/tmp/mysql.sock pid-file=/var/run/mysqld/mysqld.pid user=mysql symbolic-links=0 character-set-server=utf8mb4 lower-case-table-names=1 log-error=/var/log/mysql/error.log sql_mode='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION' default_authentication_plugin=mysql_native_password EOF
启动容器(注意修改密码)。
1 2 3 4 5 6 7 8 9 10 docker run -d \ --name mysql-server \ -p 3306:3306 \ -v /data/mysql/data:/var/lib/mysql \ -v /data/mysql/logs:/var/log/mysql \ -v /data/mysql/conf/my.cnf:/etc/mysql/my.cnf:ro \ -e MYSQL_ROOT_PASSWORD=Mysql@89s -e TZ=Asia/Shanghai \ --restart=unless-stopped \ mysql:8.0.30
1 2 3 4 5 6 7 8 9 10 docker run -d \ --name mysql-server \ -p 3306:3306 \ -v /data/mysql/data:/var/lib/mysql \ -v /data/mysql/logs:/var/log/mysql \ -v /data/mysql/conf/my.cnf:/etc/mysql/my.cnf:ro \ -e MYSQL_ROOT_PASSWORD=Mysql@89s -e TZ=Asia/Shanghai \ --restart=unless-stopped \ mysql:8.0.30
1 2 3 4 5 6 7 8 9 10 11 [root@localhost admin] > --name mysql-server \ > -p 3306:3306 \ > -v /data/mysql/data:/var/lib/mysql \ > -v /data/mysql/logs:/var/log/mysql \ > -v /data/mysql/conf/my.cnf:/etc/mysql/my.cnf:ro \ > -e MYSQL_ROOT_PASSWORD=Mysql@89s > -e TZ=Asia/Shanghai \ > --restart=unless-stopped \ > mysql:8.0.30 9bc7fd9dd0c7a1f0fabf6d8b3cf712aef5a6ed89d6a19180a6be163ad30c067f
Redis 安装配置。
上传安装包,将安装包 redis-4.0.11.tar 上传到服务器上。
加载 redis 镜像。
1 docker load <redis-4.0.11.tar
创建配置目录和数据目录。
1 mkdir -p /data/redis/conf /data/redis/data
创建配置文件并设置密码(注意修改密码)。
1 cat > /data/redis/conf/redis.conf <<EOF
1 2 3 4 5 requirepass Redis@89sdir /data port 6379bind 0.0.0.0 EOF
启动 Redis 4.0.11 容器。
1 2 3 4 5 6 7 8 docker run -d \ --name redis-server \ -p 6379:6379 \ -v /data/redis/conf/redis.conf:/etc/redis.conf \ -v /data/redis/data:/data \ --restart=always \ redis:4.0.11 \ redis-server /etc/redis.conf
Nginx 安装配置。
使用nginx -v命令可以直接显示Nginx的版本信息。
使用nginx -V命令可以显示更详细的版本信息,包括编译选项和模块信息。
上传安装包,将 Nginx 安装包 nginx-1.24.0.tar 上传到服务器上。
加载 nginx 镜像,执行以下命令,这个命令用于将一个名为 nginx-1.24.0.tar的归档文件中的 Docker 镜像加载到您的本地 Docker 环境中,使其可以用于创建和运行容器。
1 docker load <nginx-1.24.0.tar
1 2 3 4 5 6 7 8 [root@localhost admin] 420179ad2efa: Loading layer [==================================================>] 84.18MB/84.18MB 13c8460bfc9a: Loading layer [==================================================>] 62.52MB/62.52MB b9a187a24e19: Loading layer [==================================================>] 3.584kB/3.584kB 96c08fed6a4c: Loading layer [==================================================>] 4.608kB/4.608kB 29492f82bbc2: Loading layer [==================================================>] 3.584kB/3.584kB bc4a3582faa9: Loading layer [==================================================>] 7.168kB/7.168kB Loaded image: nginx:1.24.0
启动 Nginx 容器(这里先启动复制文件到宿主机)
1 docker run --name nginx -d nginx:1.24.0
1 2 [root@localhost admin] 2e536e8ba09f054a20e558c0f34a21575ff00a15ec544b3e0ab53562ac517c3a
创建目的挂载路径
1 mkdir -p /data/nginx/conf /data/nginx/log /data/nginx/html
1 2 3 4 5 /data/ └── nginx/ ├── conf/ ├── log/ └── html/
复制容器
1 2 docker cp nginx:/etc/nginx/nginx.conf /data/nginx/conf/nginx.conf
1 2 docker cp nginx:/etc/nginx/conf.d /data/nginx/conf/conf.d
1 2 docker cp nginx:/usr/share/nginx/html /data/nginx
删除临时容器
1 2 [root@localhost admin] nginx
这个临时容器是我们之前为了获取Nginx默认配置文件而故意创建的 。如果直接运行并挂载空目录,容器内的 /etc/nginx目录会被宿主机空目录覆盖,Nginx因缺少配置文件而启动失败
这个”临时容器”是有意创建且短期存在的 ,为了获取Nginx默认配置,完成配置复制后就可以删除。它的配置已经保存到宿主机,所以现在要删除它,然后用持久化的配置重新创建一个”正式容器”。
启动正式容器
1 2 3 4 5 6 7 8 9 docker run \ -p 80:80 \ -p 10001:10001 \ --name nginx \ -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \ -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \ -v /data/nginx/log:/var/log/nginx \ -v /data/nginx/html:/usr/share/nginx/html \ -d nginx:1.24.0
1 2 3 4 5 6 7 8 9 docker run \ -p 80:80 \ -p 10001:10001 \ --name nginx \ -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \ -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \ -v /data/nginx/log:/var/log/nginx \ -v /data/nginx/html:/usr/share/nginx/html \ -d nginx:1.24.0
1 2 3 4 5 6 7 8 9 10 [root@localhost admin] > -p 80:80 \ > -p 10001:10001 \ > --name nginx \ > -v /data/nginx/conf/nginx.conf:/etc/nginx/nginx.conf \ > -v /data/nginx/conf/conf.d:/etc/nginx/conf.d \ > -v /data/nginx/log:/var/log/nginx \ > -v /data/nginx/html:/usr/share/nginx/html \ > -d nginx:1.24.0 0a4ea3bae5b05b007da2ece6ca6f0d03e46d154c0e7356ea32fe8353c40704a0
挂载,双向同步。
SELinux 配置。
1 SELinux 是一个内置于 Linux 内核的安全子系统,提供更精细的访问控制,以增强系统安全性。
getenforce 这个命令用于快速查看 SELinux 的当前运行模式 ,通常会返回三种结果之一:
Enforcing:表示 强制模式 。SELinux 正在运行,并且会强制执行安全策略,阻止任何未经授权的访问。
Permissive:表示 宽容模式 。SELinux 会记录安全违规行为,但不会实际阻止这些操作。这个模式常用于故障排除和策略调试。
Disabled:表示 已关闭 。SELinux 已被完全禁用
setenforce 0 这个命令能将 SELinux 从 Enforcing(强制模式)立即切换 到 Permissive(宽容模式),而无需重启系统
永久关闭 SELinux ,需要重启后生效:
1 sed -i 's/enforcing/disabled/' /etc/selinux/config
防火墙设置
防火墙查看开放的端口。
1 firewall-cmd --list-ports
防火墙添加3306端口。
1 sudo firewall-cmd --permanent --add-port=3306/tcp
1 sudo firewall-cmd --permanent --add-port=6379/tcp
1 sudo firewall-cmd --permanent --add-port=80/tcp
1 sudo firewall-cmd --permanent --add-port=10051/tcp
1 sudo firewall-cmd --permanent --add-port=10052/tcp
1 sudo firewall-cmd --permanent --add-port=8080/tcp
防火墙重新加载。
1 sudo firewall-cmd --reload
防火墙状态。
1 sudo firewall-cmd --state
2025 年 11 月 11 日
Zabbix-Web 服务启动后果真有问题。
检查容器是否真正启动成功。
1 2 docker logs --tail 20 zabbix-web-nginx-mysql
1 2 3 4 5 6 7 8 9 [root@localhost admin] **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds... **** MySQL server is not available. Waiting 5 seconds...
检查网络连通性。
1 2 3 docker exec zabbix-web-nginx-mysql ping 192.168.10.195 docker exec zabbix-web-nginx-mysql nc -zv 192.168.10.195 3306
先把 Zabbix 的问题放一放。
运行监测平台
监测平台服务端。
连接已经启动的 MySQL 服务。
1 2 192.168.139.128 Mysql@89s#
2025 年 11 月 13 日
创建数据库
1 CREATE DATABASE IF NOT EXISTS sx_aiops CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
导入外部数据, sx_aiops_original.sql。
执行成功。
上传后端应用包 tomm-rmgt-server.jar 和启动文件 sxrmgt.sh 到部署目录。在部署目录执行./sxrmgt.sh start 启动、./sxrmgt.sh stop关闭、./sxrmgt.shrestart重启。
1 cp /home/admin tomm-aiops-server.jar /opt/tomm_server
1 chmod 777 /home/admin/sxrmgt.sh
1 cp /home/admin sxrmgt.sh /opt/tomm_server
后端应用端口号为 8880。
登录测试
默认账号密码:
1 2 tail -f nohup.outadmin yxjcgly202407!!AA
1 2 3 4 5 6 7 8 [root@localhost tomm_server] ./sxrmgt.sh: line 1: $'\r' : command not found ./sxrmgt.sh: line 3: $'\r' : command not found ./sxrmgt.sh: line 10: $'\r' : command not found : No such file or directoryopt/tomm_server ./sxrmgt.sh: line 12: $'\r' : command not found ./sxrmgt.sh: line 13: syntax error near unexpected token `$'in\r' ' ' /sxrmgt.sh: line 13: `case "$1 " in
这个错误是因为脚本文件包含了 Windows 的换行符(\r\n),而在 Linux 环境下无法识别。需要将文件格式转换为 Unix 格式。
转换文件格式 :
1 sed -i 's/\r$//' sxrmgt.sh
检查脚本语法 :
给执行权限 :
执行脚本 :
1 2 3 [root@localhost tomm_server] === start tomm-aiops-server [root@localhost tomm_server]
查看是否启动。
1 netstat -tuln | grep 8880
有显示信息则启动成功。
妈的,文档里是在部署智能运维系统,重新打包一份运行监测 jar 包部署下试试。
1 cp /home/admin tomm-mgt-server.jar /opt/tomm_server
启动项目总是显示数据库连接失败,那就把配置文件里数据库配置信息修改成本机虚拟机 ip 地址,同时连接 Docker 容器里启动的 MySQL 服务,待成功执行 SQL 脚本填充库表数据后,再尝试部署项目。
1 D :\Project\luofeng\tomm-mgt-server\script\sql\mysql
1 url: jdbc:mysql://192.168.139.128:3306/sx_monitor?useUnicode=true &characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true &serverTimezone=GMT%2B8&autoReconnect=true &rewriteBatchedStatements=true &nullCatalogMeansCurrent=true &allowMultiQueries=true
徒劳了,该监测平台连接本地 MySQL 连用户名密码都不一致,这样要改动的配置就更多了,等到正式开发的时候问问就搞定的事情。
不考虑本机部署监测平台项目了,接下来的时间就用来研究 Zabbix 和具体的业务逻辑。
安装部署,到此结束。
Zabbix
2025 年 11 月 13 日
分布式监控平台——Zabbix监控 一、监控的功能 在需要的时刻,提前预警即将出问题,避免故障发生 实时监控系统和业务, - 掘金
zabbix分布式监控平台zabbix监控系统概述 zabbix 是什么? zabbix 是一个基于 Web 界面的提供 - 掘金
zabbix介绍及部署(超详细讲解) - 靖安yj - 博客园
工作流程:
Zabbix 在进行监控时,zabbix 客户端要安装在被监控设备上,负责定期收集数据,并将其发送给 zabbix 服务端;
zabbix 服务端要安装在监控设备上,其将 zabbix 客户端发送的数据存储的数据库中,zabbix web 根据数据在前端进行展示和绘图。
工作模式:
主动模式:zabbix 客户端主动向 zabbix server请求监控项列表,并主动将监控项内需要的数据提交给 zabbix server。
被动模式:zabbix server向 agent 请求获取监控项的数据,zabbix agent 返回数据。
1 zabbix 的主动和被动模式是以 zabbxi 客户端为基准的。
五个模块。
Zabbix_Server:zabbix_server作为核心组件,用来获取agent存活情况和监控数据。所有的配置、统计、操作数据均通过server进行存取到database;
Zabbix_Database:用户存储所有的zabbix的配置信息、监控数据的数据库;
Zabbix_Web:zabbix的web界面,管理员通过web界面管理zabbix配置以及查看zabbix相关监控信息,通常与zabbix_server运行在同一台主机上,也可以单独部署在独立的服务器上;
Zabbix_Proxy:通常用于分布式监控,代理zabbix_server收集部分被监控的数据并统一发送给server端;(通常大于500台主机需要使用)
Zabbix_Agent:部署在被监控主机上,负责收集被监控主机的数据,并发送给servre端或者proxy端;
Zabbix Server、Proxy、Agent都有自己的配置文件以及log文件,重要的参数需要在这里配置,后面会详细说明。
六个进程。
在默认的情况下,zabbix有6个工作进程;分别是 zabbix_agentd,zabbix_get,zabbix_proxy,zabbix_sender,zabbix_server 和 zabbix_gateway。
其中,zabbix_java_gateway 是可选进程。这6个进程的作用如下:
zabbix-agentd 为 zabbix 客户端守护进程 ,主要负责收集客户端监控项数据。
zabbix_server 为zabbix服务端守护进程,主要负责收集zabbix客户端数据。(端口为10051)
zabbix_proxy是zabbix的代理程序,其功能类似于server,作用上类似于一个中转站,最终会把收集的数据再次提交给zabbix_server。
zabbix_get作为zabbix工具,通常运行在zabbix_server或者zabbix_proxy上,用于远程获取客户端信息,通常用于排错。
zabbix_sender也是zabbix的一个工具,通常运行在zabbix的客户端,用于耗时比较长的检查,其作用是主动发送数据。
zabbix_java_gateway是zabbix2.0以后引入的新功能,可以用于JAVA方面的设备;但是只能主动获取数据,而不能被动获取数据。
三种框架。
在实际的工作环境中,根据网络环境和监控的规模不同,zabbix一共有三种框架,分别是server_client架构、master_node_client架构和server_proxy_client架构。
1、server_client架构
zabbix最简单的架构,监控设备和被监控设备之间直接相连,zabbix_server 和 zabbix_client 之间直接进行数据交互。
2、zabbix_proxy_client架构
proxy是连接 server 和 client 之间的桥梁,其本身不存放数据,只是将zabbix_agent端发来的数据暂存,然后再提交给server。这种架构一般用于跨机房、跨网络的中型网络架构。
在server_proxy_client架构中,server设备的宕机会导致整个系统瘫痪而无法正常工作。
3、master_node_client架构
master_node_client架构是zabbix最复杂的架构。一般用于跨机房、跨网络、监控设备较多的大型网络架构。与server_proxy_client架构相比,master_node_client架构的主要区别在于node与proxy上.
在master_node_client架构中,每个node可以理解为一个小的server端,在自己的配置文件和数据库,node下游可以直接连接client,也可以再次经过proxy代理后连接client。
在master_node_client架构中,master设备宕机不会影响node节点的正常工作。
2025 年 11 月 11 日
zabbix介绍及部署(超详细讲解) - 靖安yj - 博客园
2025 年 11 月 10 日
Zabbix:企业级开源监控解决方案
zabbix分布式监控平台zabbix监控系统概述 zabbix 是什么? zabbix 是一个基于 Web 界面的提供 - 掘金
1 2 3 Zabbix 是一个企业级开源分布式监控解决方案。 Zabbix 是一种监控网络众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等健康状况和完整性的软件。Zabbix 使用灵活的通知机制,允许用户为几乎任何事件配置基于电子邮件的警报,从而快速响应服务器问题。Zabbix 提供基于存储数据的优秀报告和数据可视化功能,使其非常适合容量规划。
Zabbix 安装配置
安装 zabbix-java-gateway。
先上传 zabbix-java-gateway.latest.tar。
docker 加载镜像。
1 docker load <zabbix-java-gateway.latest.tar
docker 启动。
1 docker run --name zabbix-java-gateway -t --restart=unless-stopped -p 10052:10052 -e TZ=Asia/Shanghai -d zabbix/zabbix-java-gateway:latest
1 2 3 4 5 docker run --name zabbix-java-gateway -t \ --restart=unless-stopped \ -p 10052:10052 \ -e TZ=Asia/Shanghai \ -d zabbix/zabbix-java-gateway:latest
Zabbix Java Gateway 是一个独立的守护进程,专门用于监控 Java应用程序 的 JMX(Java Management Extensions) 指标。
安装 zabbix-server
上传 zabbix-server-mysql.ol-6.4.13.tar。
docker 加载镜像。
1 docker load <zabbix-server-mysql.ol-6.4.13.tar
1 2 3 4 5 6 7 8 9 10 11 12 [root@localhost admin] 0a628c3f1dfa: Loading layer [==================================================>] 114.3MB/114.3MB 9f123eed27d1: Loading layer [==================================================>] 5.131MB/5.131MB f1a18cee03fd: Loading layer [==================================================>] 174.6kB/174.6kB 1b8a4a73d477: Loading layer [==================================================>] 328.2kB/328.2kB 4c55089aa5fe: Loading layer [==================================================>] 30.21kB/30.21kB acb81b6f8559: Loading layer [==================================================>] 4.135MB/4.135MB 4694e9d5278c: Loading layer [==================================================>] 3.072kB/3.072kB 843f0fd7d625: Loading layer [==================================================>] 115.6MB/115.6MB 5f70bf18a086: Loading layer [==================================================>] 1.024kB/1.024kB 6f7ed932e3b9: Loading layer [==================================================>] 24.58kB/24.58kB Loaded image: zabbix/zabbix-server-mysql:ol-6.4.13
docker启动(注意数据库root密码)。
1 docker run --name zabbix-server-mysql -t -v zabbix_server:/etc/zabbix -e TZ=Asia/Shanghai -e DB_SERVER_HOST="192.168.10.195" -e MYSQL_DATABASE="zabbix" -e MYSQL_USER="zabbix" -e MYSQL_PASSWORD="Zabbix@89s#" -e MYSQL_ROOT_PASSWORD="Mysql@89s#" -e ZBX_JAVAGATEWAY="zabbix-java-gateway" --restart=unless-stopped -p 10051:10051 --user=root -d zabbix/zabbix-server-mysql:ol-6.4.13
1 2 3 4 5 6 7 8 9 10 11 12 13 docker run --name zabbix-server-mysql -t \ -v zabbix_server:/etc/zabbix \ -e TZ=Asia/Shanghai \ -e DB_SERVER_HOST="192.168.10.195" \ -e MYSQL_DATABASE="zabbix" \ -e MYSQL_USER="zabbix" \ -e MYSQL_PASSWORD="Zabbix@89s#" \ -e MYSQL_ROOT_PASSWORD="Mysql@89s#" \ -e ZBX_JAVAGATEWAY="zabbix-java-gateway" \ --restart=unless-stopped \ -p 10051:10051 \ --user=root \ -d zabbix/zabbix-server-mysql:ol-6.4.13
安装 zabbix-web
上传 zabbix-web-nginx-mysql.latest.tar。
docker 加载镜像。
1 docker load < zabbix-web-nginx-mysql.latest.tar
1 2 3 4 5 6 7 [root@localhost admin] b5221e4692d2: Loading layer [==================================================>] 98.55MB/98.55MB 72523de8d6bb: Loading layer [==================================================>] 27.14kB/27.14kB da371a8f2857: Loading layer [==================================================>] 143.6MB/143.6MB 5f70bf18a086: Loading layer [==================================================>] 1.024kB/1.024kB ce903e83adf6: Loading layer [==================================================>] 11.78kB/11.78kB Loaded image: zabbix/zabbix-web-nginx-mysql:latest
docker启动(注意数据库 root 密码)。
1 docker run --name zabbix-web-nginx-mysql -t -e PHP_TZ="Asia/Shanghai" -e ZBX_SERVER_HOST="192.168.10.195" -e DB_SERVER_HOST="192.168.10.195" -e MYSQL_DATABASE="zabbix" -e MYSQL_USER="zabbix" -e MYSQL_PASSWORD="Zabbix@89s#" -e MYSQL_ROOT_PASSWORD="Mysql@89s#" -p 8080:8080 --restart unless-stopped --user=root -d zabbix/zabbix-web-nginx-mysql:latest
1 2 3 4 5 6 7 8 9 10 11 12 docker run --name zabbix-web-nginx-mysql -t \ -e PHP_TZ="Asia/Shanghai" \ -e ZBX_SERVER_HOST="192.168.10.195" \ -e DB_SERVER_HOST="192.168.10.195" \ -e MYSQL_DATABASE="zabbix" \ -e MYSQL_USER="zabbix" \ -e MYSQL_PASSWORD="Zabbix@89s#" \ -e MYSQL_ROOT_PASSWORD="Mysql@89s#" \ -p 8080:8080 \ --restart unless-stopped \ --user=root \ -d zabbix/zabbix-web-nginx-mysql:latest
默认账号和密码:
更新容器中 /usr/share/zabbix/include/defines.inc.php,解决名称无法中文问题。
覆盖容器内文件:
1 docker cp defines.inc.php zabbix-web-nginx-mysql:/usr/share/zabbix/include/defines.inc.php
进入容器:
1 docker exec -it zabbix-web-nginx-mysql bash
授权文件:
1 chmod +r /usr/share/zabbix/include/defines.inc.php
重启容器:
1 docker restart zabbix-web-nginx-mysql
上传模板
删除 模板中的system.sw.os键值(模板监控项)
先导入zbx_export_templates (34).yaml再导入zbx_export_templates (33).yaml
添加主机群组公司名、公司名/收费站服务器、公司名/车道工控机、公司名/门架工控机/、公司名/门架服务器。
安装 zabbix-sender
上传 zabbix-sender-6.4.7-release1.el8.x86_64.rpm。
安装。
1 rpm -ivh zabbix-sender-6.4.7-release1.el8.x86_64.rpm
1 2 3 4 5 6 7 8 [root@localhost admin] warning: zabbix-sender-6.4.7-release1.el8.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID a14fe591: NOKEY error: Failed dependencies: libcrypto.so.1.1()(64bit) is needed by zabbix-sender-6.4.7-release1.el8.x86_64 libcrypto.so.1.1(OPENSSL_1_1_0)(64bit) is needed by zabbix-sender-6.4.7-release1.el8.x86_64 libssl.so.1.1()(64bit) is needed by zabbix-sender-6.4.7-release1.el8.x86_64 libssl.so.1.1(OPENSSL_1_1_0)(64bit) is needed by zabbix-sender-6.4.7-release1.el8.x86_64 libssl.so.1.1(OPENSSL_1_1_1)(64bit) is needed by zabbix-sender-6.4.7-release1.el8.x86_64
这个错误表明 Zabbix Sender 需要 OpenSSL 1.1 版本的库 ,但该系统可能缺少或版本不匹配。
检查当前 OpenSSL 版本。
1 2 [root@localhost admin] OpenSSL 1.0.2k-fips 26 Jan 2017
1 2 3 4 [root@localhost admin] xmlsec1-openssl-1.2.20-5.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 openssl-1.0.2k-8.el7.x86_64
解决办法,不奏效。
1 sudo rpm -ivh compat-openssl10-1.0.2o-4.el8_6.x86_64.rpm
1 2 3 4 5 6 [root@localhost admin] warning: compat-openssl10-1.0.2o-4.el8_6.x86_64.rpm: Header V4 RSA/SHA256 Signature, key ID c21ad6ea: NOKEY error: Failed dependencies: crypto-policies is needed by compat-openssl10-1:1.0.2o-4.el8_6.x86_64 openssl < 1:1.1.0 conflicts with compat-openssl10-1:1.0.2o-4.el8_6.x86_64 openssl-libs < 1:1.1.0 conflicts with compat-openssl10-1:1.0.2o-4.el8_6.x86_64
先强制安装 zabbix-sender。
1 sudo rpm -ivh --nodeps zabbix-sender-6.4.7-release1.el8.x86_64.rpm
1 2 3 4 5 [root@localhost admin] warning: zabbix-sender-6.4.7-release1.el8.x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID a14fe591: NOKEY Preparing... Updating / installing... 1:zabbix-sender-6.4.7-release1.el8
再手动补全缺失的 so 文件。
1 2 3 4 5 6 7 8 find /usr/lib64 -name "libssl.so*" find /usr/lib64 -name "libcrypto.so*" sudo ln -s /usr/lib64/libssl.so.1.1.1 /usr/lib64/libssl.so.1.1 sudo ln -s /usr/lib64/libcrypto.so.1.1.1 /usr/lib64/libcrypto.so.1.1 sudo ldconfig
最后验证是否修复。
1 ldd $(which zabbix_sender)
1 2 3 4 5 6 7 8 9 10 11 12 [root@localhost admin] linux-vdso.so.1 => (0x00007ffd227a0000) libz.so.1 => /lib64/libz.so.1 (0x00007fe792969000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fe79274d000) libssl.so.1.1 => not found libcrypto.so.1.1 => not found libm.so.6 => /lib64/libm.so.6 (0x00007fe79244a000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fe792245000) libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fe79202b000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fe791db4000) libc.so.6 => /lib64/libc.so.6 (0x00007fe7919f0000) /lib64/ld-linux-x86-64.so.2 (0x000055f119672000)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 [root@localhost admin] /usr/lib64/libcrypto.so.1.0.2k /usr/lib64/libcrypto.so.10 /usr/lib64/libssl.so.1.0.2k /usr/lib64/libssl.so.10 [root@localhost admin] lrwxrwxrwx. 1 root root 16 Nov 5 01:10 /usr/lib64/libssl.so.10 -> libssl.so.1.0.2k -rwxr-xr-x. 1 root root 470336 Aug 3 2017 /usr/lib64/libssl.so.1.0.2k [root@localhost admin] lrwxrwxrwx. 1 root root 19 Nov 5 01:10 /usr/lib64/libcrypto.so.10 -> libcrypto.so.1.0.2k -rwxr-xr-x. 1 root root 2512448 Aug 3 2017 /usr/lib64/libcrypto.so.1.0.2k [root@localhost admin] xmlsec1-openssl-1.2.20-5.el7.x86_64 openssl-libs-1.0.2k-8.el7.x86_64 openssl-1.0.2k-8.el7.x86_64
该系统是 CentOS 7 ,安装的是 OpenSSL 1.0.2k ,但 Zabbix Sender 需要的是 OpenSSL 1.1.x 。这就是版本不匹配的根本原因。
接下来整体的解决思路是这样的:
方案一:安装 OpenSSL 1.1(推荐)
由于有内网 yum 源,直接安装 OpenSSL 1.1:
1 2 3 4 5 6 7 sudo yum install openssl11 openssl11-libs sudo ln -sf /usr/lib64/openssl11/libssl.so.1.1 /usr/lib64/libssl.so.1.1 sudo ln -sf /usr/lib64/openssl11/libcrypto.so.1.1 /usr/lib64/libcrypto.so.1.1 sudo ldconfig
方案二:如果方案一失败,使用兼容方案
1 2 3 4 sudo ln -sf /usr/lib64/libssl.so.1.0.2k /usr/lib64/libssl.so.1.1 sudo ln -sf /usr/lib64/libcrypto.so.1.0.2k /usr/lib64/libcrypto.so.1.1 sudo ldconfig
方案三:下载 CentOS 7 兼容的 Zabbix Sender
1 2 3 4 5 sudo rpm -e zabbix-sender
立即验证,验证是否修复。
1 ldd $(which zabbix_sender)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 [root@localhost admin] /bin/zabbix_sender: /lib64/libcrypto.so.1.1: version `OPENSSL_1_1_0' not found (required by /bin/zabbix_sender) /bin/zabbix_sender: /lib64/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by /bin/zabbix_sender) /bin/zabbix_sender: /lib64/libssl.so.1.1: version `OPENSSL_1_1_0' not found (required by /bin/zabbix_sender) linux-vdso.so.1 => (0x00007fff7bff9000) libz.so.1 => /lib64/libz.so.1 (0x00007fa037cc2000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fa037aa6000) libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007fa037833000) libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007fa0373d2000) libm.so.6 => /lib64/libm.so.6 (0x00007fa0370d0000) libdl.so.2 => /lib64/libdl.so.2 (0x00007fa036ecb000) libresolv.so.2 => /lib64/libresolv.so.2 (0x00007fa036cb1000) libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007fa036a3a000) libc.so.6 => /lib64/libc.so.6 (0x00007fa036676000) /lib64/ld-linux-x86-64.so.2 (0x0000564d9803d000) libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007fa036429000) libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007fa036141000) libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007fa035f3c000) libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007fa035d09000) libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007fa035afa000) libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007fa0358f6000) libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fa0356ce000) libpcre.so.1 => /lib64/libpcre.so.1 (0x00007fa03546c000)
查看。
1 2 3 4 [root@localhost admin] zabbix_sender: /lib64/libcrypto.so.1.1: version `OPENSSL_1_1_0' not found (required by zabbix_sender) zabbix_sender: /lib64/libssl.so.1.1: version `OPENSSL_1_1_1' not found (required by zabbix_sender) zabbix_sender: /lib64/libssl.so.1.1: version `OPENSSL_1_1_0' not found (required by zabbix_sender)
目前还是这样的问题。
考虑到生产环境下在内网中操作,最可靠的解决方案还是:重新安装兼容 CentOS 7 的 Zabbix Sender。
1 2 3 4 5 sudo rpm -e zabbix-sender
Download and install Zabbix
搞半天安装的 zabbix-sender-6.4.7-release1.el8.x86_64.rpm是问题的根源,这是为 CentOS 8 构建的包,但我的系统是 CentOS 7 。
1 2 3 4 5 被监控主机 ──────────────────> Zabbix Server ─────────────────> 用户 │ │ │ ├─ zabbix-agent2 (被动采集) │ │ ├─ zabbix-sender (主动上报) ├─ 数据处理/存储 ├─ zabbix-web (界面) └─ Java应用 ─> Java Gateway └─ 告警判断 └─ 图表展示
各组件端口说明。
组件
默认端口
方向
用途
zabbix-server
10051
入站
接收 agent/sender 数据
zabbix-agent2
10050
出站
向 server 发送数据
zabbix-java-gateway
10052
入站
接收 JMX 监控数据
zabbix-web
80/443
入站
Web 管理界面
1 netstat -natp | grep zabbix
先跳过。
安装 zabbix-agent2
Centos
上传zabbix-agent2-6.4.7-releasel.e18.x86_64.rpm
安装rpm -ivh zabbix-agent2-6.4.7-release1.el8.x86_64.rpm
vi /etc/zabbix/zabbix_agent2.conf
主要修改以下配置:
Server=::/0 #允许所有地址访问
ServerActive=10.14.210.139 #Zabbix Proxy地址
Hostname=Zabbix Server 1 #需要与Zabbix Server的配置一致
默认监听端口是10050,不用修改。
设置开机启动systemctl enable zabbix-agent2
启动systemctl start zabbix-agent2
查看日志,看看是否运行正常
tail -f /var/log/zabbix/zabbix_agent2.log
或者看看端口是否启动
netstat -tanlp |grep 10050
Window Server
浏览器 输入127.0.0.1:9009
打开服务services.msc
ServerActive 改为 10.14.128.76:12099
Server 改为 ::/0
容器
上传zabbix-agent2-alpine-6.4-latest.tar
加载镜像docker load <zabbix-agent2-alpine-6.4-latest.tar
启动容器(替换ip这里需要两个ip,后边的ip需要启动后查看报错ip并替换重启)
docker run –name zabbix-agent2 -t -e TZ=Asia/Shanghai -e ZBX_SERVER_HOST=”10.14.139.226” -e ZBX_HOSTNAME=”Zabbix server” -v /var/run/docker.sock:/var/run/docker.sock:ro -p 10050:10050 –restart=unless-stopped -d zabbix/zabbix-agent2:alpine-6.4-latest
收费系统
2026 年 1 月 13 日
1 2 3 C :\WINDOWS\system32>ssh -T git@101.227.48.102 git @101.227.48.102 's password:Connection closed by 101.227.48.102 port 22
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 C: \WINDOWS\system32>ssh -T -v git@101.227 .48.102 OpenSSH_for_Windows_9.5 p1, LibreSSL 3.8 .2 debug1: Reading configuration data C:\\Users\\Lenovo/.ssh/configdebug1: Connecting to 101.227 .48.102 [101.227 .48.102 ] port 22 .debug1: Connection established.debug1: identity file C:\\Users\\Lenovo/.ssh/id_rsa type 0 debug1: identity file C:\\Users\\Lenovo/.ssh/id_rsa-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ecdsa type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ecdsa-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ecdsa_sk type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ecdsa_sk-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ed25519 type 3 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ed25519-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ed25519_sk type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_ed25519_sk-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_xmss type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_xmss-cert type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_dsa type -1 debug1: identity file C:\\Users\\Lenovo/.ssh/id_dsa-cert type -1 debug1: Local version string SSH-2.0 -OpenSSH_for_Windows_9.5 debug1: Remote protocol version 2.0 , remote software version OpenSSH_8.0 debug1: compat_banner: match: OpenSSH_8.0 pat OpenSSH* compat 0 x04000000debug1: Authenticating to 101.227 .48.102 :22 as debug1: load_hostkeys: fopen C:\\Users\\Lenovo/.ssh/known_hosts2: No such file or directorydebug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directorydebug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directorydebug1: SSH2_MSG_KEXINIT sentdebug1: SSH2_MSG_KEXINIT receiveddebug1: kex: algorithm: curve25519-sha256debug1: kex: host key algorithm: ssh-ed25519debug1: kex: server->client cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: nonedebug1: kex: client->server cipher: chacha20-poly1305@openssh.com MAC: <implicit> compression: nonedebug1: expecting SSH2_MSG_KEX_ECDH_REPLYdebug1: SSH2_MSG_KEX_ECDH_REPLY receiveddebug1: Server host key : ssh-ed25519 SHA256:CPXsWA3qquwUoOVeMDDaHHbgsc1zmJWrM01Yoy6hMmIdebug1: load_hostkeys: fopen C:\\Users\\Lenovo/.ssh/known_hosts2: No such file or directorydebug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts: No such file or directorydebug1: load_hostkeys: fopen __PROGRAMDATA__\\ssh/ssh_known_hosts2: No such file or directorydebug1: Host debug1: Found key in C:\\Users\\Lenovo/.ssh/known_hosts:10 debug1: rekey out after 134217728 blocksdebug1: SSH2_MSG_NEWKEYS sentdebug1: expecting SSH2_MSG_NEWKEYSdebug1: SSH2_MSG_NEWKEYS receiveddebug1: rekey in after 134217728 blocksdebug1: get_agent_identities: ssh_get_authentication_socket: No such file or directorydebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_rsa RSA SHA256:18 HfOCQvT8zCV5AVrzxYRzhwO4W0HB0pOhzCk8klaLwdebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_ecdsadebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_ecdsa_skdebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_ed25519 ED25519 SHA256:314L S48LcdNWWV6CRzNlB0/oeBGMioEXuiYGuMtMAAMdebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_ed25519_skdebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_xmssdebug1: Will attempt key : C:\\Users\\Lenovo/.ssh/id_dsadebug1: SSH2_MSG_EXT_INFO receiveddebug1: kex_input_ext_info: server-sig-algs=<ssh-ed25519,ssh-rsa,rsa-sha2-256 ,rsa-sha2-512 ,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521>debug1: SSH2_MSG_SERVICE_ACCEPT receiveddebug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with -mic,passworddebug1: Next authentication method: publickeydebug1: Offering public key : C:\\Users\\Lenovo/.ssh/id_rsa RSA SHA256:18 HfOCQvT8zCV5AVrzxYRzhwO4W0HB0pOhzCk8klaLwdebug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with -mic,passworddebug1: Trying private key : C:\\Users\\Lenovo/.ssh/id_ecdsadebug1: Trying private key : C:\\Users\\Lenovo/.ssh/id_ecdsa_skdebug1: Offering public key : C:\\Users\\Lenovo/.ssh/id_ed25519 ED25519 SHA256:314L S48LcdNWWV6CRzNlB0/oeBGMioEXuiYGuMtMAAMdebug1: Authentications that can continue : publickey,gssapi-keyex,gssapi-with -mic,passworddebug1: Trying private key : C:\\Users\\Lenovo/.ssh/id_ed25519_skdebug1: Trying private key : C:\\Users\\Lenovo/.ssh/id_xmssdebug1: Trying private key : C:\\Users\\Lenovo/.ssh/id_dsadebug1: Next authentication method: password git@101.227 .48.102
1 2 3 4 5 6 7 8 9 10 11 你好,我需要通过 SSH 密钥访问 GitLab 的 Git 仓库。 我的公钥是:ssh -rsa AAAAB3NzaC1yc2BAAA...(你的公钥内容) 公钥指纹是:SHA256:18 Hf0CQvT8zCV5AVrzXYRzhw04W0HB8p0hzCk8kLaLw 请帮我将以上公钥添加到服务器的 git 用户的 ~/.ssh/authorized_keys 文件中, 并确认 SSH 服务的 PubkeyAuthentication 设置为 yes 。 这样我就不需要每次都输入密码了。
2025 年 11 月 17 日
1 glpat-vtQtz1YtzToB6L7W5Cgn
添加了个访问令牌,拉取代码还是报错,算了解决下SSH密钥配置问题吧。
本机重新生成SSH密钥。
1 ssh-keygen -t rsa -b 4096 -C "your_email@example .com
Gitlab平台配置该SSH密钥。
2025 年 11 月 13 日
有哪些常见的Docker容器操作命令?掌握这些Docker命令,让容器管理事半功倍-腾讯云开发者社区-腾讯云
【腾讯文档】加班统计表 https://docs.qq.com/sheet/DTEFLY3p2R0tQV0pU?tab=000001
history 模块 是一个专注于时序数据管理的模块,它通过合理的数据分类存储策略,为系统提供了高效的历史监控数据管理能力。该模块的设计充分考虑了大数据量、高并发场景下的性能需求,通过批量操作、增量同步和定期清理等机制,保证了系统的稳定性和响应速度。
从业务角度看,该模块为整个监控系统提供了数据持久化和历史查询的基础设施,支持上层应用进行趋势分析、报表生成等高级功能。
knowledge 模块 是一个典型的知识库管理系统实现,采用了标准的三层架构和清晰的对象职责划分。该模块提供了知识库内容的完整CRUD操作和基于树形结构的分类菜单管理功能。
代码整体设计规范,使用了MyBatis-Plus等主流框架提高开发效率,同时预留了数据校验等扩展点。虽然存在一些小的代码问题,但整体实现了完整的业务功能,能够满足知识库管理的基本需求。
Section 模块 主要提供高速公路交通监控系统的数据统计、分析和展示功能,支持:
实时监控设备状态和性能指标
告警分析和趋势预测
数据传输质量监控
大屏可视化展示
支持决策分析和问题定位
sync 模块 是TOMM管理系统中的数据同步核心模块,主要负责接收和处理来自路段侧的数据同步请求,实现省中心与路段侧的数据一致性和实时性。该模块支持多种数据类型的同步,包括部门、资产、告警、监控项等18种不同类型的数据。
system 模块 是整个系统的核心模块,主要负责以下关键业务功能:
资产管理 :提供资产信息的CRUD操作,支持资产分类管理、关联关系维护、资产详情记录等功能,区分省中心和路段两级数据管理模式。
告警管理 :实现告警数据的查询、统计、趋势分析、历史记录管理等功能,支持告警级别分类、告警策略匹配、告警关闭和恢复处理。
系统配置 :提供参数配置的CRUD操作、缓存管理、键名唯一性校验等功能,支持系统参数的动态配置和管理。
路段管理 :实现路段信息的基础CRUD操作,支持路段编号、名称、授权码、服务器IP等信息管理。
用户管理 :提供用户分页查询、列表查询和条件过滤等功能,支持多表关联查询。
2025 年 11 月 12 日
已使用的微服务相关组件:
Spring Cloud OpenFeign
项目中通过 @EnableFeignClients 启用了Feign客户端
实现了 SectionApiClient 接口用于服务间调用
配置了动态Feign客户端( DynamicFeignClientConfiguration )
值得注意的是,项目禁用了负载均衡功能( FeignNoLoadBalanceConfig )
分布式消息队列 - Kafka
在多个配置文件中都配置了Kafka相关参数
用于系统间的数据传输和事件驱动
分布式任务调度 - XXL-Job
项目包含了 tomm-xxl-job-admin 模块
用于管理和调度分布式任务
分布式缓存和锁 - Redis/Redisson
使用Redisson客户端操作Redis
实现分布式锁、分布式限流等功能
分布式日志追踪 - TLog
服务监控 - Spring Boot Admin
缺少的典型微服务组件。
项目中没有发现以下典型的微服务核心组件:
服务注册与发现 :没有使用Eureka、Nacos、Consul或Zookeeper等
配置中心 :没有使用Spring Cloud Config或Nacos Config等
API网关 :没有使用Spring Cloud Gateway或Zuul等
服务熔断和限流 :没有使用Sentinel、Hystrix或Resilience4j等
项目架构特点:
多模块单体架构 :虽然项目分为多个模块(tomm-admin、tomm-system、tomm-common等),但这些更像是功能模块的划分,而非独立部署的微服务
分布式能力增强 :项目集成了多种分布式系统常用组件,具备一定的分布式处理能力
动态服务调用 :通过动态Feign客户端,可以灵活调用不同的外部服务
容器化支持 :提供了Docker和Docker Compose配置,支持容器化部署
数据库集群支持 :支持多种数据库,具备处理大数据量的能力总结 该项目是一个增强型的单体应用 ,它采用了多模块的结构设计,并集成了多种分布式系统的常用组件,以提高系统的可靠性、可扩展性和维护性。虽然它没有完整的微服务架构,但已经具备了一些微服务的特性和能力。这种架构适合业务相对稳定、团队规模适中的项目,可以在保持开发效率的同时,为未来可能的微服务拆分打下基础。
2025 年 11 月 11 日
http://101.227.48.102:10080/
http://101.227.48.102:10080/tangxinghua/tomm-mgt-server/-/tree/feature-v2
高速公路联网收费运行监测管理平台 - 大屏
高速公路联网收费运行监测管理平台 - 后台管理
指定拉取 feature-v2 分支:
1 2 export GIT_SSL_NO_VERIFY=true git clone -b feature-v2 http:// 101.227 .48.102 :10080 /tangxinghua/ tomm-mgt-server.git
这四个项目构成了一个从数据采集 -> 智能分析 -> 综合管理 -> 场景应用 的完整闭环:
gantry-sync-server 是数据源头 ,负责采集门架基础数据。
tomm-aiops-server 是智慧引擎 ,对数据进行分析,产生智能洞察。
tomm-mgt-server 是指挥中心 ,基于洞察进行全面的运维决策和管理。
tomm-rmgt-server 是前线哨所 ,在路段层面提供具体的监控视图和操作界面。
看会儿前端代码。
1 2 3 4 5 6 7 8 9 10 11 VUE_APP_BASE_API = '/dev-api' VUE_APP_CONTEXT_PATH = '/' VUE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/login' VUE_APP_XXL_JOB_ADMIN = 'http://localhost:9100/xxl-job-admin'
把安装部署搞定,尝试把前后端项目部署并成功访问,再研究下核心业务逻辑。
2025 年 11 月 10 日
(99+ 封私信 / 82 条消息) ERP、OA、CRM到底啥区别?90% 的企业选错了,别再踩坑! - 知乎
ERP(企业资源计划) ,OA(办公自动化) ,CRM(客户关系管理) 。
高速公路联网收费运行监测管理平台
大屏调用接口。
1 2 3 4 5 6 7 8 @Tag(name = "大屏显示的接口") @RestController @RequestMapping("/big_screen_displa") @Anonymous public class BigScreenDisplaController
资产中心。
1 2 3 4 5 6 7 8 9 @Validated @RequiredArgsConstructor @RestController public class SysLoginController
1 2 3 4 5 6 7 @GetMapping("getRouters") public R<List<RouterVo>> getRouters (Long type)
1 2 3 4 5 6 7 8 9 10 @Tag(name = "资产 Controller") @RestController @RequestMapping("v2/asset") public class AssetController extends BaseController
1 2 3 4 5 6 7 8 9 10 @Tag(name = "资产类型 Controller") @RestController @RequestMapping("v2/asset_type") public class AssetTypeController extends BaseController
1 2 3 4 5 6 7 8 9 10 @Validated @RequiredArgsConstructor @RestController @RequestMapping("/system/dept") public class SysDeptController extends BaseController
1 http:// 101.227 .48.102 :10003 /dev-api/ system/dept/ v2/list
今天的任务,在本地把项目跑起来,再根据安装部署手册初步尝试在本地虚拟机安装基础环境。
业务逻辑的话,稍后放一放,姜总说业务和技术也不复杂,多的是查询接口。
本地启动 tmmo-admin 模块。
1 import sun.font.FontDesignMetrics;
1 2 D:\Project\luofeng\tomm-mgt-server-feature-v2\tomm-common\src\main\java\com\tomm\common\utils\QRCodeUtil1.java:11:16 java: 程序包sun.font不存在
出现这个错误,把 JDK 换成 jDK8 即可。
1 Error running 'TommApplication' Error running TommApplication. Command line is too long. Shorten the command line via JAR manifest or via a classpath file and rerun
在启动 TommApplication时遇到了 “Command line is too long” 的错误。这是一个在Windows系统上使用IntelliJ IDEA开发大型Java项目时常见的问题,主要是因为项目的类路径(classpath)过长,超过了操作系统允许的命令行长度限制。
打开运行/调试配置 在IDEA顶部工具栏,找到并点击当前显示为 TommApplication的运行/调试配置下拉菜单,然后选择 Edit Configurations...。在配置窗口中,找到并点击 Modify options 按钮,在展开的菜单列表中,勾选 Shorten command line 选项 启用缩短命令行功能
完成上一步后,配置界面下方会出现一个名为 Shorten command line 的新下拉菜单。点击它,您会看到两个选择:
**JAR manifest**:IDEA会创建一个临时的JAR文件,并将冗长的类路径信息写入其清单文件(MANIFEST.MF)中。这是常用的方法。
**classpath file**:IDEA会创建一个文本文件来存储类路径,然后在启动命令中引用该文件。
保存配置,重启应用。
1 2 3 2025-11-10 16:55:20 [main] ERROR o.s.boot.SpringApplication - Application run failed org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.tomm.TommApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'TMessageTemplateController' for bean class [com.tomm.web.controller.BaseData.TMessageTemplateController] conflicts with existing, non-compatible bean definition of same name and class [com.tomm.system.controller.TMessageTemplateController]
1 Caused by: java.lang.IllegalStateException: either 'jasypt.encryptor.password' or one of ['jasypt.encryptor.private-key-string' , 'jasypt.encryptor.private-key-location' ] must be provided for Password-based or Asymmetric encryption
这表明应用程序使用了 Jasypt 进行配置加密,但在启动时缺少必要的加密密钥配置。
1 2 3 4 5 6 7 8 9 10 11 12 spring: redis: host: 127.0 .0 .1 port: 6379 database: 0
1 2 3 4 5 jasypt: encryptor: password: lybgeek algorithm: PBEWithMD5AndDES iv-generator-classname: org.jasypt.iv.NoIvGenerator
直接改这个配置:
TommApplication 应用成功启动。
启动 DataCollectionApplication,出现:
1 2 RedisConnectionException: Unable to connect to Redis server: 101.227.50.186/101.227.50.186:6379 ConnectTimeoutException: connection timed out: 101.227.50.186/101.227.50.186:6379
错误原因是应用程序无法连接到指定的Redis服务器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 --- spring: redis: host: 101.227 .50 .186 port: 6379 database: 0 password: ENC(G2lSweX0Vk/aZP42SIaKqYPtv4jYjcWa) timeout: 10s ssl: false
直接连接本地 Redis,也不行,这应该是远程 Redis 服务器出现问题了,先不用管。
顺利启动 MonitorAdminApplication 和 XxlJobAdminApplication 应用。
大屏
2025 年 11 月 5 日
高速公路联网收费运行监测管理平台
高速公路联网收费运行监测管理平台
让高速更“高速”!四川成雅高速试点自由流ETC门架
高速公路龙门架收费详解与未来展望
1 “龙门架分段式收费”是一种高速公路收费模式。龙门架,作为布设在两个相邻收费站之间的设备,主要负责计算收费金额和扣费。这种分段收费的方式,是将高速公路依据相邻的互通立交、入/出口收费站划分为若干个独立的收费区间,每个区间都会独立计算费额。而ETC门架的名称,通常以收费区间两端连接点的名称来命名,例如“花城大道-黄埔大道”。
1 图中所示即为龙门架,它会在车辆经过时自动记录行车路径与时间,进而生成详细的通行流水。在收费站出口处,通常只会显示最后一个匝道的费用情况。若该匝道不收费,则显示为0元;若应收费,则显示相应的匝道费额,客户所见的收费记录即为该费用。
ETC车辆通过龙门架时,其收费金额是根据相邻两个收费站的里程、车型对应的收费标准以及折扣优惠来计算的 ,最终按照“四舍五入”的规则精确到“分”。
对于人工收费车辆 ,则使用CPC卡来记录行车路径,采用分段计费的方式,在出口合并收费,并同样遵循“四舍五入”的规则取整至“元”。
高速收费模式。
首座ETC门架亮相!淮南人路过这里会发现!
高速龙门架激增,你了解ETC门架的双重功能吗
鼓掌!我省正在运营高速首个ETC门架安装完成!(内附视频)
刚连上数字公司 WIFI 的时候进不了这个系统,现在把手机热点关了连数字公司也行了,省点自己的流量。
(99+ 封私信 / 82 条消息) 高速记费门架上,悬挂“不抓拍违章”醒目标牌,这么做的目的是什么? - 知乎
门架的服务器,工控机还有机柜是什么东西?
三者的关系与协同工作流程
我们可以通过一个简单的流程来理解它们如何协同工作:
车辆通行 :一辆装有ETC设备的汽车通过收费门架。
数据采集 :门架上的RSU天线与车辆OBU进行通信,完成交易;摄像机抓拍车辆图像和车牌信息。
边缘处理(工控机) :每个车道的工控机实时处理本车道设备采集的数据,并生成一条原始的通行记录。
数据汇聚(门架服务器) :所有车道的工控机将通行记录上传至安装在机柜 内的门架服务器 。
存储与上传 :门架服务器将所有数据整合、存储,然后通过通信网络实时上传至省级联网中心平台,用于后台计费、清分结算和运行监测。
物理保障(机柜) :在整个过程中,机柜 为内部的工控机 和门架服务器 提供了一个安全、稳定、适宜的运行环境。
省中心,路段公司还有收费站三者之间有什么关系?
所以,它们三者的关系是:
收费站 向 路段公司 负责,是收入的直接“采集器”。
路段公司 向 省中心 负责,是具体业务的“经营者”和“执行者”。
省中心 对所有 路段公司 和 收费站 进行管理和协调,是规则的“制定者”和资金的“清算者”。
保存下大屏页面截图。
1 同事让我研究下高速公路联网收费运行监测管理平台,以及对应的大屏。你就是最红我有些东西确实不太明确,不过你从这个系统中可以告我些什么信息呢。
这个项目一期二期在指什么?
根据您之前提供的平台信息,同事口中的“一期、二期”很可能指:
一期 :指当前已经上线的这个高速公路联网收费运行监测管理平台 本身,它实现了对全省路网、设备、收费业务的初步集中监测和告警。
二期 :可能是在讨论下一步的升级计划 。例如:“二期我们准备把所有的门架设备监控也接进来。”“这个AI分析功能得等到二期才能开发。”“目前大屏显示的是基础数据,二期的可视化效果会更棒。”
作为后台开发人员,在这份工作中,我可能会负责什么样的任务?
你的工作虽然不在收费一线,但却是整个收费系统的大脑和心脏。你每天打交道的主要是服务器、数据库、数据流水、业务参数 。你的核心价值在于保障资金准确、保障系统稳定、保障规则生效、保障数据有用 。
智慧收费 | 高速公路联网收费运行态势智慧感知系统研究及应用-腾讯云开发者社区-腾讯云
公路收费系统。
1 公路收费系统采用省收费中心、路段分中心、收费站的三级管理体制 [1 ]。底层车道系统具备车型判别、信息校验、计费核算功能,支持ETC 、移动支付等自动缴费方式。收费站系统负责数据查询、票据管理及图像稽查,并向下辖车道终端传输基础参数。省级联网中心通过"芸路通" "芸数聚" 等平台实现全路网数据汇总与通行费拆分结算。
公路收费系统是基于信息技术实现道路通行费征收管理的专业化软件体系,其建设与推广受国务院深化收费公路制度改革部署推动。系统通过车道终端设备、收费站管理平台及省级联网系统的三级架构,集成ETC电子不停车收费、移动支付、车牌识别等技术手段,有效提升通行效率并降低运营成本。截至2019年底,全国已实现ETC用户突破1.8亿、货车不停车收费等政策目标,人工车道全面支持移动支付方式 [1]。杭州恒生芸擎、北京捷迅贵德等企业开发的收费系统解决方案,采用”云 边 端”架构与智能分析技术,在浙江等省份实现高效处理能力。
中午十二点吃个饱饭,睡了二十分钟到两点十分醒来。
Jetbrains正式宣布免费,有点猛啊!提到 Jetbrains 这家公司,相信搞开发的同学应该都不陌生。 该公司盛产 - 掘金
软考
2026 年 2 月 27 日
信息系统项目管理师综合知识章节题库 - 信管网
信管网,刷题。
2026 年 2 月 25 日
全国计算机技术与软件专业技术资格(水平)考试
2025 年 11 月 7 日
中国计算机技术职业资格网
希赛网_专注在线职业教育24年
明年上半年可以考信息系统项目管理师 高项,明年下半年可以考系统架构设计师 高项,计划用一年的时间拿下两本软考高级证书。
中级暂不考虑,已经有软件设计师 中项了,
积分入户_百度百科
1 积分入户是中国部分城市基于积分指标体系审核外来务工人员落户资格的户籍管理政策。
(99+ 封私信 / 82 条消息) 信息系统项目管理师证书(高项)有什么用? - 知乎
端口超限
2026 年 1 月 12 日
1 2 3 http: dengrui1Dr@ 20251107
2025 年 11 月 7 日
http://101.227.48.102:10080/
http://101.227.48.102:10080/tangxinghua/tomm-mgt-server/-/tree/feature-v2
1 2 3 4 5 6 Lenovo@LAPTOP-5 U3S75BI MINGW64 /d/ 桌面/新建文件夹 $ git clone http:// 101.227 .48.102 :10080 /tangxinghua/ tomm-mgt-server/-/ tree/feature-v2 Cloning into 'feature-v2' ... fatal: unable to update url base from redirection: asked for : http:// 101.227 .48.102 :10080 /tangxinghua/ tomm-mgt-server/-/ tree/feature-v2/i nfo/refs?service=git-upload-pack redirect: http:// 101.227 .48.102 :10080 /users/ sign_in
这样直接拉取确实能拉取成功,不过为什么只拉下来个README.md文件呢。。
1 2 export GIT_SSL_NO_VERIFY=true git clone http://101.227.48.102/zhm/tomm-rmgt-server.git
1 2 export GIT_SSL_NO_VERIFY=true git clone http://101.227.48.102:10080/tangxinghua/tomm-mgt-server.git
1 2 export GIT_SSL_NO_VERIFY=true git clone http://101.227.48.102:10080/tangxinghua/tomm-mgt-server.git
1 http://101.227.48.102:10080/tangxinghua/tomm-mgt-server/-/tree/feature-v2.git
解决火狐浏览器的(此网址已被限制,此网址使用了一个通常用于网络浏览以外目的的端口,出于安全原因,Firefox 取消了该请求)问题_火狐此计算机已取消连接-CSDN博客
1 此网址已被限制,此网址使用了一个通常用于网络浏览以外目的的端口,出于安全原因,Firefox 取消了该请求
解决方案:
1、在火狐浏览器中输入 about:config
2、在搜索首选项中输入 network.security.ports.banned.override
1 network.security .ports .banned .override
其中,设置开放端口可以使用,来分隔多个端口;使用-表示一个开放端口范围。
3、测试,访问 http://101.227.48.102:10080/。
其实解决方案 DeepSeek 刚刚已经讲明白了,只不过没图没指导完全没看懂在干什么。
解决方法:修改 Firefox 配置
请严格按照以下步骤操作:
第一步:打开 Firefox 配置编辑器
在 Firefox 地址栏中,输入 about:config然后按 Enter。
您会看到一个警告页面,提示“这会失去保修!”或类似内容。点击 “接受风险并继续” 。
第二步:修改安全配置
在顶部的搜索栏中,搜索 security.ports。
这会过滤出与端口限制相关的配置项。我们需要修改的是 security.ports.banned.override。
双击 security.ports.banned.override这一项。
会弹出一个对话框让你输入字符串值。
在输入框中,填入您需要解除限制的端口号 10080。如果您需要允许多个端口,用英文逗号分隔,例如:10080,8081,9000。
点击 “确定” 。
第三步:刷新页面或重新访问网址
现在,回到之前被阻止的标签页,刷新页面 ,或者在新标签页中重新输入网址 http://101.227.48.102:10080。您现在应该可以正常访问该代码仓库了。S
1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDhWwnOcW2CD7mkj08pnmAxQuPvEoBCIo4lwofyh5Gnf4rrrmL5a1dvilwGxVuSNRCTpdCcwU7gire7ira4kiyu1xrPY21H77jC8hmOkYwJ/xFHs9j3uO2qdv6vk3nzMian8ahiN7EgVDBColQVTPMt0zM33sFaP4X6dvqsMwgDZWbgzbViqo7MDWNvyaCZlb14YSeDQZ4K5oQGyzj5jhLNV/ D2PqvSiA4MKiPwMlUMZvuS0NmZWBqoFIbVXeQ21t0ZzIlse+5 ogwki0yAJd1mgInAlyEvYYoDNBvNFgjOyHJ9Rc0LbtIQASu90oap9vXdb2AEOZ0cgDaeeISxUrsmc9N/Sc8La49SHBgazO9ClMq84cyBKECzRo6iHh6SjNGsKNdTdiSuzgO7SUrUQ+mGBBSIyKpuGJ3mhlS6ewzRTq3iC1cZoUzl1VD4/ Buvxds2BIEVSLzfsqC+/RG8rFc7PFo005eFF9d09INoT8Woype59norGGkWikVodAHYlJUs= Lenovo@LAPTOP-5 U3S75BI
1 2 3 4 5 ssh-keygen -t ed25519 -C "your_email@example.com" -f ~/.ssh/i d_ed25519_gitlab ssh-keygen -t rsa -b 4096 -C "your_email@example.com" -f ~/.ssh/i d_rsa_gitlab
执行这个,强制指定生成新密钥后的存放路径。
1 ssh - keygen - t ed25519 - C "dengwei@dengwei.com" - f C : \Users \Lenovo \. ssh \id_ed25519 _gitlab
生成成功,Gitlab 平台添加 SSH 密钥成功。
1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFyb7N7m7i2AY301bcIiPO7QkBgDAnR1H/7 dVrlQw9K1 dengwei@ dengwei.com
测试连接 :
1 ssh -T git@101.227.48.102
首先验证 SSH 密钥是否正确加载
1 2 3 4 5 ssh-add -l ssh-add C:\Users\Lenovo\.ssh\id_ed25519_gitlab # 替换为您的私钥文件路径
出现错误:
1 2 C:\WINDOWS\system32>ssh-add -lError connecting to agent: No such file or directory
这个错误表明 SSH 代理没有运行 。在 Windows 系统中,SSH 代理的管理方式与 Linux/Mac 不同。
Windows 系统下的 SSH 代理管理,使用 Git Bash:
1 2 3 4 eval "$(ssh-agent -s) " ssh-add C:\Users\Lenovo\.ssh\id_ed25519_gitlab ssh-add -l
依次执行命令。
1 2 3 Lenovo@LAPTOP-5 U3S75BI MINGW64 /d/ Project /luofeng $ ssh-add -l The agent has no identities.
1 2 3 Lenovo@LAPTOP-5U3S75BI MINGW64 /d/Project/luofeng $ ssh-add C :\Users\Lenovo\.ssh\id_ed25519_gitlabC :UsersLenovo.sshid_ed25519_gitlab : No such file or directory
1 2 3 Lenovo@LAPTOP-5 U3S75BI MINGW64 /d/ Project /luofeng $ ssh-add C:/Users/ Lenovo/.ssh/i d_ed25519_gitlab Identity added: C:/Users/ Lenovo/.ssh/i d_ed25519_gitlab (dengwei@dengwei.com)
还是不行。。
拉取 Gitee 代码就没有什么问题,这个 Gitlab 平台反复配置完毕 SSH 密钥,在拉取仓库代码时还是提示要求输入密码。
直接下载压缩包吧。
代码看到了,但 maven 仓库还没给配。
美元
2025 年 11 月 7 日
人民币购买力竟超美元,生活成本差距惊人,真相让人震惊
美元和人民币之间的实际购买力按盒饭算美元
USB
2025 年 11 月 7 日
[USB Type-C_百度百科](https://baike.baidu.com/item/USB Type-C/16565059)
usb-a和usb-b和usb-c的搜索结果_百度图片搜索
1 DP 输出指的是DisplayPort接口的输出功。DisplayPort是由PC及芯片制造商联盟开发,视频电子标准协会标准化的数字式视频接口标准,支持高分辨率、高刷新率和高动态范围技术,如4 K、8 K等。与HDMI相比,DP具有更高带宽和免费协议等优势。
显示器DP接口和HDMI有什么区别?详细对比一看就懂!
DP 接口和 HDMI 接口。
1 USB 全称为 Universal Serial Bus,翻译过来就是通用串行总线,由英特尔与众多电脑公司提出来用于规范电脑与外部设备的连接与通讯。
(99+ 封私信 / 82 条消息) usb的学习一 - 知乎
USB接口那么多!!你都认识吗??知道他们的区别吗??_mirco b与 usb a_usb接口有几种-CSDN博客
USB Type-A,USB Type–B,USB-Type C 接口。
分清楚各式各样的USB接口!一帖搞定_usb-a接口-CSDN博客
1 USB:Universal Serial Bus,通用串行总线。
USB: Universal Serial Bus,通用串行总线。
HDMI: High Definition Multimedia Interface,高清多媒体接口。
DP: DisplayPort,数字式视频接口标准。DP在这几年也逐渐流行起来了,它是一个由PC及芯片制造商联盟开发,视频电子标准协会(VESA)标准化的数字式视频接口标准,DP 的功能和 HDMI 非常相似,主要用于视频传输。
电脑USB、HDMI、DP各种接口及速度-CSDN博客
(99+ 封私信 / 82 条消息) 一文看懂显示接口:HDMI / DP / VGA / USB-C 有什么区别?怎么选? - 知乎
银行卡
2025 年 11 月 6 日
别再纠结了!社保卡的所属银行是哪个?4种方式都可以查询
银行一类卡和二类卡,你真的了解吗?
中国银行一类卡和二类卡的区别?
有关银行卡的知识,同下。
社保
2025 年 12 月 2 日
太原2025社保计算器_五险一金计算器_微蜂网
1 2 社保11月份没买,公司交的部分,按太原标准发给你,你自己买。 下个月开始,在公司买社保,个人要扣除569.72元,也就是下个月工资是4000 =569.72
1 公司买的话,买广州的社保,医保什么的可以全国通用的,你问问慧敏,公司给他买的也是广州社保
按养老保险缴纳8%、医疗保险缴纳2%,工伤保险缴纳0.2%的标准,以自己的全额工资为主,在广州交社保个人缴纳576.54元,公司缴纳部分1408.90元,一共1985.44元。
这个计算结果相当接近了。
如果按太原的标准,那个人缴纳515元,公司缴纳1307.5元,一共1822.5元。
那看来挺划算。
昨天报了中行卡账号,周四晚前就能领到上个月工资了,高兴高兴,一个月辛辛苦苦收入还是不赖的,上个月差旅费还会额外发给我。
2025 年 11 月 6 日
不知道“五险一金”是什么?看这篇就够了
1 “转正后缴纳”:违法!《社会保险法》第五十八条规定,用人单位应当自用工之日起三十日内为其职工向社会保险经办机构申请办理社会保险登记。未办理社会保险登记的,由社会保险经办机构核定其应当缴纳的社会保险费。即使在试用期,用人单位与劳动者协商一致,也不能不缴纳社保费哦!
秒懂“五险一金”原来是这么回事~😲
一口气读懂五险一金
激活社保卡金融功能需本人持有效身份证件和社保卡原件,到卡面所示服务银行的全国任一网点柜台办理,16周岁以下未成年人可由监护人代办。 该流程依据银行监管规定,无法线上办理,且激活时可同步启用社保功能。
必备材料 :本人有效身份证件(如居民身份证)及社保卡原件;16周岁以下未成年人需额外提供监护人身份证件及关系证明(如户口簿、出生医学证明)。
办理步骤 :确认社保卡卡面所示服务银行;本人携带材料至该银行全国任一网点(部分银行支持异地激活);在柜台设置金融账户密码,完成激活。
特殊人群 :未成年人 由监护人持双方证件及关系证明代办;行动不便者 可联系银行预约上门服务。
关键说明 :必须本人办理(未成年人除外),不可代办或线上操作;激活后金融功能立即生效,用于养老金发放等资金存取;未激活仅社保功能可用;社保功能可通过“电子社保卡”小程序等线上启用,但金融功能需线下办理。
1 2 激活后金融功能立即生效,用于养老金发放等资金存取;未激活仅社保功能可用。 这句话什么意思,我入职后正常缴纳五险一金,未激活金融功能的社保卡可以正常使用吗?
答案是:完全可以正常使用。
您入职后,公司为您正常缴纳“五险一金”(其中“五险”就是通过社保卡来关联的),完全不受社保卡金融功能是否激活的影响。
五险一金的缴纳主要通过单位账户完成,与社保卡是否激活无直接关联。即使未激活社保卡,单位仍可正常为员工缴纳社保费用。
医保使用 :您可以直接用未激活金融功能的社保卡去医院看病、在定点药店买药,医保报销部分会正常结算。
社保缴费记录 :您的养老保险、失业保险等缴费记录会正常计入您的个人社保账户,可以通过社保局官网、APP或线下机器查询。
简单来说:金融功能只关系到“钱怎么发到您手上”,而社保功能关系到“您的社保权益和记录”。 只要公司为您正常参保,您的社保权益就在持续积累。
虽然不激活金融功能不影响您现阶段使用社保待遇,但还是强烈建议您尽快抽空去银行网点激活它 ,原因如下:
未来领取待遇需要 :当您未来需要领取养老金、报销生育津贴等现金补贴时,钱会打到这个金融账户。如果账户未激活,钱可能无法正常打入,会影响您领取。
一卡多用,方便省事 :激活后,您就不需要额外提供其他银行卡号给单位或社保机构用于接收各类补贴,一张卡全搞定。
激活是免费的 :携带本人身份证和社保卡,到卡面上所示银行的任意网点(如卡上印着“工商银行”,就去工行网点)即可办理激活手续,设置银行卡密码,整个过程很快。
现在未激活金融功能,完全不影响 入职后正常使用社保(看病、买药、积累缴费年限),考虑到未来需要顺利领取各种社保待遇,建议尽早激活 金融功能。
1 你说的很清楚明白,我能不能这么理解,不激活完全不影响交社保,激活金融功能后就能将其当作一张储蓄卡来使用了。
社保卡金融功能未激活并不影响交社保用社保,公司为您缴纳社保费用、您用卡看病报销、积累社保权益,这些核心功能完全不受影响。
而金融功能激活后,社保卡就变成了一张标准的银行借记卡,具备所有储蓄卡的功能(存钱、取钱、转账、理财等)。
完全正确。
1 借记卡,储蓄卡,信用卡,一类卡,二类卡……等等这些概念是什么意思啊
银行卡按功能和本质分类,可分为借记卡 vs 信用卡。
储蓄卡 、工资卡,这两个名字都是借记卡的俗称。
信用卡 ,又叫透支卡,银行先给您一个信用额度(比如1万元),您可以在额度内直接花钱,这相当于向银行借了一笔短期贷款。到每个月账单日,您需要把花的钱还给银行,逾期不还会产生高额利息和影响信用。
借记卡/储蓄卡是花自己的钱;信用卡是花银行的钱(要还的)。
银行卡按账户权限分类,又可分为一类卡、二类卡和三类卡
这是中国人民银行(中国的央行)为了管理账户风险而做的规定,主要针对的是借记卡 (以及其背后的银行账户)。
您可以把它想象成家里的门:一类卡是大门,二类卡是房门,三类卡是保险柜的小门。
卡类型
形象比喻
功能与限额(年累计限额)
特点与用途
一类卡
家里的“大门”
全能、无限额 (理论上受银行单日限额限制,但年累计无上限)。
· 全功能账户 。 · 存款、取款、转账、理财、消费,所有功能不受限制。 · 一个人在同一家银行只能开立一个一类户 。您的工资卡、主要理财卡通常就是这个。
二类卡
家里的“房门”
有限额 : · 存入/转入资金:日限额1万,年累计限额20万 。 · 消费/支出:日限额1万,年累计限额20万 。
· 限制功能账户 。 · 适合用于日常小额消费、绑定支付软件(微信/支付宝)、买理财等,资金安全更有保障。 · 一个人在同一家银行可以开多个二类户。
三类卡
家里的“保险柜”
限额很低 :账户余额最高不超过2000元 ,用于小额快捷支付。
· 极度限制账户 。 · 主要用于手机扫码支付、闪付等小额消费场景。 · 即使被盗,损失也有限。
重要关系:
您新办的社保卡上的金融账户,默认就是一类卡 (只要您在该银行没有其他一类卡)。
如果您在某家银行已经有一张一类卡(比如以前的工资卡),再办新卡(包括社保卡)时,银行可能会询问您是否要将新卡降为二类卡,或者将旧卡降级。
💳社保卡六大实用功能,你知道几个
五险一金到底有啥用?作为子女和打工人,我终于想明白了
接下来的问答涉及到大量的 AI 回复内容,其回复不可谓不精准正确,索性把三次提问得到的结果都贴在下面了,交五险一金到底有什么好处 。
1 2 都说交社保交五险一金对自己有好处,究竟有什么好处呢,网络上的资源内容来来去去就是那几个字眼:什么养老保险累计交够15年就能在退休后领养老金,医保将来能报销能买药,失业保险交够满一年后可以在被动离职后每月领钱,工伤保险生育保险又能保障自己的安全更人性化…… 但是这养老金每月能领多少呢,医保缴够后将来能怎么报销呢,又怎么买药,失业保险又能领多少钱,工伤后怎么申请工伤险呢……等等这些细枝末节的问题我完全不晓得答案。
您这个问题问得非常好,也特别实在!您的感觉完全正确——网络上大部分信息都停留在“有什么”的层面,而您关心的是“怎么用”、“能得多少”这个核心问题。这就像别人只告诉您“汽车能代步”,而您想知道的是“这车怎么开?油耗多少?能跑多快?”。
下面,我将抛开那些笼统的字眼,用最直白的方式为您拆解“五险一金”实实在在的好处和操作细节。
养老保险:退休金到底怎么算?
核心好处 :只要累计缴满15年,并达到法定退休年龄,退休后就可以每月领钱,活到老领到老 。这个钱还会随着社会平均工资的增长而增加,是退休后最稳定的收入来源。
关键问题:每月能领多少?
计算公式非常复杂,但我们可以用一个“白话版”来理解,它主要取决于三大要素:
“存款”多少(您的缴费基数) :您工资越高,缴费基数就越高,个人账户里存的钱就越多。原则是“多缴多得”。
“存款”多久(您的缴费年限) :您交的时间越长,账户里的钱也越多。原则是“长缴多得”。交满15年只是门槛,建议一直交到退休 。
“社会平均工资”(退休时上年度全省市的社会平均工资) :您退休时社会的整体工资水平越高,您能领到的基础养老金也越高。
一个极简的估算例子 :
假设您退休时,当地社会平均工资为8000元/月,您一生的平均缴费工资也是8000元,缴费刚好30年。
基础养老金 ≈ (8000 + 8000) / 2 × 30 × 1% = 2400元/月
个人账户养老金 ≈ 您个人账户里全部储存额(您自己缴的部分+利息) ÷ 一个固定的计发月数(如60岁退休是139个月)。假设您个人账户有20万,那么这部分 ≈ 200000 / 139 ≈ 1439元/月 。
那么您每月总养老金 ≈ 2400 + 1439 = 3839元/月 。
请注意,这只是一个简化模型 ,但能帮您理解其构成。实际金额可以通过支付宝/微信中的“社保查询”服务或当地人社APP进行测算。
医疗保险:具体怎么报销和买药?
核心好处 :解决“看病贵”的问题。它分为两个账户:
个人账户(医保卡里的钱) : 来源 :您自己缴纳的医保部分(约2%)会进入这个账户。 怎么用 :就像一笔医疗专款,可以用来: 在定点药店刷卡买药 (非处方药和部分处方药)。 支付门诊、急诊、住院的起付线以下和个人自付部分的费用 。
统筹账户(国家的大池子) : 来源 :公司为您缴纳的大部分医保进入这个公共基金。 怎么用(报销) :当您的医疗费用超过一定金额(称为“起付线”或“门槛费”)后,就可以按比例报销。 报销流程 :在定点医院 看病时,在挂号、缴费时主动出示社保卡(或电子医保凭证),系统会直接进行结算——您只需要支付报销后需要自己掏腰包的那部分 ,报销部分由医院和医保系统直接结算,您无需垫付再跑报销。 报销比例 :通常医院级别越高(如三甲医院),报销比例越低(如70%-85%);社区医院报销比例更高(可能超过90%)。也有年度报销上限(封顶线),一般为几十万元。
失业保险:被动离职后能领多少钱?
核心好处 :被公司辞退、合同到期公司不续签等非自愿失业后,提供过渡性的经济支持。
关键问题:能领多少?领多久?
能领多少 :各地标准不同,但通常是**当地最低工资的70%-90%**。例如,某市最低工资2320元/月,失业金可能在1600-2100元/月左右。具体金额由当地社保局核定。
领多久 :与您缴费时间挂钩。 缴费满1年不足5年:最长领12个月。 缴费满5年不足10年:最长领18个月。 缴费10年以上:最长领24个月。
怎么领 : 单位需在解除劳动关系后为您办理“社保停保”,并注明原因是非本人意愿(如辞退)。 您本人在离职后,携带身份证、社保卡等材料到户籍地或参保地的公共就业服务机构 办理失业登记。 审核通过后,失业金会按月发放到您的社保卡金融账户或指定银行卡。
工伤保险与生育保险:怎么申请?
(1)工伤保险
场景 :在工作时间、工作地点、因工作原因受伤/患病/死亡(包括上下班途中非本人主责的交通事故)。
怎么申请 : 第一时间 :救治伤员,并通知单位和人力资源部门。 单位申报 :单位应在规定时间内(通常是30日内)向人社局提交《工伤认定申请表》及相关证据(如病历、证人证言、事故证明)。 认定 :人社局调查后出具《工伤认定决定书》。 待遇 :认定后,医疗费用由工伤保险基金报销,停工留薪期间工资照发,并根据伤残等级获得一次性伤残补助金等。
(2)生育保险
核心好处 :报销生育相关的医疗费(产检、分娩等),并领取产假期间的“工资”(叫生育津贴)。
怎么享受 : 报销 :在定点医院生育,通常也是直接刷社保卡结算。 领津贴 :女职工休产假期间,由生育保险基金支付生育津贴。一般是由单位代为申领,然后发放给个人。金额与单位上年度平均工资和产假天数挂钩。
最后,关于“一金”——住房公积金 ,它的好处极其实在:
贷款 :用公积金贷款买房,利率远低于商业贷款(能省下几十万利息)。
提取 :不仅可以用来买房、建房、租房,现在很多城市也支持用于支付大病医疗、老旧小区加装电梯等。
总结一下 :
“五险一金”不是虚无缥缈的概念,它是一套设计精密的国家保障体系。了解这些细节,才能在未来需要时真正地“用对”、“用好”它,让它成为您生活最坚实的后盾。建议您下载当地人社APP和公积金APP,实名认证后,可以随时查询自己的缴费明细和账户余额,做到心中有数。
1 2 3 4 5 6 领多久:与您缴费时间挂钩。 缴费满1年不足5年:最长领12个月。 缴费满5年不足10年:最长领18个月。 缴费10年以上:最长领24个月。 这个还是没有说明白,能领多少钱你说明白了,但具体能领多久你没说明白,假设我缴费至少一年了,我每次失业后都能领失业金吗,能领多久?再工作半年后又失业了还能继续领吗?到底能领多长时间。
您这个问题问到了关键点上!我之前的解释确实不够精确,非常抱歉。这个“最长领多久”的规则很容易让人混淆,因为它涉及到 “累计缴费年限” 和 “单次领取期限” 以及 “剩余待遇” 这几个概念。
下面我用最清晰的方式为您彻底讲明白。
核心原则:不是“每次失业都能完整地领一遍 ”。
失业金的领取规则,可以理解为您有一个 “失业保险待遇账户” ,这个账户的总额度是由您职业生涯总的累计缴费年限 决定的。但每次失业,您只领取其中的一部分,没用完的额度可以存起来下次再用。
第一部分:首次失业,能领多久?(单次领取期限)
这个“最长领取月数”的表格,指的是您第一次 符合条件申请失业金时,根据您截至当时为止的总缴费年限 ,所能领取的最长月数 。
举例说明:
小王 ,工作了3年零1个月(累计缴费满3年,不足5年),不幸被公司裁员。 他首次失业,最多可以领取12个月 的失业金。
老李 ,在同一家公司勤勤恳恳工作了11年(累计缴费满10年以上),不幸被裁员。 他首次失业,最多可以领取24个月 的失业金。
这就是您看到的那个表格的意思。它确定的是您“首次申领”时的天花板。
第二部分:最关键的问题——再就业后又失业,还能领吗?能领多久?
答案是:能领,但规则很特别。 这里分两种情况,我们用两个例子来彻底讲清:
情况一:领完失业金后再就业,又失业
规则 :重新就业后,再次缴费满一年 以上后再次失业的,缴费时间重新计算 ,可以再次申领失业金。
举例 : 小王第一次失业,领了8个月 失业金后找到新工作。 他在新单位又干了2年 后,再次被裁员。 他能领多久? 因为他重新就业后缴费已满一年(实际是2年),所以可以再次申领 。根据他新的累计缴费年限(2年,属于“满1年不足5年”) ,他第二次失业最多可以再领12个月 。
注意 :他第一次没领完的4个月(12-8=4)不会累积到第二次,因为第二次申领是基于新的缴费记录重新计算资格和期限的。
情况二:没领完失业金就再就业,又失业(您问的情况)
规则 :这是最复杂也最重要的一条。前次失业应领取而尚未领取的失业保险金的期限可以保留 ,与下次失业后应领取的期限合并计算 ,但合并后的期限最长不能超过24个月。
举例 : 小王第一次失业,根据他7年的总缴费年限(满5年不足10年),他最多可以领18个月 。 但他只领了3个月 ,就找到新工作了。于是他主动停止领取失业金。 他在新单位只干了半年 (注意,这次缴费未满一年),又不幸被裁员。 他还能领吗?能领多久? 能领 !因为他上次失业还有未领完的期限 :18个月 - 3个月 = 15个月 的额度。 这次他虽然只工作了半年(缴费未满一年),不具备“重新计算”的资格,但他可以继续申领上次剩余的15个月额度 。 他这次失业,可以继续把上次剩下的15个月领完。
为了让您一目了然,我们可以把失业金想象成一个有时间限制的“专属红包”:
您的工作变动情况
对失业金的影响
关键点
第一次失业
根据总缴费年限 ,开启一个专属红包,有效期最长为表格规定的月数(如12、18、24个月)。
确定初始额度。
领完红包后再就业,又失业
必须重新工作并缴费满一年 ,才能开启一个新的红包 。新红包大小由新的累计缴费年限 决定。
重新计算,旧额度作废 。
没领完红包就再就业,又失业
旧红包里剩下的钱不会消失 !你可以继续领完。如果新工作缴费又满一年,旧红包的剩余额度会和新红包的额度合并,但总额不能超过24个月。
余额保留,合并计算 。
最后的重要提醒 :
非自愿离职 :必须是公司辞退、合同到期公司不续签等非本人意愿中断就业的情况才能申领。自己主动辞职是不可以的。
及时办理 :离职后应在规定时间内(通常是60天)办理失业登记,才有资格领取。
希望这个详细的解释和例子能彻底解决您的疑惑!这套规则设计得比较精细,就是为了在保障失业者生活的同时,鼓励大家积极再就业。
1 我明白了,那能领多少钱跟自己缴费多少没有关系吗,我只看到你说按当地最低工资标准来发放。
您这个问题非常尖锐,直接触及了失业保险制度的一个核心特点:它更侧重于“保基本生活”而非“按劳分配”。
您的观察非常准——失业金的金额,确实与您失业前工资的高低、个人缴费的多少没有直接的正比关系。
但这不代表完全无关,我来为您拆解这其中的逻辑:
核心决定因素:确实是“最低工资标准”
您说得对,失业保险金的主要发放标准是参照参保地所在城市的最低工资标准 的一个比例(通常是70%-90%)。这是为了确保一个公平的“托底”机制,保障所有失业者都能获得维持基本生活的费用,而不是拉大收入差距。
例如 :北京2023年月最低工资标准是2320元,那么失业金可能在1624元(2320×70%)到2088元(2320×90%)这个区间内。一个失业前月薪5000元和一个失业前月薪15000元的人,只要参保地相同,他们领取的失业金金额会非常接近。
间接关联因素:您的缴费工资有“天花板”和“地板”
虽然金额不直接挂钩,但您的缴费基数(也就是您的工资)通过以下方式间接影响着您能领到的钱:
“天花板”效应(封顶) :失业金不会无限高。它有上限,这个上限就是当地最低工资的某个比例(如90%)。即使您月薪10万,缴费基数按最高上限缴纳,您领到的失业金也不会超过这个法定上限。
“地板”效应(托底) :法律规定,您的缴费基数不能低于当地社保缴费的最低基数 (通常是当地平均工资的60%或当地最低工资标准)。所以,即使您工资再低,也是按这个最低基数来缴费的,从而保证了您失业后领取的金额不会低于一个底线。
简单比喻:
失业保险更像一个“公共游泳池”,它有统一的浅水区和深水区(水位由最低工资决定),而不是一个根据您缴费量为您定制的“私人浴缸”。无论您之前贡献的水量是1吨还是10吨,您进来后都在同一个池子里游泳,水位对大家都一样。
与缴费直接挂钩的是什么?——是“领取资格”和“期限”
这才是您的缴费贡献真正发挥作用的地方!您的缴费工资高、缴费年限长,主要换来的是:
更稳固的领取资格 :缴费满一年是门槛。
更长的领取期限 :如我们之前讨论的,缴费5年能领18个月,缴费10年以上能领24个月。这是对长期、稳定缴费人员的重要回报。
为什么这样设计?
这种“金额保基本,期限论贡献”的设计,是基于社会保险的“共济”和“再分配”原则:
社会共济 :高收入者多缴费,与低收入者一起充实失业保险基金,共同增强社会抵御失业风险的能力。
保障基本 :核心目标是防止失业者及其家庭因收入中断而陷入贫困,而不是维持其原有的生活水平。维持原有生活水平更多需要通过个人储蓄、投资等渠道来实现。
促进再就业 :如果失业金与原有工资挂钩过高,可能会降低部分人寻找新工作的积极性。设定一个“保基本”的水平,有助于激励失业人员尽快重返劳动力市场。
总结一下:
您可以这样理解失业保险的逻辑:
“您能领多久” -> 这是对您长期缴费贡献 的奖励。
“您能领多少” -> 这是社会对您基本生活需求的保障 。
所以,虽然您感觉自己的高缴费没有直接换来更高的失业金,但它为您换来了更长的保障期限和更稳固的保障资格,这本身就是一种重要的对等回报。希望这个解释能帮您更好地理解失业保险的设计初衷!
月薪
2025 年 11 月 6 日
这个计算是完全正确的,它准确地反映了在特定情况下(只工作了一段时间且处于试用期)的月工资计算方法。
我来为您详细解释一下这个公式背后的逻辑和每个数字的含义。
公式分解:8 / 21.75 * 4000 = 1471.26
这个公式是标准的 “日薪制” 计算方法,适用于计算未出满勤月份的工资。
21.75(月计薪天数) :这是整个计算的核心基础。它不是一个估算值,而是中国人力资源和社会保障部规定的官方计薪天数。来源 :一年有365天,共52周零1天。扣除104天周末(52周 * 2天)后,剩下的261天为法定工作日。再将这261天平均到12个月,就得出:261天 ÷ 12个月 = 21.75天/月 。关键点 :这个数字是固定的,不考虑当月实际有多少个工作日 (比如2月可能只有20个工作日,而10月可能有23个)。所有月的计薪天数都统一按21.75天计算,这样可以避免大小月、节假日造成的计算不公平。
4000(您的试用期月薪) :这是您与公司约定的、在正常工作满一个月(即计薪天数21.75天)的情况下,应得的全额工资。
8(您上个月的实际出勤天数) :这是您在上个月实际为公司工作的天数。
计算逻辑(正算法):
第一步:计算日薪
1 日薪= 21.75 月薪= 21.754000 ≈183.91
第二步:计算当月应得工资
1 应得工资= 日薪×实际出勤天数= 183.91 ×8 ≈1471.28
整个计算的思路是:先算出您每天的工资是多少,然后再乘以您实际工作的天数。
服务器
2025 年 11 月 6 日
小型公司一般用什么服务器?这五点须知晓
1 2 3 4 .入门级塔式服务器 代表型号:戴尔PowerEdge T系列(如T150/T350)、惠普ProLiant ML系列(如ML30 Gen10+)、联想ThinkSystem ST系列(如ST250)。 使用场景:适合员工规模20人以下的企业,用于文件共享、基础ERP系统或小型数据库。 配置建议:通常配备Intel Xeon E-2300 系列或AMD EPYC 3000系列处理器,16-32 GB内存,1-2 块企业级SATA硬盘(可选RAID 1冗余)。
公司服务架构_互联网公司服务器内存多大-CSDN博客
服务器的配置与公司架构的大小、使用场景、负载需求密切相关。以下是各类服务器配置总结:
小型公司:适合 4 核 CPU,8GB 内存,500GB SSD 的服务器,用于开发、测试及低流量生产环境。
中型公司:适合 8 核 CPU,16GB - 64GB 内存,1TB SSD 配 RAID 配置,用于高流量应用的生产环境。
大型公司:适合 16 核以上 CPU,64GB - 128GB 内存,企业级存储系统和高可用架构,用于高并发、大数据、高可用需求。
云架构:根据需求动态配置,使用弹性计算、存储和负载均衡服务,适合大规模分布式系统。
1 磁盘阵列模式(RAID)是一种通过组合多个独立硬盘实现数据冗余与性能优化的存储技术,全称为独立磁盘冗余阵列。
一篇文章彻底搞懂RAID磁盘阵列及其配置使用-CSDN博客
RAID(Redundant Array of Independent Disks)即独立磁盘冗余阵列,是一种通过多磁盘组合实现数据冗余、性能提升或二者兼顾的存储虚拟化技术。其核心原理包括:
条带化(Striping):数据分块并行写入多磁盘(如RAID 0)
镜像(Mirroring):数据完全复制到多磁盘(如RAID 1)
奇偶校验(Parity):通过校验数据实现故障恢复(如RAID 5/6)
RAID的介绍和配置_组raid-CSDN博客
服务器尺寸详解:从1U到42U的完整指南
中国银行
2025 年 11 月 6 日
看看这周末有空出门办理下银行卡吧,这些事情其实上周出差那会儿就能告诉我的,工资打不到账户了才通知我要办个中国银行的卡。
中国银行开卡攻略:跑了三次终于搞定
中国银行怎么办银行卡-百度经验
身份证,在职证明?申请表,线上办理,设置交易密码,绑定信息,激活。
中国银行自助办卡流程是什么_百度知道
中国银行线上申请办卡指南
能线上办理才最好。
中国银行卡怎么办理 需要带什么过去_百度知道
(99+ 封私信 / 82 条消息) 中国银行卡办理 - 搜索结果 - 知乎
知乎上办理流程风评很差劲。
办银行卡是对私还是对公 - 财梯网
1 我要在中国银行APP 上预约办理银行卡,单位发工资需要用中国银行卡,这里取号时选择现金业务还是其他业务啊,不懂。
应该选择“其他业务”。
原因如下:
业务性质匹配: 办理银行卡(特别是工资卡)属于“账户开立”或“个人业务”,而不是直接的现金存取、兑换等“现金业务”。银行通常将“开卡”归类在“个人非现金业务”或简单的“其他业务”中。
界面提示: 在APP的选项里,“现金业务”通常有明确的指向性。选择“其他业务”是一个更通用和准确的选择,可以涵盖开卡、挂失、签约网银等多种服务。
1 单位发工资要给中国银行卡里打钱,办理这种业务是对公还是对私的,去的时候需要携带什么证件?
为了确保一次办成,请按以下清单准备:
物品类别
具体物品
重要性
备注
必须携带
本人身份证原件
★★★★★
无身份证无法办理
必须携带
本人实名认证的手机
★★★★★
用于接收验证码和绑定银行卡
建议携带
工作证明 (盖章文件/工牌/劳动合同)
★★★★☆
证明办卡用途,成功率大增
需要知晓
个人详细现住址 (精确到门牌号)
★★★☆☆
银行系统必填项
需要知晓
单位全称、地址等信息
★★☆☆☆
开户时可能会询问并录入系统
1 我只能说办理一张工资卡吗,就不能找个合适的理由正常办理储蓄卡吗。
“你好,我想新开一张借记卡,作为工资卡使用。单位要求用中国银行的卡。”
直接说办“工资卡”其实是最合适、最顺利 的理由。
为什么这么说?我们来对比一下:
说法
银行人员的理解
可能的结果
推荐指数
“我要办一张工资卡,单位发薪用。”
“真实、合理的开卡需求。” 工资卡是刚需,受反诈法规保护,银行认为风险较低。
流程清晰,目标明确。 大堂经理会直接引导你走“工资卡”开户流程,即使需要你提供工作证明(如工牌),也是标准程序,并非刁难。
★★★★★
“我就办张普通的储蓄卡,存点钱。”
“用途模糊,可能存在风险。” 在当前“断卡行动”背景下,这种无具体用途的开卡会触发银行更严格的风控审核。
可能会被详细追问。 柜员或智能机具可能会问得更细:“主要用途是什么?”“预计资金流量多大?”“有没有理财需求?”等。回答得含糊其辞反而更可疑。
等周六上午去最近那家中国银行一趟,携带身份证和工作证明看能不能一次性办好,最近差旅费报销还有从下个月打工资都要用。
盘外
2025 年 12 月 2 日
Configuring a publishing source for your GitHub Pages site - GitHub Docs
(99+ 封私信 / 82 条消息) 什么是github-page,为啥好多人在这个上面部署网站,在这上面搭建是不需要自己有后台服务器吗? - 知乎
2025 年 12 月 1 日
微信小游戏包体限制4M,一个字体就11.24M,怎么玩?引言 哈喽大家好,很多时候,我们的游戏项目为了美观和保证风格的统 - 掘金
(99+ 封私信 / 82 条消息) 码云gitee的Pages服务下线了,有那些替代品? - 知乎
2025 年 11 月 21 日
Vue-Vben-Admin 从入门到实战:后端开发的前端探索之旅
2025 年 11 月 18 日
颜色网站为啥都收费?自己做个要花多少钱?如果一个人做个小型的视频网站,一年到底要花多少钱? 网站本身的成本+人力成本,我 - 掘金
刚刚 Java 25 炸裂发布!让 Java 再次伟大刚刚,Java 25 正式发布!这是继 Java 21 之后,又一 - 掘金
尤雨溪力荐!Vue3 生态最强大的 14 个 UI 组件库!在 Vue3 官网 的「Ecosystem → UI Com - 掘金
分享10个吊炸天的油猴脚本,2025最新!油猴(Tampermonkey)是一款浏览器插件,允许用户在网页加载时注入自定 - 掘金
我为什么说全栈正在杀死前端?大家好,我又来了🤣。 打开2025年的招聘软件,十个资深前端岗位,有八个在JD(职位描述) - 掘金
Java web后端转Java游戏后端作为Java后端开发者转向游戏后端开发,虽然核心编程能力相通,但游戏开发在架构设计 - 掘金
1 通过以上流程,Java后端开发者可逐步掌握游戏开发特性,重点需要转变的思维模式包括:从请求响应模式到实时状态同步、从CRUD主导到复杂逻辑计算、从分钟级延迟到毫秒级响应的要求。建议从简单的棋牌类游戏入手,逐步过渡到大型实时游戏开发。
没设计也能很漂亮,非常适合独立开发:Trae + 飞个马MCP 因为团队规模比较小,没有专门的设计师,就尝试使用Trae - 掘金
2025 年 11 月 14 日
我发现很多程序员都不会打日志。。。日志用来记录程序运行时的状态和信息,这样当系统出现问题时,我们可以通过日志快速定位问题 - 掘金
Logstash 负责收集各个服务的日志,然后发送给 Elasticsearch 存储和索引,最后通过 Kibana 提供一个可视化的界面。
让老弟做个数据同步,结果踩了 7 个大坑!第一天上班,老板就交给你一个艰巨的任务:定期把公司的订单数据同步到数据分析仓库 - 掘金
2025 年 11 月 10 日
那些年我们一起追过的Java技术,现在真的别再追了!今天的Spring Cloud、Kotlin、GraalVM,可能就 - 掘金
2025 年 11 月 5 日
最近想把这些系列给看了。
菜鸟教程 - 学的不仅是技术,更是梦想!
Docker入门到实践(一)docker简介和安装docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及 - 掘金
uni-app官网
竹子爱熊猫 的个人主页 - 专栏 - 掘金
Electron开发实践(1)——为什么选择ElectronElectron的诞生 Electron(原名为Atom S - 掘金
把 Vue.js 再过一遍,基础要打牢。
2025 年 11 月 6 日
Electron开发实践(4)——跨进程通信前言 进程间通信 (IPC) 是在 Electron 中构建功能丰富的桌面应 - 掘金
看不太进去。。
2025 年 11 月 7 日
接私活神器!一个轻量级的 Java 快速开发平台!X-SpringBoot —— 一个轻量级的 Java 快速开发平台, - 掘金
有了免费的Kiro,这次真的可以把Cursor扔了!Claude的金主爸爸亚马逊(AWS)偷偷发布了一款AI编程工具,K - 掘金
掘金,Docker。
AI时代的工作和成长引言 去年夏天,我一口气读完几篇AI文章,兴奋得连夜想写点什么。 可一年过去,键盘上落的不是代码,是 - 掘金
网线
2025 年 11 月 17 日
1 PL2303芯片 和 FTDI 芯片有什么区别?
特性
FTDI (Future Technology Devices International)
Prolific (巨量)
核心定位
工业级、商用级 。强调稳定性、可靠性和长期支持。
消费级、成本敏感型 。主打高性价比和基本功能。
稳定性与性能
极高 。公认的稳定性标杆,数据传输错误率低,兼容性极佳。
一般 。在简单应用下没问题,但在复杂环境或长时通信中可能不如FTDI稳定。
驱动程序
“教科书级别”的稳定 。驱动更新积极,对不同操作系统(包括旧版Win、Linux、甚至嵌入式系统)支持非常好。策略是持续优化兼容性 。
驱动是“重灾区” 。为了打击山寨芯片,Prolific通过更新驱动故意让旧版和山寨芯片无法使用 ,导致用户常因驱动问题无法通信。
价格
较贵 。芯片本身和采用FTDI芯片的线缆价格都更高。
便宜 。极具成本优势,是大量廉价线缆的首选。
山寨情况
有,但FTDI的反制措施更“狠”(曾通过驱动将山寨芯片的PID/VID篡改,导致其变砖),一定程度上抑制了山寨泛滥。
山寨仿冒芯片极多 。您买到的线,里面的PL2303芯片很可能就是山寨版本。
常见型号
FT232RL, FT231X, FT234X等
PL2303TA, PL2303HXD, PL2303HXS, PL2303GT 等
2025 年 11 月 5 日
高清线和hdmi线的区别是什么_装修全知道_学堂_齐家网
全网最强讲解:3000多字,解释清楚为什么需要HDMI线?怎么选?
G307/太原绕城高速(路口) - 百度地图
网线_百度百科
8路千兆以太网接口。
千兆网线8根线定义图_电脑与电脑之间的网线直连-CSDN博客
网络线序与标准详解:千兆网与百兆网差异深入解析
一条能通车的千兆网络,需要以下组成部分协同工作:
组成部分
实物比喻
作用和要求
1. 网卡(NIC)
汽车的引擎
安装在电脑、路由器等设备里。它是核心,决定了设备有没有能力 跑千兆。一个百兆的网卡,即使用千兆网线和千兆路由器,速度也上不去。
2. 网线
公路路面
负责传输电信号。千兆网络至少需要使用 Cat 5e(超五类) 或更高级的 Cat 6(六类) 网线。路面的质量(线材好坏)直接影响稳定性和速度上限。
3. 路由器/交换机
交通枢纽/立交桥
负责指挥数据包去往正确的设备。你必须有一个千兆端口 的路由器/交换机。如果路由器是百兆的,那么整个内部网络的速度就会被限制在百兆。
4. 接口(RJ-45)
公路的进出口匝道
就是你平时插网线的那个插槽和水晶头。它有8个金属触点。百兆网络实际上只用了其中4个(1,2,3,6),而千兆网络必须8个触点全部正常工作 。
简单自检: 要想实现千兆速度,必须确保 网卡 + 网线 + 路由器 三者都支持千兆标准,缺一不可。
它不是一种特殊的线,而是一个“质量标准”
首先纠正一个常见误解:并没有一种官方叫做“千兆网线”的线缆 。这个称呼指的是达到了能够稳定传输千兆网络信号标准的网线 。
这就像说“能跑F1赛车的赛道”,它指的是一种赛道的修建标准 (平整度、摩擦力、弯道设计等),而不是赛道本身的名字。
千兆网线 vs. 百兆网线(公路的“车道”数量)
最根本的区别在于8根芯线是否全部工作 。
网络类型
比喻
线缆要求
常用线缆类别
百兆网络 (100M)
双向4车道公路
只使用8根线里的4根 (1, 2, 3, 6)来传输数据。另外4根是闲置的。
Cat 5(五类线) 就足够了。
千兆网络 (1000M)
双向8车道公路
8根线必须全部使用 ,而且技术更先进,每对线都能同时收发数据。
至少需要 Cat 5e(超五类) ,推荐 Cat 6(六类) 。
关键点: 如果你用一条只有4根芯线能通的老旧或劣质网线(比如某些只有4芯的电话线冒充的网线),那么即使你的电脑和路由器是千兆的,速度也会被限制在百兆。因为“路面”只有4条车道,无法满足8车道同时通车的需求。
如何识别一条“千兆网线”?(看路面的“等级标号”)
最可靠的方法就是看网线外皮上印刷的文字 。
寻找“CAT”字样 :**CAT 5e或 CAT 5E:这是 超五类线 ,是千兆网络的 入门标准。在100米距离内能稳定支持千兆网络。这是目前最常见、性价比最高的选择。 CAT 6:这是 六类线,标准更高。它内部通常带一个“十字骨架”(如下图),用来更好地隔离4对线,减少串扰。它不仅完美支持千兆(1000M),还能支持更高速的 万兆(10G)网络(但距离较短,约55米)。 未来几年内,这是更好的选择。****CAT 6A**(超六类)、CAT 7等:支持更高速率(如万兆到100米),一般家庭目前用不到,多见于数据中心。
看水晶头 :虽然不绝对,但千兆网线的水晶头,8个金属触点必须是齐全的、镀金的 ,看起来做工更扎实。百兆网线有些劣质的水晶头可能触点材质很差,甚至只有4个触点。
千兆网线的内在要求:为什么Cat 5e以上才能当千兆网线?
要达到“千兆标准”,这条“路面”必须在以下几个方面达标:
材质纯度(路面材质) :必须使用无氧铜 ,电阻小,信号损耗低。劣质线会用铜包铝、铜包铁,电阻大,信号衰减严重,轻则降速,重则断网。
双绞密度(车道的平整度) :网线里的8根线是两两相绞成4对的。绞合的密度越高,抗电磁干扰的能力就越强。Cat 6线的绞合密度通常比Cat 5e更高。
屏蔽性能(公路的隔音墙) :在电磁干扰强的环境(比如旁边有强电线),需要使用屏蔽线 。屏蔽线外有一层金属箔或编织网,像隔音墙一样保护内部信号。家用一般用非屏蔽线(UTP) 就够了。
总结与选购建议
线缆类型
最大频率
支持的最高速率(理想条件下)
推荐场景
Cat 5
100 MHz
100 Mbps(百兆)
已淘汰 ,不要购买。
Cat 5e
100 MHz
1000 Mbps(千兆)
家庭主流选择 ,性价比高,完全满足千兆需求。
Cat 6
250 MHz
1 Gbps(100米)/ 10 Gbps(55米)
追求品质和未来性的选择 ,抗干扰更好,为万兆留有余地。
Cat 6A/7
500 MHz+
10 Gbps(100米)
家庭极客、NAS重度用户、小型企业。
有时候这 AI 的理解要比绝大多数网站内容靠谱些。
2025 年 11 月 7 日
1 2 3 现在要采购一条网线,预计下周就要去现场调试设备了,得用自己的电脑连接高速收费站的费用显示器,在车道处调试下,现在需要我买一条网线,用电脑连接费显等设备时,得额外用一个USB转接口把笔记本和设备连接起来。 现在的问题是,网线应该买什么规格的,USB转接口呢,你推荐一下,今下午下班后我就买京东快递,明天就回来了。
核心采购清单(今晚下单,明天送达)
物品名称
规格要求
推荐理由
京东关键词示例
1. 网线
超五类类或六类非屏蔽网线 ,长度建议 3米或5米 (预留操作空间)
超五类(Cat5e)或六, 完全足以应对千兆网络,是性价比最高的选择。非屏蔽型号(UTP)柔软易用,完全满足现场调试环境。3-5米长度足以在车道旁灵活操作。
“六类网线 3米” “超五类网线 5米”
2. USB转网口转换器
USB Type-C转RJ45千兆网口转接头 (务必确认接口与您笔记本匹配)
这是关键设备!绝大多数现代轻薄本已取消RJ45网口,必须靠它转换。千兆 是标准配置,[基本知识] 务必选择品牌货以保证驱动兼容性和稳定性,避免“三无”产品。
“USB转网口转换器 千兆” “Type-C转RJ45”
请立刻检查您笔记本电脑的接口类型,是传统的USB-A口(扁长型)还是USB-C口(椭圆形)。据此选择对应的转换器!
1 我的笔记本是 Lenovo XiaoXinPro 16lHU 2021 ,你给看下如果要买转接口,应该买什么样接口类型的。
好的,我们来快速准确地确定您需要的转接口类型。
根据您的笔记本电脑型号 **联想小新Pro 16 2021款 (16lHU)**,我们可以直接锁定它的接口规格。
您需要购买 Type-C 转 RJ45 网口转换器
详细说明和选购建议:
1.接口确认 :您2021款的小新Pro 16,机身上配备的是 USB Type-C 接口 。这个接口是椭圆形的,并且支持充电、数据传输和视频输出。因此,您必须选择 USB-C 转 RJ45 的转换器。
2.关键参数 :务必选择 千兆(1000Mbps) 型号。百兆(100M)的已经过时,无法满足现代网络设备调试的需求。
3.选购关键词(用于京东搜索) : •Type-C 转网口 •USB-C 转 RJ45 千兆 •扩展坞 千兆网口(如果您未来还需要连接U盘或显示器,可以考虑功能更多的扩展坞,但目前仅转网口的小转接头更便宜便携)
您的最终采购清单(今晚京东下单):
物品
为 小新Pro 16 2021款 精准匹配的规格
USB转网口转换器
Type-C 转 RJ45 千兆网口转接头
网线
六类(Cat6)或超五类(Cat5e)非屏蔽网线,长度3-5米
现在就可以打开京东APP或网站,直接搜索 “Type-C 转千兆网卡” ,选择一个销量高、评价好的品牌(如绿联、毕亚兹、飞利浦等),今天下单,明天就能送达。
确保这个转接头能在您的电脑上正常识别,是明天现场调试成功的第一步。祝顺利!
usb线转网口线-usb线转网口线厂家、品牌、图片、热帖-阿里巴巴
usb转换线网线-usb转换线网线厂家、品牌、图片、热帖-阿里巴巴
虚拟机 环境变量
2026 年 2 月 26 日
Linux 系统中添加或追加环境变量_linux添加环境变量-CSDN博客
一、临时新增环境变量 (快速测试用)
这种方式只在当前终端会话生效,关闭终端或切换用户后就失效,适合临时测试:
1 2 3 4 5 6 7 8 9 10 export JAVA_HOME=/home/loongson/src/jdk-11.0.29export PATH=$JAVA_HOME /bin:$PATH echo $JAVA_HOME echo $PATH
关键:$PATH 表示 “保留原来的 PATH 值”,$JAVA_HOME/bin:$PATH 是把新路径加到最前面,优先执行。
二、永久新增环境变量 (推荐,分场景)
场景 1:仅给当前普通用户(loongson)生效
修改用户个人配置文件,只影响当前用户,不会干扰其他用户,是最推荐的方式:
编辑用户的 .bashrc 文件(bash shell 的核心配置文件):
1 2 3 4 vi ~/.bashrc nano ~/.bashrc
在文件末尾添加新增环境变量的命令(示例):
1 2 3 4 5 6 export JAVA_HOME=/home/loongson/src/jdk-11.0.29export PATH=$JAVA_HOME /bin:$PATH export CLASSPATH=.:$JAVA_HOME /lib/dt.jar:$JAVA_HOME /lib/tools.jar
保存退出后,让配置立即生效:
验证:
1 2 echo $JAVA_HOME java -version
场景 2:给系统所有用户 (包括 root)生效
修改系统全局配置文件,所有用户登录后都会加载,适合需要统一环境的场景:
编辑 /etc/profile(需要 root 权限):
在文件末尾添加同样的环境变量配置:
1 2 3 4 export JAVA_HOME=/home/loongson/src/jdk-11.0.29export PATH=$JAVA_HOME /bin:$PATH export CLASSPATH=.:$JAVA_HOME /lib/dt.jar:$JAVA_HOME /lib/tools.jar
保存退出后,让全局配置立即生效(普通用户和 root 都要执行):
1 2 3 4 5 source /etc/profile su rootsource /etc/profile
验证:切换任意用户,执行 echo $JAVA_HOME 都能看到配置的路径。
场景3:**修改 /etc/environment**(仅纯变量定义)
你之前看到的 /etc/environment 是系统基础环境变量文件,只支持 “变量 = 值” 的纯定义格式,不能写 export,也不能用 $ 引用其他变量 :
1 2 3 4 5 sudo vi /etc/environment JAVA_HOME="/home/loongson/src/jdk-11.0.29" PATH="/home/loongson/src/jdk-11.0.29/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
生效:需要重新登录(注销再登录),或重启系统。
注意:这个文件优先级低,会被 .bashrc//etc/profile 覆盖,一般不推荐在这里改 PATH。
三、修改后验证 & 回滚
验证环境变量:
1 2 3 4 5 6 echo $JAVA_HOME env | grep -i java java -version
回滚(如果配置错了):
个人配置:删除 .bashrc 末尾添加的内容,执行 source ~/.bashrc;
全局配置:删除 /etc/profile 末尾添加的内容,执行 source /etc/profile。
总结 :
临时新增:用 export 变量=值,仅当前 shell 生效;
永久新增(推荐):普通用户改 ~/.bashrc,所有用户改 /etc/profile,添加后执行 source 文件名 立即生效;
关键注意:/etc/environment 不支持 export 和变量引用,优先级低,一般不用来改 PATH;新增 PATH 时要保留原有值(加 $PATH),避免覆盖系统默认路径。
2025 年 12 月 18 日
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 [admin@localhost ~]$ ifconfig docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 172.17.255.255 inet6 fe80::42:b1ff:fe3a:4b6e prefixlen 64 scopeid 0x20<link> ether 02:42:b1:3a:4b:6e txqueuelen 0 (Ethernet) RX packets 37 bytes 2060 (2.0 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 39 bytes 4066 (3.9 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.139.128 netmask 255.255.255.0 broadcast 192.168.139.255 inet6 fe80::b250:523d:d564:e75a prefixlen 64 scopeid 0x20<link> ether 00:0c:29:b3:1a:75 txqueuelen 1000 (Ethernet) RX packets 58 bytes 5312 (5.1 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 127 bytes 12725 (12.4 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10<host> loop txqueuelen 1 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 veth5dbcacb: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::9003:99ff:fe82:3e26 prefixlen 64 scopeid 0x20<link> ether 92:03:99:82:3e:26 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 31 bytes 3292 (3.2 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 vethab9d652: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::c8c:94ff:fe14:38be prefixlen 64 scopeid 0x20<link> ether 0e:8c:94:14:38:be txqueuelen 0 (Ethernet) RX packets 37 bytes 2578 (2.5 KiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 42 bytes 3838 (3.7 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255 ether 52:54:00:d1:4f:a7 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 C:\WINDOWS\system32>ipconfigWindows IP 配置 无线局域网适配器 本地连接* 9 : 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 VMware Network Adapter VMnet1 : 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::bcc3:1f75:3cb:b22f%11 IPv4 地址 . . . . . . . . . . . . : 192.168.91.1 子网掩码 . . . . . . . . . . . . : 255.255.255.0 默认网关. . . . . . . . . . . . . : 以太网适配器 以太网 : 媒体状态 . . . . . . . . . . . . : 媒体已断开连接 连接特定的 DNS 后缀 . . . . . . . : 以太网适配器 VMware Network Adapter VMnet8 : 连接特定的 DNS 后缀 . . . . . . . : 本地链接 IPv6 地址. . . . . . . . : fe80::52b0:a529:27d4:73d6%8 IPv4 地址 . . . . . . . . . . . . : 192.168.139.1 子网掩码 . . . . . . . . . . . . : 255.255.255.0 默认网关. . . . . . . . . . . . . : 无线局域网适配器 WLAN : 连接特定的 DNS 后缀 . . . . . . . : IPv6 地址 . . . . . . . . . . . . : 2409:8744:0:17:0:1:0:28e 本地链接 IPv6 地址. . . . . . . . : fe80::515e:31f0:dafb:1bc3%2 IPv4 地址 . . . . . . . . . . . . : 172.16.20.211 子网掩码 . . . . . . . . . . . . : 255.255.254.0 默认网关. . . . . . . . . . . . . : fe80::5ab3:8fff:feba:6f19%2 172.16.20.1 隧道适配器 Teredo Tunneling Pseudo-Interface : 连接特定的 DNS 后缀 . . . . . . . : IPv6 地址 . . . . . . . . . . . . : 2001:0:14c9:d502:3478:3413:8a5f:426 本地链接 IPv6 地址. . . . . . . . : fe80::3478:3413:8a5f:426%14 默认网关. . . . . . . . . . . . . :
2025 年 11 月 10 日
查看虚拟机磁盘空间大小。
linux命令:查看空间(内存、磁盘、文件目录、分区) - 子非鱼灬亦非我 - 博客园
Linux使用du和sort命令查找最大文件和目录_Linux_脚本之家
Linux的清屏命令(linux终端清屏)-腾讯云开发者社区-腾讯云
2025 年 11 月 5 日
vmware workstation pro 17激活码_vmware workstation17密钥-CSDN博客
1 You do not have permission to enter a license key. Try again using the system administrator account.
虚拟机VMware17安装包免费下载及安装激活教程(附激活密钥) - 影武浮云 - 博客园
最新的许可证密钥:
1 2 3 4 NZ4RR -FTK5H-H81C1-Q30QH-1 V2LA4A4RR -813 DK-M81A9-4 U35H-06 KNDMC60H -DWHD5-H80U9-6 V85M-8280 DJU090 -6039 P-08409 -8 J0QH-2 YR7F
问题解决:
vmware 16无权输入密钥,联系管理员权限解决办法_you do not have permission to enter a license key.-CSDN博客
工具栏搜索“cmd”找到命令提示符;
右击以管理员身份运行;
找到VMware安装目录,进入VMware的安装目录下的 x64 文件夹,复制地址。如下:
在已打开的cmd中输入代码:
1 2 3 4 5 cd /d d: cd D:\Program Files\XUNIJI\x64(这里以我的目录为例,将加粗部分改为你的VMware的安装目录即可) vmware-vmx.exe --new -sn xxxx-xxxx-xxxx-xxxx(密钥内容:YF390-0 HF8P-M81RQ-2 DXQE-M2UT6)
注意:cmd要以管理员身份运行,否则会导致命令无效。
1 2 3 4 5 cd /d d: cd D:\dev\VMware Workstation Pro 17.0 64位 vmware-vmx.exe --new-sn NZ4RR-FTK5H-H81C1-Q30QH-1V2LA
1 vmware.exe --new-sn NZ4RR-FTK5H-H81C1-Q30QH-1V2LA
1 vmware-vmx.exe --new-sn xxxx-xxxx-xxxx-xxxx(密钥内容:YF390-0HF8P-M81RQ-2DXQE-M2UT6)
测试完毕,执行这三条命令即可:
1 cd D:\dev\VMware Workstation Pro 17.0 64位\x64
1 vmware-vmx.exe --new-sn NZ4RR-FTK5H-H81C1-Q30QH-1V2LA
顺利执行,不过没什么用,不起作用。
VMWare 17 虚拟机安装。
本机 CentOS7 密码为 :12345678。
边缘网关
2025 年 11 月 25 日
路段版本,顶部菜单。
架舱,设备检测,详情界面 -> 资产基本信息,监测信息,告警信息,资产拓扑图(省二期),性能指标,指标排序。
收费站监测,数据传输总览,数据传输指标,交易数据完整性。
系统公告,运维管理,统计分析(车道门架运行监测排行榜),导出报表功能,版本监测。
基础管理,设备管理,资产管理。
2025 年 10 月 30 日
RSU_百度百科
MTC(人工与自动化设备协同运作的高速公路收费系统)_百度百科
RS232/RS485串口:RSU 天线控制器,MTC 读卡机,移动支付扫码枪,费额显示器,称重设备。
千兆以太网接口:车牌识别摄像机,车型识别,智能栏杆机,打印机,特情机。
1 以太网供电(Power over Ethernet,简称PoE)也称PoE供电,是一种可以在以太网中透过双绞线来传输电力与数据到设备上的技术。
1 IC卡 (Integrated Circuit Card ,集成电路卡),也称智能卡(Smart card )、智慧卡(Intelligent card )、微电路卡(Microcircuit card )或微芯片卡等。
1 CPC卡的英文全称Compound Pass Car (复合通行卡),主要用于高速公路收费系统中记录车辆行驶路径和计费信息。
收费站主要设备包括站级服务器、车道设备以及称重设备,应满足本章设备技术要求,同时应充分考虑国家安全战略要求及新技术发展和应用,实现联网收费系统安全、稳定、高效运行。
车道设备主要包括RSU、高清车牌图像识别设备、车型识别设备、电动栏杆机、车辆检测器、信息显示屏、手持终端、移动支付终端、自助发卡设备、 自助交费设备、车道控制器、非接触IC卡读写器等。若采用集成化设备,集成 的设备模块均应满足本章设备技术要求
1 2 PCI是Peripheral Component Interconnect (外设部件互连标准)的缩写,它是个人电脑中使用最为广泛的接口 PCL密码卡
1 PSAM(Purchase Secure Access Module )是销售点终端安全存取模块,符合中国金融集成电路(IC)卡规范,主要用于商用POS终端、网点终端等设备的安全控制管理,支持多级发卡机制和多应用环境。
出差
2026 年 2 月 3 日
1月5号,21.17,22.37;6号,19.77,38.79;7号,20.01,29.32;8号,20.9,52;9号,20,38.6;14号,20.01,31.98;15号,20.22,29.7;16号,20.65,31.17;20号,20.9,26.3;21号,21.65,35.29;22号,19.88,33.49;28号,19.6,42.29。
总计 656.06 元。
上个月去太原南打车花了 656.06 元。
2026 年 1 月 9 日
上个月在太原南打车220.92,买设备197.1,一共花销418.02块。
17号到4号,十九天。
在河南打车165,高铁470,住宿921.93,一共花销1556.93块。
2026 年 1 月 5 日
其实这段时间打车花销也挺大的,去太原南站打车9块,南阳东站到彭营打车花了 90 块,宾馆到中天打车花了22块,九里沟到济源站打车花了 37 块,南站到大马打车7块。
今天打车又花了 20 块,下午回去还当然得打车。
加班费算补贴,差旅费算报销,一码归一码。
2026 年 1 月 3 日
高铁票,太原到郑州 195.5 元,郑州东到南阳东 119 元,济源到焦作 12.5 元,焦作到太原 143 元。
高铁共计 470 元。
17号晚哈泊开开酒店 71 元,18 号晚幸福旅客驿站 100.77 元,19号 - 21 号合家欢宾馆 190 元,途客中国旅居酒店 480 元,今晚济源恒通宾馆 80.16 元。
住宿共计 921.93 元。
上个月总花销 470 + 921.93 + 418 = 1,809.93 元。
2026 年 1 月 2 日
差旅费不好算啊。
前期住酒店花销比较杂乱,吃饭完全没必要算,奔波了半个多月愣是没动手打过一次车。
那就是住酒店占大头,加上来回的高铁票,回去可能要打几趟车,到时候添上。
2025 年 12 月 21 日
周四回郑州东的地铁,当晚幸福率旅店住宿,吃一碗米线,周五一早去南阳的高铁票,打车去彭营,当晚邓州住一晚酒店,昨天下午吃一碗牛肉拉面。
2025 年 12 月 18 日
太原南到郑州的动车票,打车去酒店的花销,今早打车来中天的花销。
2025 年 12 月 12 日
一眨眼计算差旅费花销都已经是将近两周前的事情了。
电源适配器 45.90 元,一串四口线 151.20 元,插排暂时不算。
打车,上周五来回分别花销 19 元,45.6 元;上周六来回分别花销 22.42 元,22.2 元;这周一来回分别花销 19 元,44.26 元;周五来回分别花销 20.81 元,27.63 元。
买设备花销 197.1 元,打车花销 220.92 元,总花销 418.02 元。
周一,上个月的差旅费总花销给打到卡上了,高兴高兴。
2025 年 11 月 30 日
这周的花销。
千兆交换机,34.90 元;网线转换头,14.90 元;两条网线,17.43 元;公对母串口线延长线,35.90 元。
买设备一共花了 103.13 元。
周一没去,周二来回两趟车,分别花销 21.06 元,25.25 元;周三来回两趟车,分别花销 21.63 元,29.25 元;周四来回两趟车,分别花销 21.09 元,25.33 元;周五来回两趟车,分别花销 23.38 元,40.16 元;周六来回两趟车,分别花销 22.60 元,25.72 元。
打车一共花了 255.47 元。
截至今天,买设备一共花了 103.13 元 + 270.58 元 = 373.71 元,打车一共花了 164.08 元 + 255.47 元 = 419.55 元。
这个月开销差旅费开销,793.26 元 。
2025 年 11 月 24 日
上周的花销还没算进去。
额外买了两根新串口线,各自花销 62.10 元,62.10元。
周一来回打了两趟车,分别花销 16.85 元 ,28.38 元;周三,周四,周五中午打了一趟车过去,各自花销 23.02 元,22.22 元,22.54 元;周六来回打了两趟车,分别花销 25.01 元,26.06 元。
串口屏 93.25 元,USB 转 TTL 模块 53.13 元。
直至今天,买设备花销 270.58 元,打车花销 164.08 元 ,共计花销 434.66 元。
妈的,项目预备金早都超支了,剩下的开始自己垫付了都,多付了 51.41 元。
2025 年 11 月 18 日
周三,截至目前,又买了两条串口线,打了两趟车,今天还得打两趟车,还买了一个串口屏,老贵了这个东西。
今下午结束后总结下花销。
2025 年 11 月 16 日
统计下过去两周多时间里的花销。
网线 16.71 块,网线-USB转接线 49.00 块,键盘 25.90 块,串口线 59.00 块,打印两张车牌 2 块。
打车费,周六来回打了两趟车,周日来回打了两趟车,花销分别是 21.37 元,29.76 元,21.37 元,24.29 元。
直到今晚,买设备花销 152.61 元,打车花销 96.79 元,共计花销 249.4 元。
得算清楚,算明白。
当时两千块的预备金还剩 632.65 元,现在还剩 383.25 元。
2025 年 11 月 6 日
高铁536元,打车175.46元,住宿655.89元,吃饭192.8元,共计1,560.15元。
1 23 号晚,郑州二七鸿运宾馆,花销69 .84 元,未开票。
住宿,高铁和打车的发票都开了。
替公司省钱,姜总额外补给自己300块。
公司现在的出差补助是50一天,包住宿、交通,吃饭自理,一共出差从24号到4号共12天,1,560.15 +600 - 192.8=1967.35。
我算一算。
项目预备金姜总当时给我打了两千块。
出差12天,出差每天补助50一共补助给我六百块,这是我应得的,拿到了。
替公司省钱,姜总额外补助给自己三百块,拿到了。
出差费用减去吃饭自理的花销,这是项目预备金真正开销的费用,一共是 1560.15 元 - 192.8 元 = 1,367.35 元。
这样算下来,自己一共拿了九百块补助,两千块的预备金还剩下 2000 元 - 1367.35 元 = 632.65 元 。
这六百多就是可支配的项目预备金了。
2025 年 11 月 5 日
截至今天,差旅费花销又新增了几项。
3号晚,下班后高德打车去酒店,花销13.91元;晚上点美团外卖,花销16.3元;品苑清雅酒店住宿花销99.83元,开票九十九块。
4号,上午高德打车去濮阳东站,花销27.24元。
4号,下午一顿汤面花了十块钱,如果这顿饭也算差旅费的话,花销10元。
2025 年 11 月 3 日
梳理下通勤费。
24号,东站打计程车到濮阳高速路口,花销52.60元,开票六十块。
25号,退了品苑清雅酒店后打车到爱尚依家宾馆,花销10.48元。
26号,中午打车去品苑清雅酒店开住宿发票,来回花销分别为13.31元,11.75元。
27号,28号,30号,31号,11月3号,早上打车到高速路口,花销分别为7.77元,8.36元,7.06元,7.18元,7.2元。
29号,早上打计程车到高速路口,花销8.6元,开票十块。
长治东-郑州,郑州东-濮阳东,濮阳东-郑州东,郑州东-太原,花销分别为112.5元,93元,116元,214.5元,暂未开票。
梳理下住宿费。
23号晚,郑州二七鸿运宾馆,花销69.84元,未开票。
24号晚,品苑清雅酒店,花销100.89元,开票一百块。
25-30号共六晚,爱尚依家宾馆,花销210元,开票二百块。
31-3号共三晚,朝夕相处宾馆,花销245.17元,暂未开票。
截至3号午,通勤 + 住宿共计1296.21元。
梳理下吃饭花了多少钱。
24号午,一碗西红柿鸡蛋面,花销14元;24号晚,美团点外卖,花销15元;25号-3号,冯记面馆吃了八碗面,共计花销64元,砂锅店光顾四次,共计花销52元,跑过两次小卖部,共计花销20元,共享单车骑过一次,花销1.5元。
截至3号午,通勤 + 住宿共计1462.71元。
四点半,写完今天的工作日志。
1 2 3 4 5 11月3日 现场观摩:自动栏杆机在交易成功后短暂失灵; 车道出卡机未检测到车辆吐卡失败,由维护人员手动按卡机绿色按钮后正常出卡; 卡机刷子损坏读卡不稳定,短暂关闭该车道后维护处理; 车道内车辆停靠不当,交易完成启动车辆后车侧身剐蹭到收费岛防护栏。
2025 年 10 月 31 日
1 C :\Users\Lenovo\AppData\Roaming\Typora\typora-user-images
车辆驶入: 压到地感线圈 -> 线圈产生信号 -> 信号线传到黑色智能节点 的DI1端子 -> 节点通过网线告知白色网关 -> 网关启动交易流程。
ETC交易: 网关通知RSU控制器 -> 控制器通过射频线驱动RSU天线 扫描 -> 与车载OBU通信 -> 交易数据经网关WAN口上传云端验证。
放行: 验证成功 -> 网关通过网线命令智能节点 -> 节点通过DO1端子控制栏杆机 抬杆,通过DO2端子控制信号灯 变绿 -> 同时,网关通过LAN口将金额发送到费额显示器 显示。
车辆离开: 压到出口线圈 -> 信号传至智能节点 -> 节点控制栏杆落杆。
早上刚到就用 DeepSeek 分析收费岛核心网口布线逻辑。
贴一下这段解析吧。
图2 & 图3:机柜内部核心布局(对应地图中的白色网关、黑色节点)
这两张图展示的是同一个机柜内部,角度略有不同,我们结合起来看。机柜布局从上到下非常清晰:
顶层:电源接入与分配区(图2顶部)****你看到的是: 一排电源插座,上面插着多个黑色电源适配器。接线逻辑: 这是整个机柜的“心脏”。市电进来后,通过这些插座和适配器,转换成各种设备需要的安全电压(如12V、24V),再通过下方的红线(火线)、蓝线(零线)分配到各个断路器和设备。“冰箱”那个标签可能是个趣称,可能指代某个大功率设备或就是个内部标记。
中层:网络通信核心 —— 白色边缘网关(图3中部)****你看到的是: 那个白色的、有多个网口和指示灯的设备。这就是我上次说的“智慧边缘网关”,是整个车道的“大脑”,负责数据交换和上传。**网口分布与接线逻辑(对照地图看,这是重点!): WAN/UPLINK口(图3,网关左侧的网口):这个口通常有显著不同。在你图片里,它很可能就是那个连接着 蓝色网线或者最粗网线的接口。 这是通往收费站服务器的总上行线,是车道的生命线,绝对不能动!****LAN口(图3,网关右侧的多个网口):这些口用于连接内部设备。根据常见配置:其中一个LAN口(比如LAN1)会接一根网线(比如灰色)到 下层黑色“智能节点”(地图中的内部通信)。这就是“大脑”和“手脚”之间的神经。另一个LAN口(比如LAN2)会接一根网线到 图4中的RSU控制器上。还会有一个LAN口预留给 费额显示器**(图1/图5中的蓝色收费亭设备),网线会从机柜接到亭子里。
下层:现场控制核心 —— 黑色“智能节点”(图2/3下部)****你看到的是: 那个标有“智能节点”的黑色设备,下面有一排排接线端子(绿色和黄色),插满了红、黄、蓝等颜色的电线。接线逻辑(对照地图看,这是难点!):****上行通信: 它通过一根从上面白色网关来的网线 (很可能是灰色)接收指令。数字量输入(DI): 端子排上标有DI1, DI2等字样的地方(图片中标签较小,但逻辑如此),接的是地感线圈 的信号线。线圈检测到车辆,就给这里一个“通/断”信号。数字量输出(DO): 端子排上标有DO1, DO2等字样的地方,接的是自动栏杆机 和车道信号灯 的控制线。系统命令通过这里发出,控制栏杆抬起落下,信号灯红绿变化。
图4:RSU控制器与配电区(对应地图中的RSU控制器)
这张图展示了机柜的另一个部分,通常是并排安装的。
顶部:配电断路器****你看到的是: 两排“CHNT”品牌的微型断路器。接线逻辑: 每个断路器控制一个回路。比如:一路给白色网关,一路给智能节点,一路给RSU控制器,一路给栏杆机,一路给费额显示器。你维护时操作某个设备,最好关闭对应的断路器,保证安全。
中部:RSU控制器****你看到的是: 两个黑色的“RSU控制器”,上面有指示灯。这就是ETC通信的核心。接线逻辑(对照地图看):****网络端: 它通过一根网线 (比如从白色网关的LAN2口来的蓝色网线)与“大脑”连接,传输交易数据。射频端: 它背后有专用的射频接口,通过一根粗大的同轴电缆 连接到车道顶棚或安全岛上的RSU天线 (就是那个像平板一样的东西)。车辆OBU的信息就是通过这个链路收发。
右侧:其他通信模块****你看到的是: 灰色的模块,可能用于4G/5G备份通信或与收费站的其他系统交互。
十点半去路口把接线看了一遍,杨工不懂,附近也没什么人懂,这网口接线本来就是出厂后由专业人员配置的,各司其职哪有外行闲着没事干去瞎琢磨。
在这里工作也是够闲的,看他们的工作氛围就能明显觉察到,幸福感挺高。
中午十二点多就走了。
妈的,下午六点,工作日志还没写。
1 2 3 10 月31 日1 、现场观摩特情处理,车辆完成交易后电动栏杆未抬起;无牌车辆通行处理;卡机出卡卡死;一辆ETC车在出口车道交易时显示余额不足,引导司机将ETC卡从OBU上取下后,交由维护人员使用车道非接触IC卡读写器完成刷卡支付。2 、观察出口车道收费设备内部的布线逻辑,重点确认了读卡机、RSU天线、自动栏杆机和费额显示器设备的连接和通信状态,拍照保存。
写完咯,连同设备图也打包好给发过去,周末愉快!
2025 年 10 月 30 日
提早写好工作日志。
1 2 3 10 月30 日1 、现场观摩特殊情况处理:发卡机卡住没有正常出卡,快速断电重启设备后恢复正常;在ETC车道排队等候车辆的车载单元被旁边车道的RSU天线误读导致在本车道交易失败,引导该车辆倒车脱离感应区后重新驶入后,成功完成交易并抬杆放行;入口处后车跟车过近误将前车的通行卡取走,现场人员引导后车在安全区域等了10 分钟,待系统释放掉该卡的绑定信息后再重新进车道取卡。2 、查看高速联网收费系统技术方案文档,系统学习车道主要设备技术要求、标志标线和交通安全措施等。
下午六点钟,刚吃完饭上楼进房间,打了两把游戏就看到姜总打来语音,明天得去高速路口拍设备接线和外形照片,回太原会提前通知。
2025 年 10 月 29 日
午饭前看完《交通运输部-高速公路联网收费系统优化升级收费站标准化专项试点技术方案附件》。
下午三点钟,昨天这个时候已经去高速路口收费站了。
下班前,写完今天的工作日志。
1 2 3 10 月29 日:1 、现场观摩调整车道卡机处摄像头的监控角度,更准确捕捉车辆驶入和通行过程中的CPC卡取放操作。2 、学习车道设备与收费系统之间如何通过标准化的通信协议进行控制和数据交换的接口规范。
GitCode - 全球开发者的开源社区,开源代码托管平台
2025 年 10 月 28 日
今早问了通信机房有没有可供连接的设备,没有。
杨师傅刚给发了机器人和外场的日志,可以看过车的逻辑和交易的逻辑。
下午三点钟跟杨工去高速收费站处,在路口一直呆到四点半左右才返回上楼,观摩并记录了一些现场车辆通行出入口的特殊情况。
1 划防盗栏,卡机刷子,无卡过人工通道,卡太厚出不来,调整摄像头角度,出卡慢问题,无车牌处理,称重信息缺失,牵引车强制查验,排查摄像头问题,识别不到车辆,手动按绿色按钮弹出卡机
下班前工作日志写个大概:
1 2 3 4 5 10 月28 日1 、现场观摩车辆在收费站出入口通行特情处理,包括无车牌人工处理、卡机刷子损坏导致读卡不稳定、CPC 卡太厚卡在出口出不来、货车剐蹭防护栏等。2 、观察到导致卡机出卡慢有诸多原因,如卡盒内CPC 卡排列不齐、卡片过厚、初始化卡片信息时网络拥堵、感应线圈触发信号延迟等。3 、查看车道系统平台的日志区域了解车辆通行和缴费交易的逻辑。4 、查看高速联网收费系统技术方案文档,系统学习出入口车道关键业务流程、站级交易系统功能模块、车道布局等。
高速收费站入口处,卡机出卡慢会是什么原因导致的,扫描到车辆信息后需要做什么比对才能绑定什么信息来着,你给讲一讲。
DeepSeek 回答挺详细专业,学习一下:
好的,没问题!您这个问题问得非常专业,是高速公路收费系统运维中很常见的一个问题。我来给您详细拆解一下。
卡机出卡慢的常见原因
卡机(自动发卡机)出卡慢,就像打印机卡纸一样,是由多种因素造成的。我们可以从硬件、软件、外部环境三个层面来分析:
1. 硬件问题(最常见)
卡盒问题 :卡盒没有安装到位,或者卡盒内的通行卡数量太少、排列不整齐,导致取卡机械臂无法顺利吸起或抓取卡片。
机械结构磨损/故障 :发卡机的核心部件是取卡臂、传送轮等机械装置。长期使用后,可能会出现磨损、松动、或者有灰尘、油污堆积,导致动作不顺畅、卡顿。
传感器故障 :发卡机内部有多个光学或机械传感器,用于检测卡盒是否有卡、卡片是否被成功抓取、卡片是否运送到出卡口等。任何一个传感器失灵或脏污,都会导致系统误判,从而反复尝试或停止出卡流程,造成延迟。
卡片本身问题 :通行卡变形、弯曲、过厚或过薄,也会在传送过程中遇到阻力。
2. 软件与系统问题
系统响应延迟 :当车辆驶入触发线圈后,触发信号需要经过工控机上传到收费站级的服务器,甚至可能要与省中心的系统进行短暂的通信,以获取时间、站号等信息来初始化一张卡片。如果网络拥堵或服务器处理能力达到瓶颈,这个响应过程就会变慢。
软件BUG或死机 :发卡机的控制软件可能出现临时性的错误,需要“反应”一下,或者工控机本身运行了太多程序,导致资源不足。
3. 外部环境因素
触发线圈灵敏度 :埋设在车道下的感应线圈可能因为损坏或参数漂移,导致检测车辆不灵敏,触发信号延迟,从而让整个出卡流程的启动就慢了半拍。
天气因素 :在极端的潮湿、寒冷或炎热天气下,电子元件和机械结构的性能可能会受到影响。
简单总结一下处理思路 :如果遇到某台卡机出卡慢,运维人员通常会先检查卡盒和卡片,然后清洁传感器和传送路径,最后再排查软件日志和网络连接。
扫描车辆信息后的比对与绑定流程
您问的这个问题,正是目前高速公路收费系统从 “计重收费” 向 “车型收费” 转变的核心,主要应用于ETC和CPC卡(复合通行卡)的入口流程。
当车辆驶入车道,摄像头(以及可能的其他辅助设备)会扫描捕捉车辆信息,主要包括:车牌号码、车牌颜色、车辆外观(用于AI识别车型)。
系统捕捉到这些信息后,会进行一系列快速的比对和绑定,以确保后续计费的准确性。
需要比对的信息清单:
与部级/省级数据库比对(核心比对) 比对对象 :全国ETC客户服务系统或省级数据库中的车辆档案。 比对内容 : 车牌号 :识别出的车牌号是否真实有效。 车牌颜色 :蓝牌、黄牌、绿牌等,不同颜色代表不同的车辆类型(如客车、货车、新能源车等)。 车辆特征(车型分类) :这是最关键的一步。系统会用AI图像识别技术判断车辆的实际物理特征(如车轴数、车头高度、轮廓等),并与数据库中该车牌登记的标准车型 进行比对。 目的 :防止“大车小标”(例如,实际是三类货车,但办理ETC时登记为二类车,以少交通行费)。如果识别出的车型与数据库登记的车型不一致,系统会标记异常,在出口时可能会转为人工核查,按实际车型收费。
与黑名单/状态名单比对 比对对象 :状态名单系统(包括黑名单、挂失卡、支付账户异常等名单)。 比对内容 :该ETC车辆或CPC卡是否被列入异常名单。 目的 :如果车辆在黑名单中,入口栏杆不会抬起,或者系统会提示工作人员进行干预。
绑定什么信息?
在完成上述比对且无误后,系统会生成一条入口流水记录,并将以下信息绑定 在一起,写入即将发放的CPC卡 或ETC交易记录 中:
入口信息 :入口收费站编号、入口时间、车道号、操作员号。
车辆信息 :车牌号码 、识别出的车型 (作为计费依据)。
卡片信息 :CPC卡的内部序列号。
简单来说,这个绑定的过程就是: 把 “谁(车牌车型)” 、“在哪儿上的(入口站)” 、“什么时候上的(入口时间)” 、“用的哪张卡(卡号)” 这几条信息打包成一个数据包。
后续流程:
对于ETC车辆 ,这个数据包会通过RSU(路侧天线)写入OBU(车载单元),然后抬杆放行。
对于非ETC车辆(取CPC卡) ,这个数据包会写入CPC卡中,然后卡机才吐卡。司机拿到的CPC卡里,已经存储了所有这些信息。在出口时,读卡器会读取这些信息,结合出口信息,计算出准确的通行费。
2025 年 10 月 27 日
上网找找资料看。
高速公路收费系统工程应用软件技术方案-CSDN博客
下午,姜总补发了两份项目文档,可供参考学习。
《智能边缘网关产品研发技术方案V1.1》《交通运输部-高速公路联网收费系统优化升级收费站标准化专项试点技术方案附件》。
晚八点钟,补上今天的工作日志。
1 2 3 4 10 月27 日1 、杨师傅详细解答收费站入口处地感线圈如何在车辆驶过后,触发三目摄像头抓拍车牌和车型识别,并发出是否有车信号控制栏杆上抬下落的,介绍各环节如何衔接。2 、人工收费车道出现了车主准备取卡,而读卡机发生故障卡死没有正常吐出通行卡的问题,观摩了现场维护人员打开设备机柜快速重启硬件后让卡机出卡正常;此外杨师傅简单描述了无牌车、车牌识别错误等情况的现场处理流程。3 、学习智能边缘网关产品研发技术方案,初步了解高速公路收费系统的整体硬件架构、软件架构以及标准化设计原则。
2025 年 10 月 24 日
27号晚,补上24号的工作日志。
1 2 10月24日 跟杨师傅去到高速路口收费站现场,认识了ETC天线、读卡发卡机、车牌识别摄像机、自动栏杆机和费用显示器等外部核心设备,了解到来往车辆从入站识别、计费收费到抬杆放行的基本流程。
晚上住一晚酒店,接下来的两天周末可以好好休息了。
河南 特微智能
2025 年 12 月 18 日
trawe.cn
特微乐行(广州)技术有限公司_百度百科
硬件产品 :发卡机器人,缴费机器人,ETC 特情自助终端,智慧服务厅,关道机 + 限高智能终端,岛头智能节点,岛尾智能节点,边缘云站,缴费 + 电票智能终端,智能支付终端,相控阵天线,读卡器,电子标签,智慧云舱。
软件产品 :智慧云收费系统,远程值守云坐席系统,移动支付系统,云监控平台,电子发票系统,ETC 发行平台。
中天高科
2025 年 12 月 18 日
到郑州的第二天。
昨天下午四点半就到了郑州站,找个车子去预定的酒店呆了一晚,六点多点两份外卖把晚饭解决了,随便玩会儿晚十二点不到就睡觉了。
早上七点半醒来,洗漱收拾行李,下楼,在路口打个车子出发去中天,半小时后到,八点半就坐在工位上了。
二楼,挺宽敞一办公室。
分布式消息中间件-RocketMQ_rocketmq解耦-CSDN博客
百度地图
北京特微智能科技有限公司_百度百科
2025 年 10 月 27 日
在河南濮阳的第四天,上周五下午到了濮阳站高速路口,在附近度假区订了六晚的民宿一直呆到今天。
没什么好聊的,已经在日记里吐槽过了。
事业单位 医生
2026 年 2 月 25 日
医生要编制好还是不要编制好呢?
1 2 3 4 工作稳定性 事业编制医生:事业编制医生属于事业单位的正式员工,工作稳定性较高。编制内医生享有国家规定的各类福利保障,如医疗保险、养老保险、住房公积金等。此外,编制内医生的工作岗位相对固定,受到单位保护,较少面临被解雇的风险。 合同制医生:合同制医生通过签订劳动合同的方式受聘于医院,工作稳定性相对较低。合同期满后,医院有权决定是否续约,这使得合同制医生在工作稳定性上不如编制内医生。
1 2 3 事业编制医生:编制内医生的福利待遇通常较为优厚,包括稳定的工资、绩效奖金、带薪年假、定期体检等。此外,事业编制医生在退休后能够享受相对较高的养老金,这为其晚年生活提供了保障。 合同制医生:合同制医生的福利待遇因医院和地区而异,可能不如编制内医生稳定和丰厚。虽然一些大城市的大型医院可能为合同制医生提供较好的待遇,但总体来说,他们的福利水平仍不如事业编制医生。
1 2 3 事业编制医生:编制内医生在职业发展上可能享有更多的机会和资源。例如,他们通常有更多的机会参加专业培训、学术交流和科研项目。此外,事业编制医生在职称评审和晋升方面可能会受到优待。 合同制医生:合同制医生在职业发展上面临更多的挑战和不确定性。他们需要通过出色的工作表现和个人努力来获得职业晋升的机会。尽管合同制医生在某些情况下可能会受到不公平的待遇,但一些能力出众的医生依然能够在职业上取得显著成就。
1 2 3 事业编制医生:事业编制医生的职业路径相对固定,工作调动和变更较为困难。这种稳定性虽然提供了安全感,但也限制了职业灵活性。对于一些希望尝试不同医院或地区工作机会的医生来说,编制内的限制可能成为一种束缚。 合同制医生:合同制医生在职业选择上具有更大的灵活性。他们可以根据个人兴趣和职业规划自由选择不同的医院和工作地点。这种灵活性使得合同制医生能够更好地适应个人和职业发展的需求。
1 2 3 安全感和稳定性:对于重视工作稳定性和安全感的医生来说,事业编制无疑是一个更好的选择。编制内的稳定工作和优厚福利能够提供更高的生活保障,减少职业风险。 追求挑战和自由:对于那些喜欢挑战和追求自由的医生来说,合同制可能更为适合。他们可以利用灵活的职业选择来实现个人职业目标,获得更多的职业发展机会和生活体验。
编制
2026 年 3 月 5 日
专技岗晋升实行的是职称评聘制 ,分初、中、高三个层次13个等级,其中11-13级为初级职称,8-10级为中级职称,5-7级为副高职称,1-4级为正高职称 。从初级职称晋升中级职称,原则上要求拿到初级职称并在岗三年以上,中级晋升副高,要求在中级岗位任满五年以上,副高晋升正高,同样要求副高满五年。
专技岗想要晋升一般要求具备三个条件:1、拿到相应的职称,这是先决条件;2、职称岗位有空缺,这是必要条件;3、单位和领导愿意聘任,这是决定条件。三个条件缺一不可。
(99+ 封私信 / 81 条消息) 山西省直事业单位考试容易考吗? - 知乎
教材,机构,题集,套卷。
中公,花果,粉笔,中公。
2026 年 3 月 3 日
事业单位考试A、B、C、D、E类是指什么_华图问答_广东华图教育
事业单位abcde类的区别是什么_事业单位招聘考试_华图教育
2026 年 2 月 25 日
事业单位管理岗与技术岗有哪些区别_华图教育
人事考试网 - 山西省人力资源和社会保障厅
专业技术岗、管理岗和工勤岗傻傻分不清
管理岗和专技岗有什么区别?这五个方面对比,就明白了!
卫生专业技术等级一般分为十三个等级,你都知道吗?
(99+ 封私信 / 81 条消息) 卫生专业技术人员各级别职称制度 - 知乎
2026 年 2 月 9 日
(99+ 封私信 / 81 条消息) 事业单位考试自然科学c类具体考哪些? - 知乎
2026 年 1 月 6 日
人事考试网 - 山西省人力资源和社会保障厅
2026山西事业编考试时间:3月28日、29日! - 上岸鸭公考
2026 年 1 月 26 日
驾考
2026 年 2 月 27 日
虚假一年,吊销两年,撤销三年,醉驾五年,逃逸终生不得再考(假一吊二撤三醉五逃终生)。
北京市小车科目一模拟考试章节练习【驾考宝典】
花了一小时,做完了驾驶证和机动车管理100题。
2026 年 2 月 26 日
科一、科二、科三、科四到底考什么?80%的学员都没搞清楚
第一次考驾照不知道考什么?一分钟看完流程_懂车帝
🚗手动挡VS自动挡,哪个更优?-有驾
2025驾校学车考驾照,到底选手动挡C1好还是选自动挡C2好?一篇文章讲清楚区别