开发快平台(M302I小e开发板系列教程)
开发快平台(M302I小e开发板系列教程)
开发块平台ESP8266模块相关理解
一. M302I小e开发板源码注释,源码基于:v1.4.0.8-u34.zip
1. user_main.c
/******************************************************************************
* Copyright 2013-2014 Espressif Systems (Wuxi)
*
* FileName: user_main.c
*
* Description: entry file of user application
*
* Modification history:
* 2014/12/1, v1.0 create this file.
*******************************************************************************/
#include "esp_common.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h" #include "lwip/sockets.h"
#include "lwip/dns.h"
#include "lwip/netdb.h"
#include "driver/uart.h"
#include "espressif/esp_system.h"
#include "et_types.h" #include "driver/i2c_master.h"
#include "driver/OLED_I2C.h" #include "driver/RGB_light.h"
#include "driver/delay.h" #include "user_config.h"
#include "driver/gpio.h"
#include "espressif/smartconfig.h"
#include "driver/i2s.h"
#include "factory.h"
#include "et_api_compatible.h"
#ifdef IR_DEMO
#include "driver/ir.h"
#endif extern void et_user_main(void *pvParameters);
extern void read_uart_buf_task(void *pvParameters);
extern void send_to_mqtt_task(void *pvParameters); LOCAL os_timer_t test_timer;
LOCAL WORK_MODE_T work_mode = WORK_MODE_BUTT; extern et_cloud_handle g_cloud_handle;
extern et_int32 to_stop_app; et_int8 air_kiss_start_flag = ;
et_int8 user_main_start_flag = ;
et_int8 wifi_reconnect_start_flag = ; /******************************************************************************
* FunctionName : user_get_mode_str
* Description : Get mode string
* Parameters :
* Returns : NONE
*******************************************************************************/
et_uchar* ICACHE_FLASH_ATTR
user_get_mode_str(et_uint32 mode)
{
et_uchar *mode_str[] =
{
"DEFAULT",
"AUDIO",
"RGB",
"BAROMETRIC",
"OLED",
"INVALID"
}; return (WORK_MODE_BUTT <= mode ? mode_str[WORK_MODE_BUTT] : mode_str[mode]);
} /******************************************************************************
* FunctionName : user_esp_platform_check_ip
* Description : check whether get ip addr or not
* Parameters : none
* Returns : none
*******************************************************************************/
void ICACHE_FLASH_ATTR
user_esp_platform_check_ip(void)
{
static et_uint32 time = ;
et_uint32 connect_error_flag=;
struct ip_info ipconfig; os_timer_disarm(&test_timer);
//get ip info of ESP8266 station
wifi_get_ip_info(STATION_IF, &ipconfig);
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipconfig.ip.addr != )
{
os_printf("got ip !!! \r\n");
if (user_main_start_flag == )
{
user_main_start_flag = ;
xTaskCreate(et_user_main, "et_user_main", , NULL, , NULL);
}
wifi_reconnect_start_flag = ;
}
else
{
if(wifi_station_get_connect_status() == STATION_WRONG_PASSWORD)
{
if ((system_get_time() - time) >= )
{
os_printf("connect fail, wrong password!!! \r\n");
time = system_get_time();
}
connect_error_flag = ;
}
else if(wifi_station_get_connect_status() == STATION_NO_AP_FOUND)
{
if ((system_get_time() - time) >= )
{
os_printf("connect fail, no AP found!!! \r\n");
time = system_get_time();
}
connect_error_flag = ;
}
else if(wifi_station_get_connect_status() == STATION_CONNECT_FAIL)
{
if ((system_get_time() - time) >= )
{
os_printf("connect fail, connect fail!!! \r\n");
time = system_get_time();
}
connect_error_flag = ;
} if(connect_error_flag == )
{
if (air_kiss_start_flag == )
{
wifi_station_set_reconnect_policy(false);
smartconfig_stop();
air_kiss_start_flag = ;
if(work_mode == WORK_MODE_OLED)
{
OLED_clear();
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //show 网络配置失败
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_str(, , " ", );
}
}
}
//re-arm timer to check ip
os_timer_setfn(&test_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);
os_timer_arm(&test_timer, , );
}
} /******************************************************************************
* FunctionName : user_get_run_mode
* Description : Get the current working mode
* Parameters :
* Returns : NONE
*******************************************************************************/
et_uint32 ICACHE_FLASH_ATTR
user_get_run_mode()
{
return work_mode;
} void audio_init(void)
{
//audio_key_init(); // SPEAKER init
i2s_audio_init(); } /******************************************************************************
* FunctionName : user_init_work_mode
* Description : Initialization work mode
* Parameters :
* Returns : NONE
*******************************************************************************/
et_int32 ICACHE_FLASH_ATTR
user_init_work_mode(et_uint32 mode, et_uchar fac_norm_mode)
{
if (WORK_MODE_BUTT <= mode)
{
os_printf("The work mode=%u is invalid !!!\n", mode);
return RETURN_ERR;
} //#ifdef USER_PRINT_DEBUG
os_printf("get work mode=%s is success !!!\n", user_get_mode_str(mode));
//#endif switch (mode)
{
case WORK_MODE_DEFAULT:
DHT11_init();
break; case WORK_MODE_AUDIO:
DHT11_init();
audio_init();
break; case WORK_MODE_RGB:
RGB_light_init(); // RGB init
DHT11_init();
break; case WORK_MODE_BAROMETRIC:
i2c_master_gpio_init(); // BAROMETRIC init
DHT11_init(); // temperature init
break; case WORK_MODE_OLED:
i2c_master_gpio_init(); // I2C init
OLED_init(); // OLED init
OLED_clear();
DHT11_init();
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
break; default:
break;
} return RETURN_OK;
} /******************************************************************************
* FunctionName : user_get_work_mode
* Description : Get work mode from ADC
* Parameters :
* Returns : NONE
*******************************************************************************/
et_int32 ICACHE_FLASH_ATTR
user_get_work_mode(et_uint32 *mode)
{
et_uint32 adc = system_adc_read();
if (adc > )
{
os_printf("The adc value=%u is invalid !!!\n", adc);
return RETURN_ERR;
} #ifdef USER_PRINT_DEBUG
os_printf("get adc value=%u is success !!!\n", adc);
#endif // ADC turn into work mode
if(adc < )
{
*mode = WORK_MODE_DEFAULT;
}
else if (adc < )
{
*mode = WORK_MODE_AUDIO;
}
else if(adc < )
{
*mode = WORK_MODE_RGB;
}
else if(adc < )
{
*mode = WORK_MODE_BAROMETRIC;
}
else if(adc < )
{
*mode = WORK_MODE_OLED;
}
else
{
*mode = WORK_MODE_BUTT;
}
return RETURN_OK;
} void ICACHE_FLASH_ATTR
smartconfig_done(sc_status status, void *pdata)
{
switch(status)
{
case SC_STATUS_WAIT:
os_printf("SC_STATUS_WAIT\n");
break; case SC_STATUS_FIND_CHANNEL:
set_wifi_spark_timer();
os_printf("SC_STATUS_FIND_CHANNEL\n");
break; case SC_STATUS_GETTING_SSID_PSWD:
os_printf("SC_STATUS_GETTING_SSID_PSWD\n");
sc_type *type = pdata;
if (*type == SC_TYPE_ESPTOUCH)
{
os_printf("SC_TYPE:SC_TYPE_ESPTOUCH\n");
}
else
{
os_printf("SC_TYPE:SC_TYPE_AIRKISS\n");
}
break; case SC_STATUS_LINK:
{
os_printf("SC_STATUS_LINK\n");
struct station_config *sta_conf = pdata; wifi_station_set_config(sta_conf);
wifi_station_disconnect();
wifi_station_connect();
}
break; case SC_STATUS_LINK_OVER: {
os_printf("SC_STATUS_LINK_OVER\n");
smartconfig_stop();
if(work_mode == WORK_MODE_OLED)
{
OLED_clear();
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //show 网络配置完成
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_str(, , " ", );
}
delay_s();
system_restart();
break;
}
} } void airkiss_key_init(key_gpio_t*key)
{
et_uint32 io_reg;
io_reg = GPIO_PIN_REG(key->key_num); PIN_PULLUP_EN(io_reg);
PIN_FUNC_SELECT(io_reg, );
GPIO_AS_INPUT(key->key_gpio_pin);
} void ICACHE_FLASH_ATTR
airkiss_key_poll_task(void *pvParameters)
{
et_uint32 value, i; while()
{
value = gpio_get_value(AIRKISS_KEY_IO_NUM);
if(!air_kiss_start_flag && !value)
{
delay_s();
value = gpio_get_value(AIRKISS_KEY_IO_NUM);
if(!air_kiss_start_flag && !value)
{
os_printf("begin to airkiss\n");
air_kiss_start_flag = ;
os_timer_disarm(&test_timer);
to_stop_app = ; //in airkiss mode, stop et_user_main thread
if(g_cloud_handle != NULL)
{
et_logout_cloud(g_cloud_handle);
et_destroy_context(g_cloud_handle);
g_cloud_handle = NULL;
}
delay_s();
wifi_reconnect_start_flag = ;
smartconfig_start(smartconfig_done); //airkiss start
if(work_mode == WORK_MODE_OLED)
{
OLED_clear();
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //show 网络配置中...
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_chn(, , );
OLED_show_str(, , "...", );
}
os_timer_setfn(&test_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);
os_timer_arm(&test_timer, , );
}
}
delay_ms();
}
os_printf("end airkiss\n");
vTaskDelete(NULL);
} void ICACHE_FLASH_ATTR
user_show_logo()
{
extern et_uchar BMP1[];
et_uint32 len = ; // BMP1 member i2c_master_gpio_init(); // I2C init
OLED_init(); // OLED init
OLED_clear(); // show logo
OLED_show_bmp(, , , , BMP1, len);
} void et_wifi_event_cb(System_Event_t *event)
{
switch(event->event_id)
{
case EVENT_STAMODE_SCAN_DONE: //ESP8266 station finish scanning AP break;
case EVENT_STAMODE_CONNECTED: //ESP8266 station connected to AP os_printf("et connect to ssid %s, channel %d\n", event->event_info.connected.ssid, event->event_info.connected.channel);
break;
case EVENT_STAMODE_DISCONNECTED: //ESP8266 station disconnected to AP
disarm_wifi_spark_timer();
wifi_led_off();
if(true != wifi_station_get_reconnect_policy())
{
os_printf("et wifi set to reconnect\n");
wifi_station_set_reconnect_policy(true);
}
//os_printf("et disconnect from ssid %s, reason %d\n", event->event_info.disconnected.ssid, event->event_info.disconnected.reason);
if(wifi_reconnect_start_flag != )
{
os_printf("airkiss start or start first don't restart %d\n",wifi_reconnect_start_flag);
}
else
{
os_printf("et wifi station connect status %d, restart system\n",wifi_station_get_connect_status());
system_restart();
}
break;
case EVENT_STAMODE_AUTHMODE_CHANGE: //the auth mode of AP connected by ESP8266 station changed
os_printf("mode: %d -> %d\n", event->event_info.auth_change.old_mode, event->event_info.auth_change.new_mode);
break;
case EVENT_STAMODE_GOT_IP: //ESP8266 station got IP from connected AP
set_wifi_spark_timer();
//os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR, IP2STR(&event->event_info.got_ip.ip), IP2STR(&event->event_info.got_ip.mask),
// IP2STR(&event->event_info.got_ip.gw));
break;
// case EVENT_STAMODE_DHCP_TIMEOUT: //ESP8266 station dhcp client got IP timeout
// break;
case EVENT_SOFTAPMODE_STACONNECTED: //a station connected to ESP8266 soft-AP
os_printf("et station: " MACSTR "join, AID = %d\n", MAC2STR(event->event_info.sta_connected.mac), event->event_info.sta_connected.aid);
break;
case EVENT_SOFTAPMODE_STADISCONNECTED: //a station disconnected to ESP8266 soft-AP
os_printf("et station: " MACSTR "leave, AID = %d\n", MAC2STR(event->event_info.sta_disconnected.mac), event->event_info.sta_disconnected.aid);
break;
// case EVENT_SOFTAPMODE_PROBEREQRECVED:
// break;
// case EVENT_MAX:
// break;
default:
break;
}
} #ifdef IR_DEMO
void ir_tx_key(void *pvParameters)
{
et_uchar value=; ir_tx_msg_t tx_data;
tx_data.ir_tx_addr = 0x55;
tx_data.ir_tx_data = 0x28;
tx_data.ir_tx_rep = ; while()
{
value = gpio_get_value(AIRKISS_KEY_IO_NUM);
if(!value)
{
delay_ms();
value = gpio_get_value(AIRKISS_KEY_IO_NUM);
if(!value)
{ //Always press down
ir_tx_func(&tx_data);
}
}
delay_ms();
} vTaskDelete(NULL); }
#endif /******************************************************************************
* FunctionName : user_init
* Description : entry of user application, init user function here
* Parameters : none
* Returns : none
*******************************************************************************/
void user_init(void)
{
os_printf("software version:%s\n", SOFTWARE_VERSION); //打印版本信息 et_uchar result=; if(get_fac_norm_mode(&result) != SPI_FLASH_RESULT_OK) //检测工作模式
{
os_printf("get_fac_norm_mode error, NORMAL mode\n");
} if(result == FAC_MODE) //运行在工厂模式
{
os_printf("run in factory mode\n");
uart_init_new_uart1(BIT_RATE_115200); //设置串口1工作模式
UART_SetPrintPort(UART1); //设置串口1为打印
uart_init_new(BIT_RATE_115200, result); //设置串口0工作模式
return;
} os_printf("run in normal mode\n"); //运行在正常模式 //if define IR_DEMO, ir rx or tx test //定义红外Demo测试
#ifdef IR_DEMO
struct station_config config; memset(&config, , sizeof(config));
wifi_set_opmode(STATION_MODE);
wifi_station_set_config_current(&config); //if define IR_RX, ir rx test
#ifdef IR_RX
ir_rx_init(); //ir tx test
#else
ir_tx_init();
xTaskCreate(ir_tx_key, "ir_tx_key", , NULL, , NULL);
#endif #else //没有定义红外Demo测试
key_gpio_t key;
struct station_config config;
struct ip_info info; // show logo
user_show_logo(); //OLED显示Logo if (RETURN_OK != user_get_work_mode(&work_mode)) //获取工作模式(因使用按键进行设置工作模式)
{
os_printf("get work mode fail !!!\n");
return;
} if (RETURN_OK != user_init_work_mode(work_mode, result)) //根据工作模式来对模块进行初始化操作
{
os_printf("init work mode fail !!!\n");
return;
} //wifi event handle
//WIFI 的配置,首先硬件查找一下FLASH里面有没有存储当前局域网有的WIFI有的话连接它,没有就执行下一步
wifi_set_event_handler_cb(et_wifi_event_cb); memset(&key, , sizeof(key_gpio_t));
key.key_gpio_pin = AIRKISS_KEY_IO_PIN;
key.key_num = AIRKISS_KEY_IO_NUM;
airkiss_key_init(&key);
//对 WIFI 考虑到了两种情况, 一种是当前smartconfig 软件配置一下。调用了一个任务函数, 用来连接网络,
wifi_set_opmode(STATION_MODE);
wifi_reconnect_start_flag = ;
xTaskCreate(airkiss_key_poll_task, "smartconfig_task", , NULL, , NULL); wifi_led_init();
memset(&config, , sizeof(struct station_config));
if(wifi_station_get_config_default(&config) == true)
{
os_printf("ssid=%s\n", config.ssid);
wifi_station_set_config_current(&config);
//for static ip set
/*wifi_station_dhcpc_stop();
IP4_ADDR(&info.ip, 192, 168, 1, 43);
IP4_ADDR(&info.gw, 192, 168, 1, 1);
IP4_ADDR(&info.netmask, 255, 255, 255, 0);
wifi_set_ip_info(STATION_IF, &info);*/
} os_timer_disarm(&test_timer);
os_timer_setfn(&test_timer, (os_timer_func_t *)user_esp_platform_check_ip, NULL);
os_timer_arm(&test_timer, , );
#endif
}
2. et_user_app.c
/*******************************************************************************
* Copyright (c) 2012, 2013 Beidouapp Corp.
*
* All rights reserved.
*
* Contributors:
* Peter Peng - initial contribution
*******************************************************************************/ #include <stdio.h>
#include <string.h>
#include <stdlib.h> #include "esp_common.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "driver/uart.h" #include "user_config.h"
#include "et_fifo.h"
#include "lwip/netdb.h"
#include "factory.h"
#include "espressif/upgrade.h"
#include "et_api_compatible.h" #define MAX_USER_ID 32
#define MAX_ILINK_CONNECT 5 et_char g_user_id[ET_USER_ID_LEN_MAX] = {};
et_char g_group_id[ET_USER_ID_LEN_MAX] = {};
et_uint32 g_group_message = ;
struct hostent *file_server_ip_addr = NULL;
msg_to_net_t msg={};
et_uchar code[]={};
extern et_int32 read_uart_data_flag;
extern xQueueHandle xQueueUart;
et_cloud_handle g_cloud_handle = NULL;
et_cloud_connect_type g_cloud_con_para = {ET_FALSE, ET_TRUE, };
et_uchar kick_out=;
et_dfs_file_info_type i_file_info; struct ilink_connect_client
{
et_int32 state;
et_char user_id[MAX_USER_ID]; }; static struct ilink_connect_client g_ilink_connect_clients[MAX_ILINK_CONNECT]; static et_uchar uart_recv_buff[UART_MAX_READ_BUFFER] = {};
static et_uchar uart_send_buff[UART_MAX_SEND_BUFFER] = {};
et_int32 to_stop_app = ; et_uint32 write_flash_end=;
et_int64 file_total_size=;
et_uint32 audio_voice_data=;
et_uint16 sector=AUDIO_FLASH_START_SECTOR; //打印16进制
void print_hex(et_uchar *label, et_uchar *str, et_int32 len)
{
et_int32 i; os_printf("%s : ", label);
for(i = ; i < len; i++)
os_printf("%02x ", str[i]);
os_printf("\n");
} //Check数据校验
et_uchar check_sum(et_uchar *buf, et_int32 len)
{
et_uchar bcc=;
et_int32 i; for(i = ; i < len; i ++)
bcc ^= buf[i]; return bcc;
} // ascii to 8421bcd,say 0x32 = 50
et_uint32 ascii_2_dec(et_int32 ascii)
{
et_int32 n =, dec=; while(ascii > )
{
dec += (ascii % ) * n;
ascii /=;
n *= ;
} return dec;
} //为服务器准备数据
static et_int32 ack_to_mqtt(et_uchar *msg_buf, et_uchar *ack_buf, et_int32 rc)
{
et_int32 len = START_LEN; ack_buf[] = 0xFF;
ack_buf[] = 0xFF;
ack_buf[] = 0x00;
ack_buf[] = ACK_ERROR_LEN;
ack_buf[] = msg_buf[] | 0x0F;
ack_buf[] = msg_buf[];
ack_buf[] = msg_buf[];
ack_buf[] = rc;
ack_buf[] = check_sum(&ack_buf[], ACK_ERROR_LEN + );
len += ACK_ERROR_LEN; return len; } //为服务器准备温湿度数据
static et_int32 ack_temp_hum_to_mqtt(et_uchar *msg_buf, et_uchar *temp_hum, et_uchar *ack_buf, et_uchar rc)
{
et_int32 len=START_LEN; ack_buf[] = 0xFF;
ack_buf[] = 0xFF;
ack_buf[] = 0x00;
ack_buf[] = ACK_TEMP_HUM_LEN;
ack_buf[] = msg_buf[] | 0x0F;
ack_buf[] = msg_buf[];
ack_buf[] = msg_buf[];
ack_buf[] = rc;
ack_buf[] = ascii_2_dec(temp_hum[]); //we transform to 8421bcd 0x50
ack_buf[] = ascii_2_dec(temp_hum[]);
ack_buf[] = ascii_2_dec(temp_hum[]);
ack_buf[] = ascii_2_dec(temp_hum[]);
ack_buf[] = check_sum(&ack_buf[], ACK_TEMP_HUM_LEN + );
len += ACK_TEMP_HUM_LEN; return len;
} //为服务器准备气压传感器数据
static et_int32 ack_barometric_to_mqtt(et_uchar *msg_buf, et_int32 barometric, et_int32 temp, et_uchar *ack_buf, et_uchar rc)
{
et_uchar baro[]={}, t;
et_int32 i, tmp, len=START_LEN; tmp = ascii_2_dec(barometric);
for(i = ; i < ; i++)
baro[i] = tmp >> ( - i) * ; tmp = ascii_2_dec(temp);
t = tmp; ack_buf[] = 0xFF;
ack_buf[] = 0xFF;
ack_buf[] = 0x00;
ack_buf[] = ACK_BAROMETRIC_LEN;
ack_buf[] = msg_buf[] | 0x0F;
ack_buf[] = msg_buf[];
ack_buf[] = msg_buf[];
ack_buf[] = rc;
ack_buf[] = baro[];
ack_buf[] = baro[];
ack_buf[] = baro[];
ack_buf[] = baro[];
ack_buf[] = t;
ack_buf[] = check_sum(&ack_buf[], ACK_BAROMETRIC_LEN + );
len += ACK_BAROMETRIC_LEN; return len;
} //上传回调函数
void upgrade_callback(void *arg)
{
struct upgrade_server_info *server = arg; if(server->upgrade_flag == true)
{
printf("upgrade success.\n");
system_upgrade_reboot();
}
else
printf("upgrade failed.\n"); free(server->url);
server->url = NULL;
} //解析服务器发送信息
et_int32 parse_msg_from_mqtt(et_uchar *msg_buf, et_int32 data_len)
{
et_int32 i, pos=, rc = -;
et_uchar cmd, type, bcc;
et_int32 len, seq;
et_uint16 gb_code=;
WORK_MODE_T mode; #ifdef USER_PRINT_DEBUG
print_hex("msg_buf", msg_buf, data_len);
#endif if(msg_buf[pos] != 0xFF ||msg_buf[pos + ] != 0xFF)
{
os_printf("parse packet head error\n");
return rc;
}
pos += ; len = (msg_buf[pos] << ) | msg_buf[pos + ];
if(len < || len != data_len - - )
{
os_printf("parse packet length error\n");
return rc;
} bcc = check_sum(&msg_buf[pos], len + - );
if(bcc != msg_buf[data_len - ])
{
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_BCC_ERROR);
os_printf("bcc error\n");
rc = et_chat_to(g_cloud_handle,msg.buf, msg.len, g_user_id, SEND_TO_ALL);
return rc;
} pos += ; cmd = msg_buf[pos];
pos += ; seq += msg_buf[pos];
pos += ; type = msg_buf[pos];
pos += ; mode = user_get_run_mode(); //get board mode from adc
switch(cmd)
{
case CMD_VER_UPDATE_NOTE: //版本升级事件
{
et_uint version_len= len - ;
et_uchar version[]={}, user_bin[]={}, bin=;
struct upgrade_server_info server={}; strncpy(version, &msg_buf[pos], version_len);
if(strcmp(version, SOFTWARE_VERSION))
{
server.sockaddrin.sin_addr.s_addr = inet_addr("192.168.13.103");
server.sockaddrin.sin_port = htons();
server.sockaddrin.sin_family = AF_INET;
server.check_cb = upgrade_callback;
server.check_times = ;
strncpy(server.pre_version, SOFTWARE_VERSION, strlen(SOFTWARE_VERSION));
strncpy(server.upgrade_version, version, version_len);
if(server.url == NULL)
server.url = (et_uchar *)malloc();
memset(server.url, , ); bin = system_upgrade_userbin_check();
if(bin == UPGRADE_FW_BIN1)
{
memcpy(user_bin, "test/user2.bin", );
}
else if(bin == UPGRADE_FW_BIN2)
{
memcpy(user_bin, "test/user1.bin", );
} sprintf(server.url, "GET /%s HTTP/1.0\r\nHost: %s:%d\r\n"pheadbuffer"", user_bin, "192.168.13.103", ); if(system_upgrade_start(&server) == false)
{
printf("upgrade is already started\n");
} }
}
break; case CMD_CONTROL: //控制命令
{
switch(type)
{
case TYPE_RGB_LIGHT_DEV: //RGB_light
{
if(mode == WORK_MODE_RGB)
{ //code undefine
et_uchar red;
et_uchar gre;
et_uchar blu; red = msg_buf[pos];
pos += ;
gre = msg_buf[pos];
pos += ;
blu = msg_buf[pos]; RGB_light_set_color(red, gre, blu); //set rgb color
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_SUCCESS);
rc = msg.len;
}
else
{
printf("mode error, mode = %u\n", mode);
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_MODE_ERR);
rc = msg.len;
}
}
break; case TYPE_OLED_DEV: //OLED
{
et_uchar z_code, b_code;
et_uint offset;
et_uchar num,i=,j,line,colum[]={}; //OLED 128x64, character is 16x16, per line can show 128/16 =8 character,
//in total lines is 64/16 = 4, the OLED can display 32 charaters in total
if(mode == WORK_MODE_OLED)
{
num = (len - ) / ; //numbers of characters
if(num == )
break; if(num > )
num = ; line = (num - ) / + ; for(i = ; i < line - ; i++) //0 to line -1 is 8 characters
{
colum[i] = ;
} colum[i] = num % ; //the last line
if(colum[i] == )
colum[i] = ; OLED_clear(); //clear oled
for(i = ; i < line; i++)
{
for(j = ; j < colum[i] ; j++)
{
z_code = msg_buf[pos++];
b_code = msg_buf[pos++]; gb_code = (z_code << ) | b_code;
if(gb_code > 0x3759) //after 0xd7f9 ,five space
{
gb_code -= ;
if(b_code >= 0x01 && b_code <= 0x04)
gb_code -= 0xa2;
} z_code = (gb_code >> ) & 0xff;
b_code = gb_code & 0xff;
offset = ((et_uint32) * (z_code - 0x10) + b_code - 0x01)*( * );
spi_flash_read(GB_DZK_START_SECTOR * SPI_FLASH_SEC_SIZE + offset, (et_uint *)code , );
oled_show_gb_chn( * j, * i, code);
}
} msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_SUCCESS);
rc = msg.len;
}
else
{
os_printf("mode error, mode = %d\n", mode);
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_MODE_ERR);
rc = msg.len;
}
}
break; default:
break;
}
}
break; case CMD_QUERY: //查询命令
{
switch(type & 0xF0)
{
case TYPE_TEMP_HUM_SENSOR: //温湿度传感器
{
et_uchar temp_hum[HUM_DATA_SIZE]={}; if(DHT11_read_temp_hum(temp_hum, HUM_DATA_SIZE) != RETURN_OK)
{
os_printf("DHT11_read_temp_hum error\n");
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_DEV_FAILED);
rc = msg.len;
break;
} msg.len = ack_temp_hum_to_mqtt(msg_buf, temp_hum, msg.buf, ACK_SUCCESS);
rc = msg.len; if(mode == WORK_MODE_OLED)
{
et_uchar display_temp[]={};
et_uchar display_hum[]={};
sprintf(display_temp, ":%d.%d", temp_hum[], temp_hum[]);
sprintf(display_hum, ":%d.%d%%", temp_hum[], temp_hum[]);
OLED_clear(); //clear oled
switch(type & 0x0F)
{
case TEMP_AND_HUM: //温度和湿度
{
//display tempeature and hummity, such as:
//温度:20.08℃
//湿度:60.89%
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //温
OLED_show_chn(, , ); //度
OLED_show_str(, , display_temp, ); //such as :20.08
OLED_show_chn(, , ); //℃ OLED_show_chn(, , ); //湿
OLED_show_chn(, , ); //度
OLED_show_str(, , display_hum, );//such as :80.05% }
break; case TEMPERATUR: //温度
{
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //温
OLED_show_chn(, , ); //度
OLED_show_str(, , display_temp, ); //such as :20.08
OLED_show_chn(, , ); //℃
}
break; case HUMMITY: //湿度
{
OLED_show_chn(, , ); //show 小e:
OLED_show_str(, , "e:", );
OLED_show_chn(, , ); //湿
OLED_show_chn(, , ); //度
OLED_show_str(, , display_hum, );//such as :80.05%
}
break;
}
}
}
break; case TYPE_BAROMETRIC_SENSOR: //气压传感器
{
et_long32 barometric=, temperature=;
if(mode == WORK_MODE_BAROMETRIC)
{
barometric = barometric_collect(&temperature);
if(barometric == -)
{
os_printf("barometric_collect error\n");
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_DEV_FAILED);
rc = msg.len;
break;
}
msg.len = ack_barometric_to_mqtt(msg_buf, (et_int32)barometric, (et_int32)temperature, msg.buf, ACK_SUCCESS);
rc = msg.len;
}
else
{
os_printf("mode error, mode = %d\n", mode);
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_MODE_ERR);
rc = msg.len;
}
}
break; default:
break;
} }
break; default:
msg.len = ack_to_mqtt(msg_buf, msg.buf, ACK_CMD_ILLIGAL);
rc = msg.len;
break;
} //上传信息
rc = et_chat_to(g_cloud_handle,msg.buf, msg.len, g_user_id, SEND_TO_CLOUD_FIRST); return rc;
} et_int32 add_userid_to_clients(et_char *userid)
{
et_int32 i = ,j = ;
et_int32 ret = -;
et_char *str = "now device has max users";
//et_int32 add_flag = 0; for(i = ; i < MAX_ILINK_CONNECT;i++)
{
if(g_ilink_connect_clients[i].state == )
{
ret = strcmp(userid,g_ilink_connect_clients[i].user_id);
if(ret == )
{
return -;
}
} } for(j = ; j < MAX_ILINK_CONNECT;j ++)
{
if(g_ilink_connect_clients[j].state == -)
{
g_ilink_connect_clients[j].state = ;
strcpy(g_ilink_connect_clients[j].user_id,userid);
os_printf("now add userid is %s\n",g_ilink_connect_clients[j].user_id);
break; } } if(j >= MAX_ILINK_CONNECT)
{
et_chat_to(g_cloud_handle,str,strlen(str),userid,SEND_TO_CLOUD);
return -;
}
else
{
return ;
}
} et_int32 remove_userid_clients(et_char *userid)
{
et_int32 i = ;
et_int32 ret = -;
for(i = ; i < MAX_ILINK_CONNECT;i++)
{
if(g_ilink_connect_clients[i].state == )
{
ret = strcmp(userid,g_ilink_connect_clients[i].user_id);
if(ret == )
{
os_printf("now userid is %s\n",g_ilink_connect_clients[i].user_id);
g_ilink_connect_clients[i].state = -;
memset(g_ilink_connect_clients[i].user_id,,sizeof(g_ilink_connect_clients[i].user_id));
os_printf("now status is %d\n",g_ilink_connect_clients[i].state);
return ;
}
} } return -; } void read_uart_buf_task(void *pvParameters)
{
os_event_t e;
et_int32 rc = ;
et_int32 cmd,seq,len;
et_uchar *data; for (;;)
{
if (xQueueReceive(xQueueUart, (void *)&e, (portTickType)portMAX_DELAY))
{
switch (e.event)
{
case UART_EVENT_RX_CHAR:
{
read_uart_data_flag = ;
memset(uart_recv_buff,,sizeof(uart_recv_buff));
rc = recv_data_uart(uart_recv_buff, e.param, e.param * );
read_uart_data_flag = ;
printf("receive uart %d\n", rc);
}
break; default:
break;
}
}
} vTaskDelete(NULL);
} void init_clients(void)
{
et_int32 j = ; for(j = ; j < MAX_ILINK_CONNECT;j ++)
{
g_ilink_connect_clients[j].state = -;
memset(g_ilink_connect_clients[j].user_id,,sizeof(g_ilink_connect_clients[j].user_id)); } } //写Flash回调函数
et_int32 write_flash_callback (void *arg, const et_int64 file_size, const et_char *data, const et_int32 current_size)
{
et_int32 result=-; if (arg == NULL)
{
return EINVAL;
} if(sector > AUDIO_FLASH_STOP_SECTOR) //超过flash,flash重新覆盖初始地址
{
file_total_size += current_size;
if(file_total_size >= file_size)
{
sector = AUDIO_FLASH_START_SECTOR;
file_total_size = AUDIO_FLASH_LEN - ;
audio_voice_data = ; //to inform interrupt of voice data coming //越界不播放,仍然下载完,只是覆盖
write_flash_end = ; //to inform interrupt of being able to send voice data to i2s
printf("file size > flash size.just play length of flash size(the former 45 seconds).\n");
} return ;
} result = spi_flash_erase_sector(sector);
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_erase_sector error\n");
return -;
} result = spi_flash_write(sector * SPI_FLASH_SEC_SIZE, (et_uint32 *)data, current_size); //write received voice data(4096 bytes) to flash
if(result != SPI_FLASH_RESULT_OK)
{
printf("spi_flash_write error\n");
return -;
} file_total_size += current_size;
sector++; if(file_total_size >= file_size) //下载完成
{
if(file_size > AUDIO_FLASH_LEN) //文件总长度打印flash长度,只播放音频的flash长度
file_total_size = AUDIO_FLASH_LEN; printf("down load file end.\n");
sector = AUDIO_FLASH_START_SECTOR;
audio_voice_data = ; //to inform interrupt of voice data coming
write_flash_end = ; //to inform interrupt of being able to send voice data to i2s
} return ;
} //消息处理任务
//其实对于消息和时间的分支定义,在 smart_e_taste_v1.4.x.x\et_app\include 的 et_types.h 的文件里。开发快官方写得非常详细。
void et_message_process(et_int32 type, et_char *send_userid, et_char *topic_name, et_int32 topic_len, et_context_mes_type *message)
{
int rc = -; switch(type)
{
case MES_CHAT_TO_CHAT: //点对点消息事件
{
os_printf("mes chat to chat: %s\n", send_userid);
memset(g_user_id, , sizeof(g_user_id));
snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid);
parse_msg_from_mqtt(message->payload, message->payload_len);
}
break; case MES_FILE_TRANSFERS: //文件传输消息事件
{
if(user_get_run_mode() != WORK_MODE_AUDIO)
{
printf("run in mode %d ,error\n", user_get_run_mode());
break;
} os_printf("File trans mes from %s:%s\n", send_userid, topic_name);
memset(&i_file_info, , sizeof(et_dfs_file_info_type));
rc = et_file_info(g_cloud_handle,message->payload, &i_file_info);
if(rc == -)
{
os_printf("file info parse failed\n");
break;
} if(file_server_ip_addr == NULL)
{
file_server_ip_addr = gethostbyname(i_file_info.source_ip_addr);
if(file_server_ip_addr == NULL)
{
os_printf("failed, get ip from im server\n");
break;
}
} memset(i_file_info.source_ip_addr, , sizeof(i_file_info.source_ip_addr));
strcpy(i_file_info.source_ip_addr, inet_ntoa(*(file_server_ip_addr->h_addr))); while(write_flash_end)
{
os_delay_us();
} rc = et_down_file(g_cloud_handle,&i_file_info, write_flash_callback);
}
break; case MES_FROM_GROUP_SUBTOPIC: //群消息和主题消息事件
{
os_printf("Group mes from %s\n", topic_name); parse_msg_from_mqtt(message->payload, message->payload_len);
}
break; case MES_FROM_LOCAL: //内网消息事件
{
os_printf("Local mes from %s:%s\n", send_userid, topic_name);
memset(g_user_id, , sizeof(g_user_id));
snprintf(g_user_id, sizeof(g_user_id), "%s",send_userid);
parse_msg_from_mqtt(message->payload, message->payload_len);
}
break; case MES_NOTICE_ADD_BUDDY: //添加用户消息事件
os_printf("You are be add buddy by %s:%s\n", send_userid, topic_name);
break; case MES_NOTICE_REMOVE_BUDDY: //删除用户消息事件
os_printf("You are be remove buddy by %s:%s\n", send_userid, topic_name);
break; case MES_USER_OFFLINE: //用户下线消息事件
os_printf("%s Offline:%s\n", send_userid, topic_name);
break; case MES_USER_ONLINE: //用户上线消息事件
os_printf("%s Online:%s\n", send_userid, topic_name);
break; case MES_USER_STATUS: //用户状态消息事件
os_printf("%s Status:%s\n", send_userid, topic_name);
break; case MES_ONLINE_BUDDIES_LIST: //在线好友列表消息事件
os_printf("Get online buddies list%s:%s\n", send_userid, topic_name);
break;
}
} //事件处理任务
void et_event_process(et_event_type event)
{
et_int32 rc = -; switch(event.event_no)
{
case EVENT_CLOUD_CONNECT: //ilink连接事件
{
disarm_wifi_spark_timer();
wifi_led_on();
os_printf("You are connect:0x%x\n", event.event_no);
}
break;
case EVENT_CLOUD_DISCONNECT: //ilink断连事件
{
set_wifi_spark_timer();
os_printf("You are disconnect:0x%x\n", event.event_no);
//et_logout_cloud(g_cloud_handle);
//et_stop_srv(g_cloud_handle);
}
break;
case EVENT_LOGIN_KICK: //被踢下线事件
kick_out = ;
os_printf("Your account was login by others:0x%x\n", event.event_no);
//et_stop_srv(g_cloud_handle);
//et_logout_cloud(g_cloud_handle);
break;
case EVENT_CLOUD_SEND_FAILED: //外网消息发送失败事件
os_printf("Cloud send failed\n");
break;
case EVENT_CLOUD_SEND_SUCCESS: //外网消息发送成功事件
os_printf("Cloud send success\n");
break;
case EVENT_LOCAL_SEND_FAILED: //内网消息发送失败事件
os_printf("Local send failed\n");
break;
case EVENT_LOCAL_SEND_SUCCESS: //内网消息发送成功事件
os_printf("Local send success\n");
break;
}
} //外网处理任务
void et_ilink_task(void *pvParameters)
{
while()
{
if(!kick_out)
et_ilink_loop(g_cloud_handle);
taskYIELD();
}
vTaskDelete(NULL);
} //内网处理任务
void et_local_task(void *pvParameters)
{
while()
{
et_server_loop(g_cloud_handle);
taskYIELD();
} vTaskDelete(NULL);
} //用户主任务
void et_user_main(void *pvParameters)
{
et_int32 rc = -;
id_info_t id;
et_server_info_t server_info;
et_net_addr_type g_cloud_addr_para = {NULL, }; os_printf("ET U-SDK var%s\n",et_sdk_ver()); //输出et_SDK版本
to_stop_app = ; memset(&id, , sizeof(id_info_t)); //开辟id信息空间
if(get_uid(&id) != SPI_FLASH_RESULT_OK) //判断获取id状态
{
os_printf("et_user_main, get_uid error\n");
return ;
} id.uid[UID_LEN - ] = '\0'; //使用Printf,遇到'\0'停止->添加结尾数符
id.appkey[APPKEY_LEN - ] = '\0';
id.secretkey[SECRETKEY_LEN - ] = '\0'; memset(&server_info, , sizeof(et_server_info_t)); //开辟服务器信息空间
if(get_server(&server_info) != SPI_FLASH_RESULT_OK) //获取服务器信息
{
os_printf("et_user_main, get_server error\n");
return ;
} server_info.lb_addr[ET_LB_ADDR_MAX - ] = '\0';
server_info.lb_port[ET_LB_PORT_MAX - ] = '\0'; g_cloud_addr_para.name_ip = server_info.lb_addr; //绑定云平台地址
g_cloud_addr_para.port = atoi(server_info.lb_port); //绑定云平台端口 os_printf("uid : %s\n", id.uid);
os_printf("appkey : %s\n", id.appkey);
os_printf("secretkey : %s\n", id.secretkey);
os_printf("server information %s : %s\n", server_info.lb_addr, server_info.lb_port); //创建用户信息上下问,在et_client文件中有说明
g_cloud_handle = et_create_context(id.uid, id.appkey, id.secretkey, g_cloud_addr_para);
if(NULL == g_cloud_handle) //如果为Null表示没有用户
{
os_printf("Init et account failed\n");
goto error;
} //设置消息发送回调函数,事件回调函数
if(et_set_callback(g_cloud_handle,et_message_process, et_event_process) < )
{
os_printf("%s et_set_callback failed.\n");
et_destroy_context(g_cloud_handle); //设置失败销毁用户信息上下文
goto error;
} //内网连接,开始连接云
rc = et_start_svr(g_cloud_handle);
if(rc != ){
os_printf("%s et_start_svr fail.\n", __FUNCTION__);
et_destroy_context(g_cloud_handle);
return;
} //创建内网任务
if(pdPASS != xTaskCreate(et_local_task, "local_task", , NULL, , NULL))
{
os_printf("%s et_local_task failed.\n", __FUNCTION__);
et_stop_srv(g_cloud_handle);
et_destroy_context(g_cloud_handle);
return;
} //外网连接,注册用户信息
do
{
rc = et_login_cloud(g_cloud_handle, g_cloud_con_para);
if(rc != )
{
os_printf("login_cloud fail\n");
}
vTaskDelay( / portTICK_RATE_MS); //如果失败,每隔2s注册
}
while(rc != && to_stop_app == ); //创建一个连接任务
if(pdPASS != xTaskCreate(et_ilink_task, "ilink_task", , NULL, , NULL))
{
os_printf("%s et_ilink_task failed.\n", __FUNCTION__);
et_logout_cloud(g_cloud_handle);
et_destroy_context(g_cloud_handle);
goto error;
} error:
vTaskDelete(NULL);
return ;
} //函数 et_create_context ,et_destroy_context,et_set_callback的位置是在 smart_e_taste_v1.4.x.x\et_app\include 的 et_client.h 的文件里。
//函数 et_start_svr,et_stop_srv,et_login_cloud,et_logout_cloud的位置是在 smart_e_taste_v1.4.x.x\et_app\include 的 et_api_compatible.h 的文件里。
二. 开发块平台ESP8266模块Flash功能分区表
地址 | 固件名 功能 | |
0x0 boot_v1.5.bin | 启动引导,系统固件(原厂) | |
0x1000 | user1.2048.new.3.bin | 上节编译生成的固件,用户应用程序 |
0xfc000(4KB) | fac.bin 进入工厂模式的bin,烧入该bin,用户可以重新烧入uid等信息到flash | |
0xfe000(4KB)> | Uid/appkey/securtkey存放地址 | |
0xff000(4KB) | 服务器ip、端口号存放地址 | |
0x100000-0x1AE000 | 该分区用于存放当前体验语音留言功能时微信端下发的音频文件 | |
0x1b0000 | gb2312_only_characters.bin | gb2312中文字库 |
0x1fc000 | esp_init_data_default.bin | 系统参数(原厂) |
0x1fe000 | blank.bin | 系统固件(原厂) |
三. 烧写固件方法如下:
1. ESP8266模块Flash擦除方法:
A. ESP8266擦除工具路径:
http://down.liangchan.net/ESP8266%B2%C1%B3%FD%B9%A4%BE%DF%CD%EA%D5%FB%B0%B2%D7%B0.zip
http://www.liangchan.net/liangchan/9183.html
B 操作方法:
a、安装python27。
b、下载get-pip.py到python安装目录。
c、进入到pip安装包所在的目录,如“cd C:\Python27\Scripts”,运行python get-pip.py指令,等候一分钟。
d、把esptool-master文件夹放到python目录下。
e、安装esptool和pyserial。直接运行pip install esptool和pip install pyserial两条指令即可自动完成。
f、把ESP8266清除flash工具放入esptool-master目录,运行软件即可。(备注: ESP8266工作在升级模式,即:GPIO0接地 )
2. 配置烧录工具
解压FLASH_DOWNLOAD_TOOLS_v2.4_150924.rar,并打开烧写软件:ESP_DOWNLOAD_TOOL_V2.4.exe,在Download Path Config选中文件并填写正确的地址,在前面的小框中打勾,表示选中该文件;按照下图配置SPI FLASH CONFIG参数;并在COM PORT选中开发板的串口PORT;
3. 烧录
配置完成之后,点击START,出现下图所示表示等待烧录,此时按住airkiss按键不放,同时通过开关对开发板上电;当烧录进度条开始增长,表示开始烧写,此时释放airkiss按键,等待进度条变化直到显示烧录完成;
4. 固件烧写注意事项
(1)user1.2048.new.3.bin文件在bin/upgrade下面,其它文件在bin目录下面;
(2)M302I开发板出厂时已经烧入了表1所列的所有固件,用户在编译自己的用户程序时,可以仅仅烧入生成的用户固件(即user1.2048.new.3.bin),而不用烧入其他参数和固件;
(3)fac.bin文件是使开发板处于工厂生产模式的文件,如果烧入该文件,系统重启后将进入工厂模式,在该模式下可以重新烧入appkey/uid/securtkey以及服务器地址和端口号,如果在必要的情况下(比如appkey/uid/securtkey以及服务器地址和端口号分区不小心被烧入其他固件而使他们丢失了),可以重新烧入这些参数。
四. 操作步骤模式:
1. 获取ESP8266模块
a. 新的模块,内置已经下载好原厂固件,可以直接按照步骤2操作;
b. 如果是其它途径获取的模块,对下载的固件不了解,可以直接对Flash进行擦除操作,按照步骤2操作;
2. 使用开发快平台上的固件进行下载,固件可以到官网进行下载,或者找一个工厂文件进行下载,下载操作参考: “三. 烧写固件方法如下”
3. 通过单独或者下载全部文件(包含fac.bin文件),能够在串口工具中看到模块进入到工厂模式,在工厂模式下,能够通过: "设备标识码配置工具 - EtDevQuickTool.exe"来烧写相关信息 ,修改后,通过按恢复出厂设置,能够进入到正常工作模式;如下图:
4. 需要填写的相关信息如下:
APPKEY: 32d64ec4-9999-219200
SECRETKEY: 1fc54501b999999999f42b6b9280237f
U-SDK-UID: Fc5wGsTuv9999999992rtasEjmj9QPfFZR
ADDRESS: lb.kaifakuai.com
PORT: 8085
草料二维码生成器:https://cli.im/
UID信息格式: {"appkey":"32d64ec4-9999-219200","uid":"Fc5wGsTuv9999999992rtasEjmj9QPfFZR"}
以上信息需要注册开发快,进入到云平台,在其中创建一个项目,ESP8266模块应该选择MCU平台,如下图:
5. 参考地址:
http://bbs.kaifakuai.com/forum.php?mod=viewthread&tid=1893&extra=page%3D1
6. 在正常工作模式下,通过按键操作,能够进入到Smart Config 模式下,用于通过微信平台连接,能够让ESP8266模块连接到Wifi;
7. 通过对源码进行修改,在Ubuntu环境下进行编译,生产新的user1.2048.new.3.bin文件,通过下载到ESP8266模块后能够运行新的应用;
开发快平台(M302I小e开发板系列教程)的更多相关文章
- 小熊派IoT开发板系列教程正式发布——免费学习
[摘要] 小熊派开源社区针对小熊派IoT开发板首次规划了小熊派未来的系列教程.从基础到进阶的设计,可适应具有不同基础的开发者,通过该系列教程的学习,开发者能够轻松掌握IoT产品的开发.该系列教程包括单 ...
- .Net Core ORM选择之路,哪个才适合你 通用查询类封装之Mongodb篇 Snowflake(雪花算法)的JavaScript实现 【开发记录】如何在B/S项目中使用中国天气的实时天气功能 【开发记录】微信小游戏开发入门——俄罗斯方块
.Net Core ORM选择之路,哪个才适合你 因为老板的一句话公司项目需要迁移到.Net Core ,但是以前同事用的ORM不支持.Net Core 开发过程也遇到了各种坑,插入条数多了也特别 ...
- 【小程序开发总结】微信小程序开发常用技术方法总结
1.获取input的值 <input bindinput="bindKeyInput" placeholder="输入同步到view中"/> b ...
- 微信小程序红包开发思路 微信红包小程序开发思路讲解
之前公司开发小程序红包,将自己在开发的过程中遇到的一些坑分享到了博客里.不少人看了以后,还是不明白怎么开发.也加了我微信咨询.所以今天,我就特意再写一篇文章,这次就不谈我开发中遇到的坑了.就主要给大家 ...
- 微信小程序开发教程 #043 - 在小程序开发中使用 npm
本文介绍了如何在微信小程序开发中使用 npm 中包的功能,大大提高微信小程序的开发效率,同时也是微信小程序系列教程的视频版更新. 微信小程序在发布之初没有对 npm 的支持功能,这也是目前很多前端开发 ...
- 这是一篇满载真诚的微信小程序开发干货
1月9日零点刚过,张小龙与团队正式发布微信小程序.它究竟能在微信8.5亿用户中牵动多少人,现在还很难说.但对于创业者来讲,小程序无疑带来了新契机,以及服务“上帝”们的新方式. 从今天起,只要开发者登录 ...
- java全栈商业小程序开发
此次开发只为学习和巩固,第一次学习开发 一.开发前需要了解: 开发框架MVVM.痛点.开源工具.VUE前端框架.微信支付模块.uni-app前端框架.小程序申请.开发工具下载.编写测试小程序.小程序结 ...
- 【云开发】10分钟零基础学会做一个快递查询微信小程序,快速掌握微信小程序开发技能(轮播图、API请求)
大家好,我叫小秃僧 这次分享的是10分钟零基础学会做一个快递查询微信小程序,快速掌握开发微信小程序技能. 这篇文章偏基础,特别适合还没有开发过微信小程序的童鞋,一些概念和逻辑我会讲细一点,尽可能用图说 ...
- 微信小程序开发教程目录
本系列教程是自己在工作中使用到而记录的,没有顺序之分 如有错误之处,请给与指正,也不希望误导了别人 微信小程序开发教程目录 微信小程序之注册和入门 微信小程序之HTTPS请求 微信小程序开发之选项卡 ...
随机推荐
- python基础1.0
1. python简介:解释性语言 安装python,注意路径加入path python的解释器,cpython,Python的解释器很多,但使用最广泛的还是CPython.如果要和Java或.Net ...
- Spring Security 理解小记
JWT 框架图如下, 来自博客https://blog.csdn.net/shehun1/article/details/45394405 个人觉得还不错.. 在开发中Spring boot 启用 加 ...
- JAVA_04
* a:局部代码块 * 在方法中出现:限定变量生命周期,及早释放,提高内存利用率 * b:构造代码块 (初始化块) * 在类中方法外出现:多个构造方法方法中相同的代码存放到一起,每次调用构造都执行,并 ...
- LevelDB源码分析-Bloom Filter
Bloom Filter bloom filter是leveldb中用来在一个block中检测key是否存在的工具,主要在BloomFilterPolicy类中实现: class BloomFilte ...
- .net Cache 需要注意的地方
CacheItemPolicy policy = new CacheItemPolicy { AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(ti ...
- appium初步认识
Appium简介: appium官网:http://appium.io/ 一.什么是appium Appium是一个开源.跨平台的测试框架,可以用来测试原生及混合的移动端应用.Appium支持IOS. ...
- 手眼标定eye-to-hand 示例:handeye_stationarycam_calibration
* * This example explains how to use the hand eye calibration for the case where* the camera is stat ...
- Jenkins master slave设置遇到的坑以及解决办法
写好了selenium测试脚本,本地运行没问题,但是现在流行分布式运行,并行执行以显得高大上. 然而,装高大上是要付出代价的. Selenium Grid 已经完美实现分布式和并行了. 奈何现在会Je ...
- FileInputStream文件字节输入流程序
第一种:.read() 一次读一个字节,返回值类型是int,方法读取硬盘访问次数太频繁.缺点:效率低,伤硬盘 import java.io.FileInputStream; import java.i ...
- Mybatis常用代码
以下使用的数据库是Mysql. Mybatis动态Sql: Mapper.xml如下: <select id="selectOrderList" resultMap=&quo ...