最近在开发一个RPC服务,在多种RPC框架之间选来选取,最终还是选择了hessian,整体上来说,hessian不仅简单而且优秀,还符合“微服务”的轻量级服务治理的理念;这个RPC框架优秀到简直没有升级和扩展的必要... 不过在实际开发中,遇到了一个小小的问题,就是如何通过hessian协议(框架)来发送一些“附属信息”,比如token等;这些附属信息,内容较小,但是可能条目个数较多,如果都封装成JAVA对象通过API传送,确实引入一些扩展性的问题。既然hessian底层基于HTTP协议,这些附属信息能否通过Header传递呢? 经过思考和验证,不仅可以,而且这也是最佳的策略;此后Client端如果需要额外传递更多的附属信息,则不需要升级API Client,透明易用。同时通过HEADER传送一些信息,这对WEB Proxy层也是良好的。
设计要求:
1、对于一个附属信息,比如TOKEN、备注等附属信息,不能通过hessian API传送。
2、附属信息可能很多,不过需要支持动态增加,增加时不应该修改hessian API,以便给Client带来兼容性问题。
3、性能问题需要兼顾。
4、附属信息通过HTTP Headers发送。
经过研究Hessian源码,发现Hessian请求默认会在header中添加一些标识信息,不过addHeader的操作是“关闭的”,不能通过简单的Spring配置或者Hessian API额外的增加其他的header;为了支持此特性,我们需要扩展Hessian API,本实例基于Spring容器。
1、我们希望Headers可以通过Spring配置方式制定。
2、我们希望可以在runtime期间,Hessian请求发送时开发者可以自定headers并通过Hessian协议发送。
3、Hessian Remote Service应该可以解析出header,并能够在Service内部获得header的内容,以便使用。
4、请求响应结束后,这些headers应该被Clear,即无状态。
设计思路:
1)那些可以通过Spring配置指定的headers,我们可以通过扩展Hessian FactoryBean来实现,将配置中指定的header(通常为全局headers)保存在Spring Bean属性中。
2)那些需要在runtime期间动态添加的headers,为了避免耦合,我们可以使用ThreadLocal方式,将它们保存在Context中,并在Hessian请求实际发送之间,扩展其addHeader方法,并将它们添加在HTTP 请求中。
3)Hessian Remote Service,通常为HTTP Servlet实例,那么我们可以基于Fitler的方式解析这些headers,这也要求Hessian Headers需要遵循一定的规则,比如header均已“x-rpc-hessian”开头等。
5)对于Spring容器中的remote service,我们也可以扩展相应的FactoryBean,来解析这些header,并放置在ThreadLocal中,此后Service执行过程中,就可以获取这些headers内容。
一、HContext.java
一个基于ThreadLocal实现的Context类,用于保存runtime期间开发者动态添加的headers。
import java.net.URLDecoder; import java.net.URLEncoder; import java.util.Collections; import java.util.HashMap; import java.util.Map; /** * Created by liuguanqing on 17/4/12. * 如果header中,有中文,需要进行URLEncoder后才能发送 */ public class HContext { public static final String KEY_PREFIX = "x-rpc-"; public static final String UTF8 = "utf-8"; public static final String SOURCE_HOST = "source_host"; public static final String REQUEST_TYPE = "request_type"; private static final ThreadLocal<Map<String,String>> context = new InheritableThreadLocal<>(); public static void init() { Map<String, String> model = context.get(); if(model == null) { context.set(new HashMap<>()); } } public static void put(String key,String value) { if(value == null) { return; } Map<String,String> model = context.get(); if(model == null) { init(); } if(!key.startsWith(KEY_PREFIX)) { key = KEY_PREFIX + key; } context.get().put(key,value); } public static void putAll(Map<String,String> kvs) { if(kvs == null || kvs.isEmpty()) { return; } for(Map.Entry<String,String> entry : kvs.entrySet()) { String value = entry.getValue(); if(value == null) { continue; } put(entry.getKey(),value); } } public static String get(String key) { key = KEY_PREFIX + key; Map<String,String> model = context.get(); if(model == null) { return null; } return model.get(key); } public static Map<String,String> getAll() { Map<String,String> model = context.get(); if(model == null) { return Collections.EMPTY_MAP; } return model; } public static void clear() { context.remove(); } }
需要注意,如果headers中包含中文,需要进行UrlEncoder之后才能发送,对应在Service端则需要UrlDecoder。
二、HessianProxy扩展类
大家都知道,Hessian客户端必须创建一个HessianProxy代理类,才能进行RPC调用。HessianProxy是通过JAVA动态代理方式创建,其代理了Serivce API的接口。HessianProxy负责进行实际的RPC请求和响应处理,它在发送请求时总会调用内部的addHeader方法,那么我们即可围绕addHeader方法开展。
import com.caucho.hessian.client.HessianConnection; import com.caucho.hessian.client.HessianProxy; import com.caucho.hessian.client.HessianProxyFactory; import java.lang.reflect.Method; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * Created by liuguanqing on 17/4/12. * */ public class HessianWithContextProxy extends HessianProxy { protected Map<String,String> globalHeaders = new HashMap<>(); public HessianWithContextProxy(URL url, HessianProxyFactory factory) { super(url, factory); HContext.init(); } public HessianWithContextProxy(URL url, HessianProxyFactory factory, Class type) { super(url, factory, type); HContext.init(); } public HessianWithContextProxy(URL url, HessianProxyFactory factory, Class type,Map<String,String> headers) { super(url, factory, type); HContext.init(); globalHeaders = headers; } protected void addRequestHeaders(HessianConnection conn) { super.addRequestHeaders(conn); try { HContext.putAll(globalHeaders);//global headers cant be replaced! Map<String, String> context = HContext.getAll(); for (Map.Entry<String, String> entry : context.entrySet()) { try { String value = entry.getValue(); if (value == null) { continue; } conn.addHeader(entry.getKey(), URLEncoder.encode(value, HContext.UTF8)); } catch (Exception e) { // } } } finally { HContext.clear(); //after send,we clear at once. //must clear context here. } } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return super.invoke(proxy,method,args); } }
对于那些global级别的headers,即通过Spring配置文件声明的、所有请求都公用的headers,我们应该在保存在HessianProxy实例的内部;对于那些runtime期间动态增加的headers,我们需要从HContext中获取,并将它们均通过addHeaders方法添加到connection中。考虑到ThreadLocal的容器的生命周期管理,我们必须在addHeaders方法调用结束后,进行clear。
在考虑HContext.clear的时机时,本人曾经引入过一些问题。起初,本人在invoke方法返回之前调用clear,事实上经过测试发现,这是错误的。需要注意,invoke方法的执行时机时“调用API的任何方法都会执行”(包括toString、getClass等等),所以Client请求在发送之前,可能多次执行invoke,那些不是API方法的执行,会导致HContext数据被清除。所以,我们应该在临近请求发送的地方进行HContext操作。
三、HessianProxyFactoryBean扩展
HessianProxy是有HessianProxyFactory创建的,我们通常可以在此FactoryBean中指定serviceUrl等等一些Hessian Client的配置信息,当然我们可以扩展它,并支持配置一些global级别的headers,这些headers,通常是一些常量,此Service Client的所有请求都可以通用;比如Token等。
import com.caucho.hessian.client.HessianProxyFactory; import com.caucho.hessian.io.HessianRemoteObject; import java.lang.reflect.Proxy; import java.net.URL; import java.util.HashMap; import java.util.Map; /** * Created by liuguanqing on 17/4/12. */ public class HessianWithContextProxyFactory extends HessianProxyFactory { private Map<String,String> globalHeaders = new HashMap<>(); public HessianWithContextProxyFactory() { super(); } public void setGlobalHeaders(Map<String, String> globalHeaders) { this.globalHeaders = globalHeaders; } public Map<String, String> getGlobalHeaders() { return globalHeaders; } @Override public Object create(Class api, URL url, ClassLoader loader) { if (api == null) throw new NullPointerException("api must not be null for HessianProxyFactory.create()"); HessianWithContextProxy handler = new HessianWithContextProxy(url, this, api,globalHeaders); return Proxy.newProxyInstance(loader, new Class[]{api, HessianRemoteObject.class}, handler); } }
这个扩展类比较简单,只需要注意,在创建HessianProxy实例时,将配置的global headers作为参数传递过去。因为面向开发者或者Spring框架时,只有HessianProxyFactory是可见的,所以这些参数只能通过FactoryBean配置然后传递给HessianProxy。
四、基于Spring框架的ProxyFactoryBean扩展
Spring支持Hessian框架,它基于HessianProxyFactoryBean实现,这个类名与Hessian原始的“HessianProxyFactory”比较类似,不过它是Spring容器的工厂bean,用于创建单例模式的HessianProxyFactory实例。注意此类是面向Hessian Client端!
import java.net.InetAddress; import java.net.NetworkInterface; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; /** * Created by liuguanqing on 17/4/12. */ public class HessianWithContextProxyFactoryBean extends HessianProxyFactoryBean { protected HessianWithContextProxyFactory proxyFactory = new HessianWithContextProxyFactory(); protected Map<String,String> headers = new HashMap<>(); public void setHeaders(Map<String, String> headers) { this.headers = headers; } private String localIp; public HessianWithContextProxyFactoryBean() { super(); super.setProxyFactory(proxyFactory);//强制修改 } @Override public void afterPropertiesSet() { super.afterPropertiesSet(); localIp = getLocalIp();//本地IP地址 headers.put(HContext.SOURCE_HOST,localIp); proxyFactory.getGlobalHeaders().putAll(headers);//append } @Override public Object invoke(MethodInvocation invocation) throws Throwable { //all the methods of hessian instances will be invoked here, //so we cant use threadLocal there. return super.invoke(invocation); } public String getLocalIp() { try { //一个主机有多个网络接口 Enumeration<NetworkInterface> netInterfaces = NetworkInterface.getNetworkInterfaces(); while (netInterfaces.hasMoreElements()) { NetworkInterface netInterface = netInterfaces.nextElement(); Enumeration<InetAddress> addresses = netInterface.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress address = addresses.nextElement(); if (address.isSiteLocalAddress() && !address.isLoopbackAddress()) { return address.getHostAddress(); } } } }catch (Exception e) { // } return null; } }
没有特别之处,只是我们默认添加了一个全局header,表示Client端的本机IP地址,主要用于Remote Service跟踪请求的来源。
五、Remote Service端
import org.springframework.remoting.caucho.HessianServiceExporter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLDecoder; import java.util.Enumeration; /** * Created by liuguanqing on 17/4/12. * */ public class HessianWithContextServiceExporter extends HessianServiceExporter { @Override public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理请求 try { Enumeration<String> headers = request.getHeaderNames(); while (headers.hasMoreElements()) { String key = headers.nextElement(); if(key.startsWith(HContext.KEY_PREFIX)) { try { String value = request.getHeader(key); if(value != null) { HContext.put(key, URLDecoder.decode(value,HContext.UTF8)); } } catch (Exception e) { // } } } HContext.put(HContext.REQUEST_TYPE,"SDK"); super.handleRequest(request,response); } finally { HContext.clear(); } } }
HessianServiceExporter是Spring提供的机制,即可以将Spring Bean暴露并与Servlet容器结合(Spring-web),它只有一个主要的方法,用于处理Client发送的请求,那么我们可以在此方法中解析Client发送的headers,并保存在HContext中。
六、使用方式
1、Client端配置
<bean id="remotePortalService" class="com.demo.hessian.spring.HessianWithContextProxyFactoryBean"> <property name="serviceUrl" value="${portal.service.url}" /> <property name="serviceInterface" value="com.demo.service.PortalService" /> <property name="overloadEnabled" value="true"/> <property name="connectTimeout" value="3000"/> <property name="hessian2" value="true"/> <property name="readTimeout" value="3000"/> <property name="headers"> <map> <entry key="project" value="${portal.service.project}"/> <entry key="token" value="${.portal.service.token}" /> </map> </property> </bean>
2、Client端JAVA代码样例
HContext.put("comment","这是Hessian服务"); HContext.put("operator","zhangsan"); remotePortalService.send(target); //不需要对HContext进行clear,HessianProxy会自动执行。
3、Remote Service端配置(web.xml)
<servlet> <servlet-name>hessianService</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-hessian.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>hessianService</servlet-name> <url-pattern>/rpc/*</url-pattern> </servlet-mapping>
spring-hessian.xml配置
<bean name="/portal" class="com.vipkid.utils.hessian.spring.HessianWithContextServiceExporter"> <property name="service" ref="portalService"/> <property name="serviceInterface" value="com.demo.service.PortalService"/> </bean>
你可能还需要在其他配置文件中声明“portalService”,这是一个Spring Bean。此外,你的Spring Controller的URI路径也需要以“/rpc”开头,即与web.xml配置保持一致。
4、Remote Service端JAVA示例
public Object send(Object target) { String clientId = HContext.get("source_host"); //HContext已经在Exportor中进行了数据准备,所以可以直接使用,也不需要clear。 }
相关推荐
Hessian 协议是一种轻量级的 remoting on http 工具,使用简单的方法提供了 RMI 的功能。采用的是二进制 RPC 协议,所以它很适合于发送二进制数据。Hessian 主要用作面向对象的消息通信。 Hessian 协议报文格式可以...
它定义了消息结构,包含Action、Envelope、Header和Body等元素,通过HTTP或HTTPS进行传输。SOAP允许服务提供商定义复杂的WSDL(Web Services Description Language)来描述服务接口,增强了服务的规范性和互操作性。...
通过在etcd服务注册实例中增加Label信息,实现了路径、body和header的适配,从而使得服务与基础设施层的数据平面以及控制平面之间的通信更加顺畅。 在实践中,有赞还探索了灰度控制系统,这是一种在线上小范围内...
序列化方面,Dubbo 2.6.0支持Hessian2、Fastjson等多种方式,用于将Java对象转换为网络传输的数据格式。 7. **监控(Monitor)** 监控模块用于收集服务调用的统计信息,帮助开发者分析服务性能和稳定性。`...
内容概要:本文介绍了西门子S7-200模拟器bet2.5e版本的功能特点及其应用价值。该模拟器支持多种通讯协议如PPI和Modbus RTU,允许用户在没有真实PLC设备的情况下进行程序测试。它不仅能够模拟主站和从站的通讯,还可以便捷地导入用户程序并提供无限期使用的优势。尽管缺少网络通讯功能,但对于基础学习和简单项目的测试依然非常实用。 适合人群:工控领域的初学者、工程师和技术爱好者,尤其是那些希望在没有真实PLC设备的情况下进行编程和通讯测试的人。 使用场景及目标:适用于需要测试PLC程序和通讯协议的场景,帮助用户熟悉PLC编程和通讯机制,提高开发效率,减少硬件依赖。主要目标是在无硬件条件下完成程序调试和通讯测试。 其他说明:文中详细展示了如何使用VB.NET、Python和梯形图语言进行具体的编程实例,强调了注意事项如地址映射、波特率设置等。此外,还提到了一些替代方法来弥补网络通讯功能的不足,如使用虚拟串口工具。
内容概要:本文介绍了一款用于抽水蓄能容量优化配置的CPLEX程序,旨在帮助用户通过数学规划方法实现抽水蓄能电站的最佳容量配置。程序不仅提供详细的代码示例,还包括视频讲解,使编程小白也能轻松理解。文中详细解释了容量优化的目标、配置参数的选择以及储能出力的重要性,并展示了如何通过CPLEX库构建线性规划模型,设定目标函数、添加约束条件并求解模型。此外,文章还讨论了实际应用场景中的注意事项,如充放电效率、水库容量变化、负荷跟踪约束等,并提供了修改参数进行场景分析的方法。 适合人群:对抽水蓄能容量优化感兴趣的电力系统工程师、研究人员及编程爱好者。 使用场景及目标:适用于需要进行抽水蓄能容量优化的工程项目,目标是通过合理的容量配置降低运营成本,提高系统稳定性。用户可以通过修改配置文件中的参数,如抽水效率、电价等,来进行不同的场景分析。 其他说明:程序包内含实战讲解视频,有助于更好地理解和应用代码。代码中包含了多种实用技巧,如处理浮点数精度、时间序列数据等,这些都是实际项目中积累的经验。
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!
内容概要:本文详细介绍了三泵恒压供水控制系统的硬件配置、PLC程序设计、触摸屏组态以及调试技巧。首先讨论了硬件配置的选择,包括变频器、压力传感器的安装位置及其重要性。接着深入探讨了PLC程序的核心逻辑,特别是PID压力调节和泵组轮换策略,确保系统能够高效节能地运行并延长设备寿命。此外,文章还强调了触摸屏组态的关键要素,如压力趋势图和手动干预界面的设计。最后,作者分享了一些调试经验和常见故障排除方法,如模拟量处理、滤波算法的应用以及紧急情况下的手动模式保障。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和恒压供水系统感兴趣的读者。 使用场景及目标:适用于需要设计和实施恒压供水控制系统的工程项目,帮助工程师掌握从硬件选型到软件编程再到系统调试的完整流程,最终实现稳定的供水控制。 其他说明:文中提供了详细的IO分配表、梯形图逻辑示例和触摸屏界面设计建议,有助于读者更好地理解和应用相关技术。同时,作者还分享了许多实践经验,为实际操作提供了宝贵的指导。
内容概要:本文详细介绍了利用西门子S7-200 PLC和组态王搭建三泵恒压供水系统的全过程。首先阐述了硬件配置,包括IO分配、接线方式以及变频器的使用方法。接着深入探讨了PLC程序的核心逻辑,特别是压力闭环控制和泵轮换策略的设计。文中还分享了组态王界面设计的经验,强调了动态压力曲线和手自动切换功能的重要性。最后,作者结合实际案例,指出了调试过程中常见的问题及其解决方案。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是对PLC编程和HMI设计有一定基础的人群。 使用场景及目标:适用于需要构建高效稳定的恒压供水系统的工程项目。主要目标是确保系统能够根据管网压力自动切换水泵,保持压力稳定,同时提高设备使用寿命和维护效率。 其他说明:文章不仅提供了详细的理论讲解,还包括了许多实用的操作技巧和经验分享,有助于读者更好地理解和掌握相关技术和应用场景。
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!
将ppt转换成图片时,所有图片的文件名中会出现“幻灯片”三个字,这时,可以将本批处理文件复制到对应文件夹内,双击运行后,可以批量删除图片文件名中的“幻灯片”三个字。
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!
内容概要:本文详细介绍了如何利用Matlab和CPLEX构建共享电动汽车的两阶段优化模型。首先,通过整数规划确定最佳充电站位置,考虑用户需求覆盖率和建设成本之间的权衡。其次,采用动态调度模型处理实时车辆分配,确保各区域需求得到满足的同时优化运营成本。文中还讨论了数据预处理技巧如K-means聚类、移动平均滤波以及CPLEX求解器的高效配置方法。 适合人群:从事交通规划、物流配送等领域研究的专业人士,尤其是对数学建模和优化算法有一定了解的研究人员和技术开发者。 使用场景及目标:适用于城市交通管理部门、共享汽车运营商等机构进行电动车基础设施布局规划和日常运营管理。主要目的是降低建设和运营成本,提高用户体验和服务质量。 其他说明:作者分享了许多实践经验,包括如何避免常见错误(如矩阵转置问题)、提高求解速度的小技巧(如稀疏矩阵的应用)以及如何通过可视化工具辅助结果分析。此外,还提到了一些潜在改进方向,如加入充电桩排队时间和路网结构的影响因素。
内容概要:本文旨在构建一种基于记忆序列回放机理的机器人全局路径优化算法模型。通过模拟大脑海马体和前额叶中的记忆回放过程,改进了传统的机器人导航算法。模型采用自适应的Top-k竞争规则和回报折扣思想,使得智能体能够在复杂障碍物环境中快速找到最短路径。实验结果显示,智能体经过1-3次探索即可收敛到稳定状态,并找到最短路径,验证了模型的有效性和快速收敛性。 适合人群:对机器人导航、智能算法、神经科学感兴趣的科研人员,尤其是从事机器人路径规划和认知计算模型研究的学者和工程师。 使用场景及目标:①适用于复杂环境下的机器人路径规划与导航任务;②用于研究大脑记忆回放机制及其对决策过程的影响;③提高机器人在未知环境中的自主学习和适应能力。 其他说明:该模型不仅在仿真环境中表现优异,还在真实机器人实验中得到了验证。通过ROS平台和MATLAB接口,实现了对智能小车的有效控制和路径优化。此外,模型的收敛性和鲁棒性优于现有的DN2和基于小脑及基底神经节的混合模型,显示出更强的适应性和更高的性能。
基于迁移学习的端到端发音检错研究.pdf
文档支持目录章节跳转同时还支持阅读器左侧大纲显示和章节快速定位,文档内容完整、条理清晰。文档内所有文字、图表、函数、目录等元素均显示正常,无任何异常情况,敬请您放心查阅与使用。文档仅供学习参考,请勿用作商业用途。 Rust 以内存安全、零成本抽象和并发高效的特性,重塑编程体验。无需垃圾回收,却能通过所有权与借用检查机制杜绝空指针、数据竞争等隐患。从底层系统开发到 Web 服务构建,从物联网设备到高性能区块链,它凭借出色的性能和可靠性,成为开发者的全能利器。拥抱 Rust,解锁高效、安全编程新境界!
内容概要:本文详细介绍了基于51单片机的酒精检测报警器的设计与实现,涵盖了硬件选型、软件编程、功能实现等方面的内容。文中提供了两种不同版本的ADC芯片(AD0809和AD0832),分别阐述了它们的工作原理、代码实现及其优缺点。此外,文章还讨论了系统的各个组成部分,如MQ-3酒精传感器、LCD1602显示屏、按键设置、声光报警等,并给出了详细的代码示例和调试技巧。 适合人群:对单片机开发有一定基础的学习者、电子爱好者、从事交通安全管理的技术人员。 使用场景及目标:适用于防止酒驾的安全监控场景,旨在提高驾驶安全性和减少交通事故的发生。通过本项目的实践,读者可以掌握单片机的基本应用技能,了解传感器数据采集、处理和反馈机制。 其他说明:文中不仅提供了完整的代码实现,还分享了许多实际开发过程中可能遇到的问题及解决方案,如传感器预热、按键防抖、ADC读取时序等。同时,作者强调了该项目作为DIY作品,在正式应用中应注意合法合规性。
内容概要:本文详细介绍了基于虚拟同步发电机(VSG)技术的光储并网系统控制策略,涵盖光伏MPPT控制、储能直流稳压、VSG控制、虚拟阻抗增加及低压穿越控制等方面。针对每个控制策略提供了具体的实现代码和应用场景分析,强调了这些策略在保障电力系统稳定性方面的重要作用。文中不仅讨论了理论背景,还给出了大量实用的代码片段和技术细节,有助于理解和实施这些先进的控制策略。 适合人群:从事新能源发电系统设计、开发和维护的专业技术人员,特别是对光储并网技术和VSG控制感兴趣的工程师。 使用场景及目标:适用于希望深入了解光储并网系统内部工作机制的研究人员和技术爱好者;旨在为解决实际工程项目中的技术难题提供指导和支持,确保光储并网系统能够在各种复杂的电网环境下稳定运行。 其他说明:文章中提到的技术和方法已在多个实际案例中得到验证,能够有效提升系统的性能和可靠性。此外,作者还分享了一些调试经验和常见错误规避技巧,对于初学者非常有价值。
内容概要:本文详细解析了中兴ZXD2400电源电路图4.1版本,涵盖输入、转换和输出三大部分。输入部分介绍了LC滤波电路的作用及其参数计算方法;转换部分围绕UC3842芯片的工作原理展开,展示了其通过比较反馈电压和参考电压来实现电压稳定转换的功能;输出部分讨论了线性稳压芯片的应用。此外,还深入探讨了PWM控制、MOSFET驱动、补偿网络、电压采样、保护电路等关键设计细节,并提供了多个Python代码片段用于参数计算和电路特性模拟。文章不仅帮助读者理解电源电路的工作机制,还分享了许多实际操作经验和注意事项。 适合人群:从事电源设计的技术人员、电子工程师、DIY爱好者。 使用场景及目标:适用于希望深入了解电源电路设计原理和技术细节的人群,旨在提高读者对电源系统的理解和实际应用能力。 其他说明:文中提供的Python代码片段有助于快速定位关键芯片位置、计算重要参数,便于理论联系实际。同时提醒读者关注版本变更说明,避免因使用旧版图纸而导致的问题。
派克气动专业的系统组件