精华内容
下载资源
问答
  • SwitchButton 开关按钮的多种实现方式源码

    万次下载 热门讨论 2014-04-15 19:32:29
    SwitchButton 开关按钮的多种实现方式 具体的说明等可以查看以下文章: http://blog.csdn.net/vipzjyno1/article/details/23707149
  • 开关、按钮开关、自锁开关内部结构:   转载于:https://www.cnblogs.com/leo0621/p/8915876.html

    开关、按钮开关、自锁开关内部结构:

      

     

    转载于:https://www.cnblogs.com/leo0621/p/8915876.html

    展开全文
  • 开关电源讲解 -- 以反激式开关电源为例

    万次阅读 多人点赞 2019-01-07 10:43:17
    下图是一个反激式开关电源的原理图。输入电压范围在AC100V~144V,输出DC12V的电压。 开关电源的思路:要实现输出的稳定的电压,先获取输出端的电压,然后反馈给输出端调控输出功率(电压低则增大输出功率,反之则...

    一、整体概括

    下图是一个反激式开关电源的原理图。输入电压范围在AC100V~144V,输出DC12V的电压。

    开关电源的思路:要实现输出的稳定的电压,先获取输出端的电压,然后反馈给输出端调控输出功率(电压低则增大输出功率,反之则减小),最终达到一个动态平衡,稳定电压是一个不断反馈的结果。

    二、瞬变滤波电路解析

    市电接入开关电源之后,首先进入瞬变滤波电路(Transient Filtering),也就是我们常说的EMI电路。下图描述的是本次举例说明的瞬变滤波电路的电路图。

    各个器件说明:

    F1-->保险管:当电流过大时,断开保险管,保护电路。

    CNR1-->压敏电阻:抑制市电瞬变中的尖峰。

    R31、R32-->普通贴片电阻:给这部分滤波放电,使用多个电阻的原因是分散各个电阻承受的功率。

    C1-->X电容:对差模干扰起滤波作用。

    T2-->共模电感:衰减共模电流。

    R2-->热敏电阻:在电路的输入端串联一个负温度系数热敏电阻增加线路的阻抗,这样就可以有效的抑制开机时产生的浪涌电压形成的浪涌电流。当电路进入稳态工作时,由于线路中持续工作电流引起的NTC发热,使得电阻器的电阻值变得很小,对线路造成的影响可以完全忽略。

    三、整流部分

    各个器件说明:

    BD1->整流桥:作用应该知道。。

    L1、EC1、EC2->π型LC滤波电路,主要起的就是滤波,使输出的电流更平滑。

    四、开关电源主体部分

    开关电源的主题部分如下图,由于采用标注的方式更好说明,所以提供标注版PDF下载(末尾有链接)。

    五、输出端滤波电路

           下图是输出端滤波电路,由于采用标注的方式更好说明,所以提供标注版PDF下载(末尾有链接)。

    六、总结

    由于本人也是初次学习开关电源,所以只对整体部分有个了解,对比较困难的部分--变压器,目前还没有很深刻的理解,其余部分有不懂的地方,可以交流。

    标注版PDF下载:链接下载

    展开全文
  • 改造家里的开关成为智能开关,保留原有开关控制,零火版 亮点 成本不超20块,这可能是目前能找到的最便宜方案了吧。 体积较小,可以塞入86开关面板内。 手机app+智能音箱+物理开关控制,状态能同步。 接入点灯科技...

    改造家里的开关成为智能开关,保留原有开关控制,零火版,基础入门(一)

    亮点

    1. 成本不超20块,这可能是目前能找到的最便宜方案了吧。
    2. 体积较小,可以塞入86开关面板内。
    3. 手机app+智能音箱+物理开关控制,状态能同步。
    4. 接入点灯科技平台,支持wifi配网,包括blinker 设备密钥。
    5. 入手门槛大大降低,有电工基础,会接入线就行。

    过程1,下载固件和wifi配置网

    过程2,接线

    过程3,改造过程

    过程4,最后效果

    点动式物理开关演示

    器材

    需要的器件如下,
    在这里插入图片描述
    在这里插入图片描述

    接线

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    手机app端,Blinker设置

    1,下载客户端

    https://diandeng.tech/doc/app-download, 下载其app, 按注册blinker账号,获取密钥authkey,iOS 在app store 搜索blinker 安装

    在这里插入图片描述

    2,注册账号

    在这里插入图片描述

    3,创建设备

    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述
    到这一步,我们拿到设备的密钥,请记录下来,后面要用!!!!

    为设备增加一个按钮, 按键设置如下图
    在这里插入图片描述

    在这里插入图片描述

    固件下载

    1,下载网盘工具包

    链接:https://pan.baidu.com/s/1LU4XkcYnH83GNsA61ywFqw 提取码:681i 复制这段内容后打开百度网盘手机App,操作更方便哦
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2,烧写固件

    把esp8266插在烧写器上,然后插入电脑的usb口,如下
    在这里插入图片描述
    运行NdoeMcu-pyFlasher-4.0-xx.exe开始下载固件到esp8266
    在这里插入图片描述

    配置wifi上网

    1, 重启esp-01
    在这里插入图片描述
    在这里插入图片描述
    用手机连接到esp8266的wifi热点,热点名不是根据型号会不一样,多半以esp-xxx开头

    在这里插入图片描述
    在这里插入图片描述
    在电脑的浏览器打开http://192.168.4.1
    在这里插入图片描述
    选择要配置的wifi,点击
    在这里插入图片描述
    2,输入密码和点灯科技创建的设备ID
    在这里插入图片描述
    3,点确定开始配网
    在这里插入图片描述
    成功后

    在这里插入图片描述
    手机端
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    接入小爱同学配置

    1、在手机上安装米家,小米音箱app.
    2、在米家APP上添加点灯科技的扩展。

    在这里插入图片描述
    3,从小爱音箱APP上查看有没有找到设备
    在这里插入图片描述

    1、如果发现在设备,就说明配置成功了,我这里设备名叫“新的设备”,现在可以对小爱说 “打开新的设备”
    2、你还可以添加小爱学习
    在这里插入图片描述
    在这里插入图片描述

    在这里插入图片描述

    接入小度配置

    代码已经支持,作者还没来得及测试,参考小爱同学配置一下

    接入天猫精灵配置

    代码已经支持,作者还没来得及测试,参考小爱同学配置一下

    接入siri配置

    1,安装“快捷指令”app,点击打开

    在这里插入图片描述
    在这里插入图片描述
    点运行按钮测试一下开关,passwd是123456

    出现下图结果,说明接口调用成功了。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    现在对着siri说,“打开台灯”“关闭台灯”

    代码

    /*
    NodeMcu或esp-01/01s控制1路继电器,集成blinker平台,
    用手机app控制1路继电器开关,添加一路物理开关控制,继电器用常开(NO)模式
     
    v1.0
    Created 2021
    by 阳阳学编程
    www.sooncore.com
    抖音号:yyxbc2010
    微信号:yyxbc2010
    
    固件有网页配网功能,固件烧写工具:
    链接:https://pan.baidu.com/s/1WsE_2gERyjaUZFbwgJnsOw 提取码:56r8 
    
    说明:
    
    1,继电器高电平触发时,YYXBC_HIGH = 1,YYXBC_LOW  = 0
    继电器低电平触发时,YYXBC_HIGH = 0,YYXBC_LOW  = 1
    const int YYXBC_HIGH = 0 ;
    const int YYXBC_LOW  = 1 ;
    
    2,用esp-01时,物理开关接在vcc 和gpio2上,继电器接在gpio0上
    用nodeMcu时,物理开关接在vcc 和D4上,继电器接在D3上,下面的宏
    定义只能同时有一个生效
    
    //NodeMCU 继电器接D3,物理开关接D4
    #define LED_BUILTIN_LIGHT 0
    #define LED_BUILTIN_K2 2
    
    //Esp-01/01s,继电器接GPIO0,物理开关接GPIO2
    //#define LED_BUILTIN_LIGHT D3
    //#define LED_BUILTIN_K2 D4
    
    3,YYXBC_BUTTON_TYPE = 1时表示物理开关为点动模式,0时表示自锁模式
    const int YYXBC_BUTTON_TYPE = 1;
    
    获得具体连接电路图和更多资源,请参阅阳阳学编程网站 www.sooncore.com。
       
    This example code is in the public domain.
    */
    
    #define BLINKER_PRINT Serial
    #define BLINKER_WIFI
    #define BLINKER_MIOT_OUTLET              // 设置小爱灯类库
    #define BLINKER_DUEROS_OUTLET            // 设置小度灯类库
    #define BLINKER_ALIGENIE_OUTLET          // 设置天猫灯类库
    
    #define BLINKER_WITHOUT_SSL              //使用这个宏,表示不用SSL加密,可以得到更多内存
    
    //
    如果要使用apconfig配网模式,打开注释掉,加让这行代码生效
    //#define BLINKER_APCONFIG
    
    如果要使用smartconfig配网模式,打开注释掉,加让这行代码生效
    //#define BLINKER_ESP_SMARTCONFIG
    
    #include <Blinker.h>
    #include <ESP8266WebServer.h>
    
    char auth[] = "a7a437131912";
    char ssid[] = "panzujiMi10";
    char pswd[] = "moto1984";
    
    String version  = "1.0.3";
    
    //NodeMCU 继电器接D3,物理开关接D4
    #define LED_BUILTIN_LIGHT 0
    #define LED_BUILTIN_K2 2
    
    //Esp-01/01s,继电器接GPIO0,物理开关接GPIO2
    //#define LED_BUILTIN_LIGHT D3
    //#define LED_BUILTIN_K2 D4
    
    /***
     * 继电器高电平触发时,YYXBC_HIGH = 1,YYXBC_LOW  = 0
     * 继电器低电平触发时,YYXBC_HIGH = 0,YYXBC_LOW  = 1
     */
    const int YYXBC_HIGH = 0 ;
    const int YYXBC_LOW  = 1 ;
    
    /***
     * 物理开关点动模式1,自锁模式0
     */
    const int YYXBC_BUTTON_TYPE = 0;
    
    //http接口请求密码
    String httppswd = "123456";
    
    bool oDuerState = YYXBC_LOW;
    bool oMioState = YYXBC_LOW;
    bool oAligenieState = YYXBC_LOW;
    
    // 新建组件对象
    BlinkerButton Button1("btn-abc");
    
    //webserver for siri
    static ESP8266WebServer esp8266_server(80);
    
    //心跳回调
    void heartbeat()
    {
       BLINKER_LOG("heartbeat,state: ", digitalRead(LED_BUILTIN));
    
        //较正app的按钮状态
        if(YYXBC_HIGH == digitalRead(LED_BUILTIN_LIGHT) ){
            Button1.print("on");
        }else{
           Button1.print("off");
        }
    }
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //*******如果是手机app 有对设备进行操作就执行下面
    
    void button1_callback(const String & state)
    {
        BLINKER_LOG("button1_callback get button state: ", state);
    
        if (state == BLINKER_CMD_ON) {
            BLINKER_LOG("Toggle on!");
            Button1.print("on");
            digitalWrite(LED_BUILTIN_LIGHT, YYXBC_HIGH);
            oDuerState = YYXBC_HIGH;
            oMioState =YYXBC_HIGH;
            oAligenieState = YYXBC_HIGH;
        }
        else if (state == BLINKER_CMD_OFF) {
            BLINKER_LOG("Toggle off!");
            Button1.print("off");
            digitalWrite(LED_BUILTIN_LIGHT, YYXBC_LOW);
            oDuerState = YYXBC_LOW;
            oMioState = YYXBC_LOW;
            oAligenieState = YYXBC_LOW;
        }
        BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH ? "on" : "off");
        BlinkerDuerOS.report();
        BlinkerMIOT.powerState(oMioState == YYXBC_HIGH ? "on" : "off");
        BlinkerMIOT.print();
        BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH ? "on" : "off");
        BlinkerAliGenie.print(); 
    }
    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //*******如果小度 有对设备进行操作就执行下面
    void duerPowerState(const String & state)
    {
        BLINKER_LOG("duerPowerState need set power state: ", state);
    
        if (state == BLINKER_CMD_ON) {
           button1_callback(BLINKER_CMD_ON);
        }
        else if (state == BLINKER_CMD_OFF) {
          button1_callback(BLINKER_CMD_OFF);
        }
    }
    
    void duerQuery(int32_t queryCode)
    {
        BLINKER_LOG("DuerOS Query codes: ", queryCode);
    
        switch (queryCode)
        {
            case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :        
                BLINKER_LOG("DuerOS Query power state");
                BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH? "on" : "off");
                BlinkerDuerOS.print();
                break;
            case BLINKER_CMD_QUERY_TIME_NUMBER :
                BLINKER_LOG("DuerOS Query time");
                BlinkerDuerOS.time(millis());
                BlinkerDuerOS.print();
                break;
            default :
                BlinkerDuerOS.powerState(oDuerState == YYXBC_HIGH? "on" : "off");
                BlinkerDuerOS.print();
                break;
        }
    }
    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //*******如果小爱有对设备进行操作就执行下面
    void miotPowerState(const String & state)
    {
        BLINKER_LOG("miotPowerState need set power state: ", state);
    
        if (state == BLINKER_CMD_ON) {
           button1_callback(BLINKER_CMD_ON);
        }
        else if (state == BLINKER_CMD_OFF) {
          button1_callback(BLINKER_CMD_OFF);
        }
    }
    
    void miotQuery(int32_t queryCode)
    {
        BLINKER_LOG("MIOT Query codes: ", queryCode);
    
        switch (queryCode)
        {
          case BLINKER_CMD_QUERY_ALL_NUMBER :
              BLINKER_LOG("MIOT Query All");
              BlinkerMIOT.powerState(oMioState == YYXBC_HIGH? "on" : "off");
              BlinkerMIOT.print();
              break;
          case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
              BLINKER_LOG("MIOT Query Power State");
              BlinkerMIOT.powerState(oMioState ==YYXBC_HIGH ? "on" : "off");
              BlinkerMIOT.print();
              break;
          default :
              BlinkerMIOT.powerState(oMioState ==YYXBC_HIGH ? "on" : "off");
              BlinkerMIOT.print();
              break;
        }
    }
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //*******如果天猫精灵有对设备进行操作就执行下面
    void aligeniePowerState(const String & state)
    {
        BLINKER_LOG("aligeniePowerState need set power state: ", state);
    
        if (state == BLINKER_CMD_ON) {
           button1_callback(BLINKER_CMD_ON);
        }
        else if (state == BLINKER_CMD_OFF) {
          button1_callback(BLINKER_CMD_OFF);
        }
    }
    
    void aligenieQuery(int32_t queryCode)
    {
        BLINKER_LOG("AliGenie Query codes: ", queryCode);
    
        switch (queryCode)
        {
          case BLINKER_CMD_QUERY_ALL_NUMBER :
              BLINKER_LOG("AliGenie Query All");
              BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH? "on" : "off");
              BlinkerAliGenie.print();
              break;
          case BLINKER_CMD_QUERY_POWERSTATE_NUMBER :
              BLINKER_LOG("AliGenie Query Power State");
              BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH? "on" : "off");
              BlinkerAliGenie.print();
              break;
          default :
              BlinkerAliGenie.powerState(oAligenieState == YYXBC_HIGH ? "on" : "off");
              BlinkerAliGenie.print();
              break;
        }
    }
    
    void dataRead(const String & data){
      BLINKER_LOG("Blinker readString: ", data);
    
      Blinker.vibrate();
      
      uint32_t BlinkerTime = millis();
      
      Blinker.print("millis", BlinkerTime);
    
    }
    
    void setup() {
        // 初始化串口
        Serial.begin(115200);
    
        #if defined(BLINKER_PRINT)
            BLINKER_DEBUG.stream(BLINKER_PRINT);
        #endif
    
    //        //debug 命令
    //    BLINKER_DEBUG.stream(BLINKER_PRINT);
    //    BLINKER_DEBUG.debugAll();
    
        // 初始化有LED的IO
        pinMode(LED_BUILTIN_LIGHT, OUTPUT);
        digitalWrite(LED_BUILTIN_LIGHT, YYXBC_LOW);
        
        pinMode(LED_BUILTIN_K2, OUTPUT);
    //    digitalWrite(LED_BUILTIN_K2, LOW);
        
     #if (defined(BLINKER_APCONFIG)) || (defined(BLINKER_ESP_SMARTCONFIG))
         //启动配网模式用这行代码
        Blinker.begin(auth);
     #else 
        Blinker.begin(auth, ssid, pswd);
     #endif
     
        Blinker.attachData(dataRead);
    
        BlinkerDuerOS.attachPowerState(duerPowerState); //小度语音操作注册函数
        BlinkerDuerOS.attachQuery(duerQuery);
    
        BlinkerMIOT.attachPowerState(miotPowerState);//小爱语音操作注册函数
        BlinkerMIOT.attachQuery(miotQuery);
    
        BlinkerAliGenie.attachPowerState(aligeniePowerState);//天猫语音操作注册函数
        BlinkerAliGenie.attachQuery(aligenieQuery);     
      
        Button1.attach(button1_callback);
        //注册回调函数
        Blinker.attachHeartbeat(heartbeat);
        
        //启动webserver ,提供接口给siri用
        esp8266_server.on("/", handleRoot); 
        esp8266_server.on("/post", handleSetConfig);           
        esp8266_server.onNotFound(handleNotFound);  
        esp8266_server.begin();                  
          
        Serial.println("HTTP esp8266_server started");
    }
    
    void loop() {
    
        static int lastms = 0;
        if (millis()-lastms > 10000) {
          lastms = millis();
          Serial.printf(PSTR("Running (%s),state(%s),version %s for %d Free mem=%d\n"),
              WiFi.localIP().toString().c_str(),
              oAligenieState == YYXBC_HIGH  ? "YYXBC_HIGH" : "CLOES",
              version.c_str(), lastms/1000, ESP.getFreeHeap());
        }
        
        Blinker.run();//运行Blinker
        esp8266_server.handleClient();// 处理http服务器访问
        
        //检查物理开关状态
        if(YYXBC_BUTTON_TYPE == 1){
           btnHandler1();
        }else{
           btnHandler2();
        }
       
    }
    
    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //*******如果iOS的siri有对设备进行操作就执行下面
                                                                      
    void handleRoot() {   //处理网站根目录“/”的访问请求 
       String data = "<html>";
          data += "<head><title>设置</title></head>";
          data += "<body>";
          data +=" <p>ESP8266 智能开关,技术支持 微信:yyxbc2010</p><hr>";
          data +=" <p>SSID:"+ WiFi.SSID() + "</p><hr>";
          data +=" <p>PSW:"+ WiFi.psk() + "</p><hr>";
          data += "</body>";
          data += "</html>";  
          
        esp8266_server.send(200, "text/html; charset=utf-8", data);  
    } 
    
    
    void handleSetConfig() {   //处理来自siri的访问请求 
      if (esp8266_server.method() != HTTP_POST) {
        esp8266_server.send(405, "text/plain", "Method Not Allowed");
      } else {
    //    String message = "POST form was:\n";
        String btnName,btnState,btnPswd;
        for (uint8_t i = 0; i < esp8266_server.args(); i++) {
           String name = esp8266_server.argName(i);
           if(name == "btn") {
               btnName = esp8266_server.arg(i);
           }
           else if (name == "state"){
               btnState = esp8266_server.arg(i);
           } 
           else if (name == "passwd"){
               btnPswd = esp8266_server.arg(i);
           }     
        }
        if(btnPswd != httppswd){
          String message = "{\"errcode\":0,\"msg\":\"password error\"}";  
          esp8266_server.send(200, "text/html; charset=utf-8", message);  
          return;
        }
        if(btnName.length() >0 && btnState.length() >0) {
            //开关btn-abc
            if(btnName == "btn-1"){
              if(btnState == "on"){
                 button1_callback( BLINKER_CMD_ON);
              }else if (btnState == "off"){
                 button1_callback( BLINKER_CMD_OFF);
              }
            }
        
        }
        String message = "{\"errcode\":0,\"msg\":\" ok\"}";  
        esp8266_server.send(200, "text/html; charset=utf-8", message); 
      }
    }
    
    // 设置处理404情况的函数'handleNotFound'
    void handleNotFound(){   
    //  digitalWrite(led, 1);
      String message = "File Not Found\n\n";
      message += "URI: ";
      message += esp8266_server.uri();
      message += "\nMethod: ";
      message += (esp8266_server.method() == HTTP_GET) ? "GET" : "POST";
      message += "\nArguments: ";
      message += esp8266_server.args();
      message += "\n";
      for (uint8_t i = 0; i < esp8266_server.args(); i++) {
        message += " " + esp8266_server.argName(i) + ": " + esp8266_server.arg(i) + "\n";
      }
      esp8266_server.send(404, "text/plain", message);
    
    }
    
    //点动模式按钮,监听按钮状态,执行相应处理
    void btnHandler1()
    {
      static bool oButtonState = false;
      int state1 =  digitalRead(LED_BUILTIN_K2); //按钮状态
      int state2 =  digitalRead(LED_BUILTIN_LIGHT); //灯的状态
      if(state1 == HIGH )
      {
        if(oButtonState ){
          if(state2 == YYXBC_HIGH )
          { 
            button1_callback(BLINKER_CMD_OFF);
            Serial.println("按钮对灯已执行关闭");
          }else{
            button1_callback(BLINKER_CMD_ON);
            Serial.println("按钮对灯已执行打开");
          }
          oButtonState = false;
        }
      }else{
        oButtonState = true;
      }
    }
    
    
    
    //自锁模式按钮,监听按钮状态,执行相应处理
    void btnHandler2()
    {
     static bool is_btn = false;//按钮的标志位,用来逻辑处理对比,判断按钮有没有改变状态
      bool is = digitalRead(LED_BUILTIN_K2);   //按钮状态
      if ( is != is_btn)
      {
        bool is_led = digitalRead(LED_BUILTIN_LIGHT);
        digitalWrite(LED_BUILTIN_LIGHT, !is_led);
        if (is_led == YYXBC_HIGH)
        {
          button1_callback(BLINKER_CMD_OFF);
          Serial.println("按钮对灯已执行关闭");
        }
        else
        {
          button1_callback(BLINKER_CMD_ON);
          Serial.println("按钮对灯已执行打开");
        }
        is_btn = digitalRead(LED_BUILTIN_K2);  //更新按钮状态
      }
    }
    

    资源下载

    本文章相关资源链接:https://pan.baidu.com/s/1LU4XkcYnH83GNsA61ywFqw 提取码:681i 复制这段内容后打开百度网盘手机App,操作更方便哦

    QQ技术讨论群

    在这里插入图片描述

    关注阳阳学编程抖音号

    在这里插入图片描述

    展开全文
  • 开关问题

    2017-10-27 03:03:14
    有N个相同的开关,每个开关都与某些开关有着联系,每当你打开或者关闭某个开关的时候,其他的与此开关相关联的开关也会相应地发生变化,即这些相联系的开关的状态如果原来为开就变为关,如果为关就变为开。...
  • 特性开关开关策略

    千次阅读 2018-03-10 17:56:40
    特性开关有时只是简简单单的通过配置true or false来决定开或关,而有时要根据某种策略来决定开或关。对于开关策略,特性开关框架一般会提供不少默认的策略给我们用,但有时我们也会遇到框架没有提供而我们又想要的...

    特性开关有时只是简简单单的通过配置true or false来决定开或关,而有时要根据某种策略来决定开或关。对于开关策略,特性开关框架一般会提供不少默认的策略给我们用,但有时我们也会遇到框架没有提供而我们又想要的,这时则需要我们自定义。掌握特性开关框架默认提供的开关策略及如何自定义开关策略都很重要。下面我以FF4J这个框架为例,介绍它自带提供的策略及如何扩展实现自己的策略。

    FF4J默认提供的策略


    上面截图列出了FF4J提供的所有默认策略,有基于表达式的策略,有基于时间的策略,有白名单黑名单策略,有权重策略等,下面我们看看默认策略怎么用。

    默认策略示例
     
    <feature uid="laolaxin" enable="true">
        <flipstrategy class="org.ff4j.strategy.time.ReleaseDateFlipStrategy">
            <param name="releaseDate" value="2018-02-26-12:15"/>
        </flipstrategy>
        <custom-properties>
            <property name="return" value="活动未开始,尽请期待"/>
        </custom-properties>
    </feature>
     
    @RequestMapping("/activity/laolaxin")
    @Feature(name="laolaxin")
    public String laolaxin(){
        //TODO laolaxin
        return "完成活动!!";
    }

    这里我们使用了ReleaseDateFlipStrategy这个策略,其实自定义策略的用法也是一样的,不同的姿势 class 字段配的值不一样。下面我们看看如何自定义策略。

    如何自定义策略

    FF4J使用了策略模式实现开关策略,具备良好的扩展性,所以我们扩展自定义策略也是蛮简单。要自定义自己的策略,需要实现 FlipStrategy 接口。

    而FF4J为我们提供了一个抽象类 AbstractFlipStrategy

    所有我们其实只需要继承AbstractFlipStrategy,然后实现evaluate方法,必要时也可以override init和 getInitParams 方法。下面我会通过一个例子来细说。

    自定义策略示例

    《xxx》app后台那边有这样一种场景,APP新版本对某一旧接口做了较大的逻辑修改,但新逻辑不能被旧app访问到,旧app要求还是访问旧逻辑,为了实现这个,开发会在代码中引入if…else…分支,通过版本号来做判断。这一场景也可以用特性开关来做,不过需要自定义策略,下面我们看看这个策略怎么写.

    自定义策略类

     
    /**
     * 自定义版本策略,对新版本开,对老版本关,新版本的版本值可配置
     */
    public class VersionStrategy extends AbstractFlipStrategy {
        private String version;
        public static final String VERSION = "version";
        private List<Integer> versionList = new ArrayList<>();
        public void init(String featureName, Map<String, String> initParams) {
            super.init(featureName, initParams);
            assertRequiredParameter(VERSION);
            if (initParams != null && initParams.containsKey(VERSION)) {
                this.version = initParams.get(VERSION);
                String[] versionStrArr = version.split("\\.");
                for (String item : versionStrArr) {
                    versionList.add(Integer.parseInt(item));
                }
            }
        }
        @Override
        public boolean evaluate(String s, FeatureStore featureStore, FlippingExecutionContext flippingExecutionContext) {
            return isNewVersion(flippingExecutionContext);
        }
        /**
         * 判断是否是新版本
         * 版本格式要求:数字.数字.数字…譬如 2.12.14
         * @param flippingExecutionContext 上下文
         * @return boolean
         */
        protected boolean isNewVersion(FlippingExecutionContext flippingExecutionContext) {
            String clientVersion = flippingExecutionContext.getValue(VERSION, false) == null ? null : flippingExecutionContext.getString(VERSION);
            if (clientVersion == null || clientVersion.trim().length() == 0) return false;
            String clientVersionArr[] = clientVersion.split("\\.");
            if (versionList.size() != clientVersionArr.length) return false;
            for (int i = 0; i < versionList.size(); i++) {
                int iversion = versionList.get(i);
                int iClientVersion = Integer.parseInt(clientVersionArr[i]);
                if (iClientVersion < iversion) return false;
            }
            return true;
        }
    }

    这里我们可以看到我们自定义了一个VersionStrategy策略类,继承了AbstractFlipStrategy ,重写了init方法,实现了evaluate方法。init 方法是干嘛的?它是初始化开关配置数据的,如上所示我们将配置的version值做了初始化。evaluate方法是做什么的?它是用来判断开关状态的,如上所示我们通过比较配置的版本号与客户端传过来的版本来判断是否是新版本,来决定开关是开还是关。下面我们看看自定义的这个策略怎么用。

    使用自定义策略

     
    <feature uid="oldAndNew" enable="true">
        <flipstrategy class="com.ppmoney.ppmon.feature.ff4j.test.VersionStrategy">
            <param name="version" value="2.1.9"/>
        </flipstrategy>
    </feature>
     
    @Autowired
    private FF4j ff4j;
    @RequestMapping("/oldAndNew")
    public String oldAndNew(HttpServletRequest request) {
        FlippingExecutionContext executionContext = new FlippingExecutionContext();
        executionContext.addValue("version", request.getHeader("version"));
        if (ff4j.check("oldAndNew", executionContext)) {
            //重构后的新逻辑
            return 1 + 2 + "";
        } else {
            //上个版本的旧逻辑
            return 1 + 1 + "";
        }
    }

    如上我们在配置中指定了 VersionStrategy,并且配置了version值 “2.1.9", 业务代码中我们将请求头里的版本值赋给 FlippingExecutionContext 对象,并通过ff4j的check方法判断开关状态,事实上 check 方法最终会调用到 evaluate 方法来决定,请看下面源码。

    到此我想大家都知道怎么自定义和使用开关策略了。

    展开全文
  • 线性开关电源

    万次阅读 2020-04-04 10:11:02
    线性开关电源
  • 开关】如何选择矩阵开关

    千次阅读 2019-08-09 09:57:34
    通俗来讲,矩阵开关就是以矩阵形式排列的开关,可以实现测试过程中的任一点之前的互联。 矩阵开关的成本主要取决于矩阵开关中的节点数量,节点数量等于X轴尺寸*Y轴尺寸。 另外,矩阵的尺寸除了影响开关卡的成本...
  • switch开关

    千次阅读 2018-11-27 12:14:45
    新写的一个switch开关 之前在网上看到的一些switch开关,只能改变大块的背景颜色,并不能改变小圆点的背景颜色. 所以写一个可以改变两个地方背景颜色switch开关. 插入链接与图片 这个是关闭状态 这个是开启状态 带...
  • MOS管开关电路

    万次阅读 2018-05-10 11:02:16
    MOS管开关电路是利用MOS管栅极(g)控制MOS管源极(s)和漏极(d)通断的原理构造的电路。因MOS管分为N沟道与P沟道,所以开关电路也主要分为两种。一般情况下普遍用于高端驱动的MOS,导通时需要是栅极电压大于源极...
  • 1. 显示开关文字 表格中使用开关组件,官方例子的文字描述是显示在开关组件的后面,如何显示在组件上呢?废话不多说直接上教程。 html <el-table-column label="是否显示"> <template v-slot="scope"> ...
  • Android SwitchButton开关

    千次下载 热门讨论 2015-07-24 23:23:45
    Android SwitchButton开关。在很多应用上已经广泛应用了,用来设置开关声音、提示等等之类,这里提供一份示例程序。
  • PMOS和NMOS在开关应用中高侧和低侧驱动的对比

    万次阅读 多人点赞 2016-07-14 13:40:26
    一说到开关,我们脑海中首先浮现的就是各式各样的机械开关,常见的有自锁开关、拨码开关、船型开关等等。区别于这类常见的机械开关,我们在电子电路中常用的还有各类半导体开关,例如三极管开关、使用三极管级联的...
  • 改造家里的开关成为智能开关,保留原有开关控制,零火版(二) 更新说明 本文章在“改造家里的开关成为智能开关,保留原有开关控制,零火版(一)”版本的基本上添加的新功能。 1、添加了433/315 射频遥控功能,可以...
  • 开关功能 长按主开关三秒,蓝色指示灯闪烁一次后松手,按下随意贴任意键即可配对成功。 清码 长按主开关10秒,蓝色指示灯闪烁4次后松手,即可清除配对。 只开功能 长按主开关5秒,蓝色指示灯闪烁两次后松手,按下...
  • element Switch开关 状态开关实现

    千次阅读 2020-05-05 22:34:36
    开关的实现 总: <el-table :data="userlist" border stripe> <el-table-column type="index" label="#"></el-table-column> <el-table-column prop="username" label="姓名"></e...
  • 包含了我们平时常用的拨码开关,按键开关,拨动开关,总共117种封装及精美3D模型。其中包含插件直插,插件侧插,贴片。完全能满足日常设计使用。每个封装都搭配了精美的3D模型哦。 下载地址 ...
  • 三极管的开关功能

    万次阅读 2018-08-14 10:33:27
    很好的理解三极管的开关功能,下面以8个实例图片,生动的阐述三极管作为开关的功能。期待大家回复讨论分析各个电路。1、低边开关 2、高边开关 3、基极电阻 4、非门电路 5、与门 6、或门 7、H桥 ...
  • 如何将接近开关作为限位开关连接? 如何使用光耦合器将接近开关连接为限位开关开关有两种类型-PNP(3002PA,,…)和NPN(3002NA,3002NB,…) 开关也分为NC –常闭(3002PB,3002NB,…)和NO –常开(3002PA...
  • 今天给大家介绍两种不同的触摸开关电路,不同的芯片可以设计不同的电路功能,也能设计相同的电路功能。下面两种电路一个是使用了4013芯片组成的触摸开关电路,另一个是使用了4011芯片组成的延时触摸开关电路, 一...
  • 今天先和大家分享一下灯光控制的智能化,打开米家APP,首页点击+进入设备搜索页,我们可以看到开关有很多种,具体如何选择呢?如何组合使用呢?如何预留线?如何改造我们可能不知道如何下手,下面听我慢慢道来。...
  • java 开关

    千次阅读 2016-01-08 19:48:51
    有时候需要某些代码执行或者不执行或者特殊情况下执行,就可以用开关来控制;开关值可以放在properties文件中,也可放在表中,动态获取开关值;下面是放于config表和配置文件同时控制 //开关方法 private ...
  • 【自锁开关】【非自锁开关】区分

    千次阅读 2019-07-11 09:53:29
    自锁开关一般是指开关自带机械锁定功能,按下去,松手后按钮是不会完全跳起来的,处于锁定状态,此时用手再按一次,机械结构解锁按钮就会自动跳起来,它就叫自锁开关。早期的直接完全断电的电视机、显示器就是使用的...
  • 开关电源学习笔记0 --- 初识开关电源

    千次阅读 多人点赞 2019-03-06 17:23:13
    本笔记将分为两部分,理论计算部分和实际应用部分。理论部分将讲述各种电路原理以及其中各元件的参数计算,实际应用部分将讲述电路...开关电源:顾名思义就是通过控制高频率的“开关”来输出特定电压的电源 这个...
  • 6脚自锁开关

    万次阅读 多人点赞 2018-04-22 18:46:03
    1. 自锁开关6脚六脚开关(六脚自锁开关)也就是我们说的双刀双掷开关,引脚共2排,每排3个引脚,中间一根是公共端,对应他左右2个脚一个常开一个常闭,另外一排和这个一样,常开对常开,公共点对公共点,常闭对常闭...
  • 三极管开关电路

    万次阅读 2018-10-26 21:42:56
    三极管除了可以当做交流信号放大器之外,也可以做为开关使用。严格说起来,三极管与一般的机械接点式开关在动作上并不完全相同,但是它却具有一些机械式开关所没有的特点。 图1所示,即为三极管电子开关的基本电路...
  • 动态修改switch开关值 1.定义一个switch开关,默认为开(checked=”checked”) &amp;amp;amp;lt;div class=&amp;amp;quot;layui-form-item&amp;amp;quot;&amp;amp;amp;gt; &amp;amp;...
  • 开关频率

    千次阅读 2016-07-31 11:50:16
    开关频率对控制性能的影响 ... 理想的控制效果只有在开关频率无限高的情况下才能实现, 此处理想的控制效果一般指好的DC稳态调节性能(即没有稳态误差、对噪声不敏感)、无限快的动态响应性能,没有超

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 110,923
精华内容 44,369
关键字:

开关