概述

远程无线开关是智能家居和物联网中重要的执行设备,它通过接入互联网来实现手机或WEB端、weixin小程序的远程开关控制,一般通过WIFI、GPRS、4G、NBIOT等来接入网络,网上卖的最多的应该WIFI版的。但作为创客的我们来说,买一个成熟的无线开关对我们来说是没什么乐趣的,我们要充分发挥创客的创造性和动手能力,去创造一款与众不同,私人定制版的无线开关。

今天要和大家分享的就是利用Arduino这个全球最大的开源硬件平台+国内使用最为广泛的STM32F系列微控制器,再加上SIM868 GPRS 2G无线通用模块,充分利用开源的代码库,再加入一些自己的编写的代码,1天就完成了这个产品的样机功能。实现了通过GPRS网络直接连到云端服务器,加了一个简单的数据库,就能实现用WEB端或weixin小程序来远程控制2路开关了,并且还具备GPS定位和LBS室内定位功能。

材料准备

要创造这个产品,你需要以下模块

STM32103CBT6双路继电器主板 1块

SIM868 2G通讯模组 1块 (GPRS通讯、内置GPS,可室内LBS定位,板载陶瓷天线。)

外壳 1个 (这个从网上购买的公壳,可以自己打印一个标签,印上自己的LOGO,给它取一个响亮的名字)

这个开源项目所需的所有部件、材料,都放在了我们的创客taobao小店,搜索“兑悦物联小店”,可以找到它们了。也可以加入创客小伙伴们的家,大家一起交流,学习。我们的学习交流企鹅群:419411339。

实现的产品性能:

控制方式:WEB/微信小程序

通讯方式:GSM

定位功能:GPS/LBS

工作电压:DC24V/DC5V

电源输入接口:

接线端子DC24V

microUSB DC5V

负载电压:0~250VAC/0~30VDC

负载电流:10A MAX

控制路数:2路

接口模式:常开/常闭

产品尺寸:85X50X32mm

Arduino 编程

关于Arduino IDE编程平台的使用,网上用很多教程,还没用入门的童鞋可自行去学习。这里需要特别说明的一点是,Arduino IDE原生并不支持STM32系列的单片机,需要单独下载安装一个第三方的库来支持。关于怎么下载安装这个库,我们在另外的文章中来详细说明。

下面先无私的分享这个无线开关自己实现的那部分完整代码:

/**************************************************************** This sketch connects to a website and downloads a page.* ** TinyGSM Getting Started guide:*   https://github.com/ynkady/TinyGSM***************************************************************/
/*使用注意:本程序使用SIM868 多功能GSM+GPS模块,使用前需注意以下事项:1、此模块适用于兑悦物联小店的GSMandGPS_MDV1.2及以上版本的模块,其它SIM868模块需要对IO进行修改
https://item.taobao.com/item.htm?spm=a1z10.1-c-s.w4004-16679354584.19.5a9c5712xGAkkw&id=5671002668682、本测试程序适用于Arduino UNO、Mega2560官方版本及其它国内各种改进版本,UNO板也可以参考本店的:
https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-16618966406.83.339d69c4yPsWMK&id=5581788859963、使用本测度程序前需下载TinyGSM库,但原来官方的库里不支持基站定位,我们对这个库进行了更改,并上传到Githup,可从以下地址下载,并替换原来的库文件https://github.com/ynkady/TinyGSMWindows的Arduino库文件地址:C:UserskadyDocumentsArduinolibraries4、GSM模块硬件连接4V---->外部电源供电+(3.4~4.2V,推荐4.0V)GND--->外部电源-GND--->Arduino UNO GNDPWRKEY-----> D4RX---------> D3TX---------> D2   特别注意:由于GSM模块要搜索移动网络时瞬间电流非常大,可能达到2A,所以GSM模块不能使用ARDUINO开发板上的电源供电,需要使用外部稳定的电源供电,或使用容量大于1500mAh以上的锂电池供电GSM模块共电模块可以从我们的小店找到:https://item.taobao.com/item.htm?spm=a1z10.3-c-s.w4002-16618966406.41.339d69c4yPsWMK&id=554761942043*/
// Select your modem:
#define TINY_GSM_MODEM_SIM800
// #define TINY_GSM_MODEM_SIM900
// #define TINY_GSM_MODEM_A6
// #define TINY_GSM_MODEM_A7
// #define TINY_GSM_MODEM_M590
// #define TINY_GSM_MODEM_ESP8266
#include <TinyGsmClient.h>
#include <Arduino_JSON.h>
#include <RTClock.h>
#include "User_Clock.h"// Your GPRS credentials
// Leave empty, if missing user or pass
//普通GSM 2G网络接入点APN为CMNET
//物联网专用接入点APN为CMIOTconst char apn[]  = "CMIOT";const char user[] = "";const char pass[] = "";//Selset Dev Board Type
#define UNO        1
#define MEGA2560   2
#define BOARD_TYPE  STM32// Use Hardware Serial on Mega, Leonardo, Micro
#if BOARD_TYPE == MEGA2560
#define SerialAT Serial3
#define GPRS_PWRKEY_PIN  4
#elif BOARD_TYPE == UNO
#define U_RX   2
#define U_TX   3
#define GPRS_PWRKEY_PIN  4
#include "SoftwareSerial.h"
SoftwareSerial SerialAT(U_RX, U_TX);
#elif BOARD_TYPE == STM32
#define SerialAT Serial2
#define GPRS_PWRKEY_PIN  PA15
#define WLBG_PWR_PIN     PA5
#define WLBG_PWR_ON       digitalWrite(WLBG_PWR_PIN, HIGH)
#define WLBG_PWR_OFF      digitalWrite(WLBG_PWR_PIN, LOW)
#define RELAY_OUT1_PIN PA3
#define RELAY_OUT2_PIN PA4
#define RELAY_OUT1_ON       digitalWrite(RELAY_OUT1_PIN, LOW)
#define RELAY_OUT1_OFF      digitalWrite(RELAY_OUT1_PIN, HIGH)
#define RELAY_OUT2_ON       digitalWrite(RELAY_OUT2_PIN, LOW)
#define RELAY_OUT2_OFF      digitalWrite(RELAY_OUT2_PIN, HIGH)
#else
#define U_RX   2
#define U_TX   3
#define GPRS_PWRKEY_PIN  4
#include "SoftwareSerial.h"
SoftwareSerial SerialAT(U_RX, U_TX);
#endif//根据硬件上的连接来更改
#define GPRS_PWRKEY_HI digitalWrite(GPRS_PWRKEY_PIN, HIGH)
#define GPRS_PWRKEY_LO digitalWrite(GPRS_PWRKEY_PIN, LOW)#define MAX_OUT_NUM  2#define RTC_FUN    1void SIM800_PWR_CON(void)
{GPRS_PWRKEY_LO;delay(1500);GPRS_PWRKEY_HI;
}
// or Software Serial on Uno, Nano
//#include <SoftwareSerial.h>
//SoftwareSerial SerialAT(2, 3); // RX, TXTinyGsm modem(SerialAT);
TinyGsmClient client(modem);#if RTC_FUN==1
RTClock InRtc (RTCSEL_LSE);  // initialise RTC
#endifbool SendDataToSever(String string);
void RTC_Interrupt(void);//以下为服务器地址,需要根据实际要连接的服务器地址或域名填写,注意:必须是公网址哦!
//const char server[] = "xxx.xxx.xxx.xxx";
//int port = 8008;
const char server[] = "shhoo.cn";
int port = 8000;bool GSM_Search_Net_Flag;
bool LBS_Connect_flag;
bool GSM_Enter_Net_flag;
bool Sever_Connect_flag;
unsigned int TimeSec = 0;          //运行超时计数
bool SendHeatBeatFlag=false;
unsigned int GPRSV=0;
unsigned int Try_Connect_Sever_Num=0;
char cmd16array[16]={0};
const char *cmdarray=cmd16array;
char Toggle = 0;  //状态灯闪灭位翻转
unsigned int ReviceServerTimeoutNum=0;const unsigned int OUT_NUM_LIST[MAX_OUT_NUM]={RELAY_OUT1_PIN,RELAY_OUT2_PIN};#if RTC_FUN==1
UTCTimeStruct RtcTime = {2018, 0, 5, 0, 16, 01, 23};
#endifstatic const unsigned char SoftWareVer[]="V1.0.1";void setup() {// Set console baud rateafio_cfg_debug_ports(AFIO_DEBUG_SW_ONLY);pinMode(GPRS_PWRKEY_PIN, OUTPUT);pinMode(WLBG_PWR_PIN, OUTPUT);pinMode(RELAY_OUT1_PIN, OUTPUT);pinMode(RELAY_OUT2_PIN, OUTPUT);WLBG_PWR_ON;RELAY_OUT1_OFF;RELAY_OUT2_OFF;/*RELAY_OUT1_ON;delay(500);RELAY_OUT1_OFF;RELAY_OUT2_ON;delay(500);RELAY_OUT2_OFF;*/GPRS_PWRKEY_HI;Serial.begin(115200);SerialAT.begin(9600);delay(1000);SIM800_PWR_CON();// Set GSM module baud ratedelay(3000);// Restart takes quite some time// To skip it, call init() instead of restart()Serial.println(F("Initializing modem..."));modem.restart();//打开GPS电源modem.GPS_PWR_CONTROL(ON);delay(2000);modem.GPS_Set_parameter();delay(1000);LBS_Connect_flag=false;GSM_Search_Net_Flag=false;GSM_Enter_Net_flag=false;//Unlock your SIM card with a PIN//modem.simUnlock("1234");//RELAY_OUT1_ON;//RELAY_OUT2_ON;Sever_Connect_flag=false;//初始化定时器2Timer2.setChannel1Mode(TIMER_OUTPUTCOMPARE);Timer2.setPeriod(1000000); // in microseconds,1STimer2.setCompare1(1);   // overflow might be smallTimer2.attachCompare1Interrupt(Time2_Handler);#if RTC_FUN==1//初始化RTC闹钟noInterrupts();time_t Alarm_Time = 0;Alarm_Time = InRtc.getTime();InRtc.createAlarm(RTC_Interrupt, Alarm_Time+60);interrupts();#endif
}static String IMEI;static  String SIMCCID;static int CSQ=0;void loop() {// Get GPRS Moudle VoltageGPRSV=modem.getBattVoltage(); Serial.print("GPRS Moudle Vol:");Serial.println(GPRSV);TimeSendHeatBeat();if(GSM_Search_Net_Flag==false){Serial.print(F("Waiting for network..."));if (!modem.waitForNetwork()) {Serial.println(" fail");delay(10000);GSM_Search_Net_Flag=false;return;}GSM_Search_Net_Flag=true;Serial.println("Search GSM Network OK");}if(GSM_Enter_Net_flag==false&&GSM_Search_Net_Flag==true){Serial.print(F("Connecting to "));Serial.print(apn);if (!modem.gprsConnect(apn, user, pass)) {Serial.println(" fail");delay(10000);GSM_Enter_Net_flag=false;return;}Serial.println(" OK");GSM_Enter_Net_flag=true;//send SMS//modem.sendSMS("+8613577182976", "this is SIM868");}//连接基站定位服务连接基站定位服务if(GSM_Search_Net_Flag==true && LBS_Connect_flag==false){if (modem.LBS_Connect()==true){LBS_Connect_flag=true;}else{Serial.println("LBS Connect Fail!");LBS_Connect_flag=false;}   }//String GPSData =modem.GPS_Get_Data();//Serial.println("GPS Data:" + GPSData + "rn");  //SerialAT.println("AT+CGNSINFrn");// delay(2000);if(Sever_Connect_flag==false){//连接基站定位服务连接基站定位服务Serial.print(F("Connecting to Server:"));Serial.print(server);if (!client.connect(server, port)) {Serial.println(" fail");delay(10000);Sever_Connect_flag=false;Try_Connect_Sever_Num++;//连接10次都连接不上服务器,重新入网if(Try_Connect_Sever_Num>10){Try_Connect_Sever_Num=0;GSM_Search_Net_Flag=false;GSM_Enter_Net_flag=false;modem.gprsDisconnect();LBS_Connect_flag=false;}return;}else{Serial.println(" OK!");Try_Connect_Sever_Num=0;Sever_Connect_flag=true;   //发送连接信息组服务器CSQ = 0;CSQ = modem.getSignalQuality();Serial.println("nGSM Enter network OKr");char string[25];sprintf(string, "CSQ:%dr", CSQ);Serial.println(string);IMEI = modem.getIMEI();Serial.println("IMEI:" + IMEI);//Serial.print(CSQ,DEC);Serial.println("r");SIMCCID = modem.getSimCCID();Serial.println("SIMCCID:" + SIMCCID);String LOCData; if(LBS_Connect_flag==true){Serial.println("LBS Connect OK!");//0,102.654510,25.064799,550,17/09/14,11:20:30LOCData= modem.Get_LOCData();Serial.println("LBSData:" + LOCData + "rn");   LBS_Connect_flag=false;}   JSONVar myObject;myObject["CSQ"] = CSQ;myObject["IMEI"] =IMEI;myObject["CCID"] =SIMCCID;myObject["LBS"]=LOCData;    Serial.print("myObject.keys() = ");Serial.println(myObject.keys());// JSON.stringify(myVar) can be used to convert the json var to a StringString jsonString = JSON.stringify(myObject);Serial.print("JSON.stringify(myObject) = ");Serial.println(jsonString);SendDataToSever(jsonString);IMEI.trim();SIMCCID.trim();LOCData.trim();delay(1000);}   }     // Make a HTTP GET request://AT+OUT:1=ONunsigned long timeout = millis();while (client.connected() && millis() - timeout < 2000L) {// Print available dataif (client.available()) {String res = client.readStringUntil('n');if(res.equals("")==false){JSONVar cmdObject = JSON.parse(res);// JSON.typeof(jsonVar) can be used to get the type of the varif (JSON.typeof(cmdObject) == "undefined") {Serial.println("Parsing input failed!");return;}Serial.print("JSON.typeof(myObject) = ");Serial.println(JSON.typeof(cmdObject)); // prints: object// myObject.hasOwnProperty(key) checks if the object contains an entry for keyif (cmdObject.hasOwnProperty("time")) {ReviceServerTimeoutNum=0;Serial.print("cmdObject["time"] = ");Serial.println(cmdObject["time"]);//20200306183358const char *DataArray=(const char*)cmdObject["time"];//String DataString = JSON.stringify(cmdObject["time"]);#if RTC_FUN==1RtcTime.year  = (DataArray[0] - '0') * 1000 + (DataArray[1] - '0')  *100 + (DataArray[2] - '0') * 10 + (DataArray[3] - '0');RtcTime.month = (DataArray[4] - '0') * 10 + (DataArray[5] - '0');RtcTime.day   = (DataArray[6] - '0') * 10 + (DataArray[7] - '0');RtcTime.hour    = (DataArray[8] - '0') * 10 + (DataArray[9] - '0');RtcTime.minutes = (DataArray[10] - '0') * 10 + (DataArray[11] - '0');RtcTime.seconds = (DataArray[12] - '0') * 10 + (DataArray[13] - '0');UTCTime CurrentSec = osal_ConvertUTCSecs(&RtcTime);InRtc.setTime(CurrentSec);noInterrupts();time_t Alarm_Time = 0;Alarm_Time = InRtc.getTime();InRtc.createAlarm(RTC_Interrupt, Alarm_Time+60);interrupts();#endif}if (cmdObject.hasOwnProperty("DO16Sta")) {//Serial.print("DO16Sta["DO16Sta"] = ");//char cmd=cmdObject["DO16Sta"];//String CmdString = JSON.stringify(cmdObject["DO16Sta"]);//Serial.println(CmdString);int i=0;//const char cmdarray[16]={0};cmdarray=(const char*)cmdObject["DO16Sta"];//CmdString.toCharArray(cmdarray, 16);for(i=0;i<16;i++){if(cmdarray[i]==0x31){//Serial.println(i+"channel Open");switch(i){case 0:RELAY_OUT1_ON;break;case 1:RELAY_OUT2_ON;break;default:break;}}else if(cmdarray[i]==0x30){//Serial.println(i+"channel close");switch(i){case 0:RELAY_OUT1_OFF;break;case 1:RELAY_OUT2_OFF;break;default:break;}}else{Serial.println("error!");//Serial.println(cmdarray[i]);}delay(10);}memset(cmd16array,'0',sizeof(cmd16array));//读输出IO的状态for(int i=0;i<MAX_OUT_NUM;i++){if(digitalRead(OUT_NUM_LIST[i])==LOW){cmd16array[i]='1';}else if(digitalRead(OUT_NUM_LIST[i])==HIGH){cmd16array[i]='0';}}//发送群控指令应答JSONVar AckObject;IMEI = modem.getIMEI();AckObject["IMEI"] = IMEI;String DO16Sta(cmd16array);AckObject["DO16Sta"] =DO16Sta;Serial.println(IMEI);Serial.println(DO16Sta);Serial.print("AckObject.keys() = ");Serial.println(AckObject.keys());// JSON.stringify(myVar) can be used to convert the json var to a StringString jsonString1 = JSON.stringify(AckObject);Serial.print("JSON.stringify(myObject) = ");Serial.println(jsonString1);// client.print(jsonString1);SendDataToSever(jsonString1);}if(cmdObject.hasOwnProperty("DONum")){int ChNum=(int)cmdObject["DONum"];if(cmdObject.hasOwnProperty("sta")){int sta=(int)cmdObject["sta"];if(sta==1){switch(ChNum){case 255:RELAY_OUT1_ON;RELAY_OUT2_ON;break;case 1:RELAY_OUT1_ON;break;case 2:RELAY_OUT2_ON;break;default:break;}}else if(sta==0){switch(ChNum){case 255:RELAY_OUT1_OFF;RELAY_OUT2_OFF;break;case 1:RELAY_OUT1_OFF;break;case 2:RELAY_OUT2_OFF;break;default:break;}} //发送单控指令应答JSONVar AckObject;IMEI = modem.getIMEI();AckObject["IMEI"] = IMEI;AckObject["DONum"] =ChNum;AckObject["sta"] = sta;Serial.print("AckObject.keys() = ");Serial.println(AckObject.keys());// JSON.stringify(myVar) can be used to convert the json var to a StringString jsonString1 = JSON.stringify(AckObject);Serial.print("JSON.stringify(myObject) = ");Serial.println(jsonString1);//client.print(jsonString1);SendDataToSever(jsonString1);} } }res.trim();  }//timeout = millis();}if(!client.connected()){if(Sever_Connect_flag==true){Sever_Connect_flag=false;client.stop();}}}
/**brief   : 定时器发送心跳包*para    : 无*return  : 无
*/
bool TimeSendHeatBeat()
{//定时发送心跳包if(SendHeatBeatFlag==true && Sever_Connect_flag==true){SendHeatBeatFlag=false;JSONVar AckObject;memset(cmd16array,0,sizeof(cmd16array));IMEI = modem.getIMEI();Serial.println("IMEI:" + IMEI);AckObject["IMEI"] = IMEI;AckObject["DO16Sta"] =cmd16array;Serial.print("AckObject.keys() = ");Serial.println(AckObject.keys());// JSON.stringify(myVar) can be used to convert the json var to a StringString jsonString1 = JSON.stringify(AckObject);Serial.print("JSON.stringify(myObject) = ");Serial.println(jsonString1);//client.print(jsonString1);if(client.connected()){SendDataToSever(jsonString1);}Serial.println("Send Heatbeat!");ReviceServerTimeoutNum++;Serial.print("ReviceServerTimeoutNum:");Serial.println(ReviceServerTimeoutNum);//如果接收服务器数据次数超时if(ReviceServerTimeoutNum>=10){ReviceServerTimeoutNum=0;if(Sever_Connect_flag==true){Sever_Connect_flag=false;client.stop();}}}
}
bool SendDataToSever(String string)
{char *sendBuf;int datalength=string.length()+1;sendBuf=(char *)malloc(datalength);string.toCharArray(sendBuf,datalength);client.write((unsigned char*)sendBuf,datalength);free(sendBuf);return true;
}
/**brief   : 定时器2中断函数*para    : 无*return  : 无
*/
void Time2_Handler(void)
{//Toggle ^= 1;//digitalWrite(RELAY_OUT1_PIN, Toggle); //状态灯闪烁TimeSec++;//如果运行超时,复位if(TimeSec >= 30){TimeSec = 0;SendHeatBeatFlag=true;}
}#if RTC_FUN==1
void RTC_Interrupt(void)
{// rtc_detach_interrupt(RTC_ALARM_SPECIFIC_INTERRUPT);Serial.println("RTC alarm interrupt");
}
#endif

以上程序实现了如下功能:

  1. GPRS模块的网络搜索、入网、连接服务器、断网自动重连、维持心跳包等;
  2. GPS定位、LBS室内定位,得到实时的经纬度数据;
  3. 用json实现了与服务器的数据交互,通过解析服务器端的指令来控制2路继电器开关;
  4. 具用RTC实时时钟功能,可远程设置时间和闹钟。

必须的外部库文件

  1. TinyGSM库,但原来官方的库里不支持基站定位,我们对这个库进行了更改,并上传到Githup,可从以下地址下载,并替换原来的库文件 https://github.com/ynkady/TinyGSM
  2. Arduino_JSON库
  3. Time时钟库
  4. 开发板选项里要安装如下图所示的ARM Cortex-M3内核库

成果展示

arduino 可以用c_lt;开源项目gt;Arduino+STM32+SIM868 用一天创造一款可以定位的GPRS无线开关...相关推荐

  1. python3语音识别模块_『开源项目』基于STM32的智能垃圾桶之语音识别

    大家好,我是『芯知识学堂』的SingleYork,前面给大家简单介绍了『开源项目』基于STM32的智能垃圾桶之成员简介,相信有很多小伙伴都已经忍不住跃跃欲试了,别着急,从这一篇开始,笔者将会带领大家一 ...

  2. stm32语音识别文字显示_『开源项目』基于STM32的智能垃圾桶之语音识别

    大家好,我是『芯知识学堂』的SingleYork,前面给大家简单介绍了『开源项目』基于STM32的智能垃圾桶之成员简介,相信有很多小伙伴都已经忍不住跃跃欲试了,别着急,从这一篇开始,笔者将会带领大家一 ...

  3. 『开源项目』基于STM32的智能垃圾桶之语音识别

    大家好,我是『芯知识学堂』的SingleYork,前面给大家简单介绍了『免费开源』基于STM32的之成员简介,相信有很多小伙伴都已经忍不住跃跃欲试了,别着急,从这一篇开始,笔者将会带领大家一步一步来完 ...

  4. 2013年度中国优秀开源项目

    2013年度中国优秀开源项目 当前63票 ACL 一个通用网络通信库,为C/ C++程序员提供高效.稳定.可靠.功能强大的开发通讯与服务器框架,以及各种常见应用协议的客户端库. 当前70票 Ansj中 ...

  5. 如何发现优秀的开源项目?

    之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是 还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到点子上了,Gi ...

  6. 从0开始学习 GitHub 系列之「08.如何发现优秀的开源项目」----转载自stormzhang 原创文章

    之前发过一系列有关 GitHub 的文章,有同学问了,GitHub 我大概了解了,Git 也差不多会使用了,但是 还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? 问到点子上了,Gi ...

  7. 阿里巴巴微服务开源项目盘点

    文章目录 阿里巴巴微服务开源项目盘点 1.Apache Dubbo 2.Apache RocketMQ 3.OpenMessaging 4.Nacos 5.Sentinel 6.Arthas 7.Sp ...

  8. python 在线网盘源码_和付费网盘说再见,跟着本文自己起个网盘(Java 开源项目)...

    本文适合有 Java 基础知识的人群,跟着本文可学习和运行 Java 网盘项目. 本文作者:HelloGitHub-秦人 HelloGitHub 推出的<讲解开源项目>[1]系列. 今天给 ...

  9. Android github上开源项目、酷炫的交互动画和视觉效果地址集合

    Android上开源的酷炫的交互动画和视觉效果:http://blog.csdn.net/u013278099/article/details/50323689 Awesome-android-ui: ...

  10. GitHub查找优秀的开源项目和一些资源福利

    GitHub 我大概了解了,Git 也差不多会使用了,但是 还是搞不清 GitHub 如何帮助我的工作,怎么提升我的工作效率? GitHub 其中一个最重要的作用就是发现全世界最优秀的开源项目,你没事 ...

最新文章

  1. 专家也要小心,HTTPS网址的网站就一定安全吗?
  2. C# 笔记 获取程序当前目录
  3. Kubernetes(7) Service Network (advanced)
  4. 对2014年,关于轻应用的五大预言
  5. html文本长度不一样的对齐,关于html:文本在中间不对齐
  6. Linux系统网络基础知识及配置
  7. Flink批处理优化器之数据属性
  8. 字符串左侧补0_(48)C++面试之最长不含重复字符的子字符串(动态规划)
  9. leetcode167. 两数之和 II - 输入有序数组
  10. 北京移动联合中兴通讯率先完成SON 4/5G全制式规模部署
  11. 应用机器学习(五):支持向量机
  12. 房屋出租系统java版
  13. PHP实现支付宝手机WAP支付接入说明
  14. java发微信字体颜色_java微信公众号发送消息模板
  15. crispr基因编辑_用CRISPR编程基因组
  16. 移植facenet pb模型到android
  17. Python取代VB/VBA,弄了个寂寞!
  18. Rasa使用指南01
  19. win10 GTX1050配置VS19+CUDA10.2+CUDNN
  20. mysql 大数据量查询总数 方式比较

热门文章

  1. Javascript特效:音乐导航
  2. reflection java_Java Reflection (JAVA反射)
  3. 数值分析(9)-最小二乘法
  4. Rviz教程系列第一章之Markers
  5. status函数(自学数据结构第一天)
  6. VS2012+OpenCV2.4.9+Qt5.3.1环境配置
  7. NodeJS连接MySQL
  8. 又一知名教授在美被捕!饶毅发文声援,中方也回应了!
  9. 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
  10. keras调用自己训练的模型,并去掉全连接层