收藏官网首页
楼主: jipin

【Gokit】从0开始实现智能插座(PCB、源码等开源)

 

20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
8#
 楼主| 发表于 2016-7-29 17:33:04 | 只看该作者
免费使用STM32、APP自动代码生成工具
Protocol.c 这个文件和MAIN.C是主要实现文件
/**
**************************************
*
* @file      Protocol.c
* @author    Gizwtis
* @version   V2.3
* @date      2015-07-06
*
* @brief     机智云.只为智能硬件而生
*            Gizwits Smart Cloud  for Smart Products
*            链接|增值ֵ|开放|中立|安全|自有|自由|生态
*            www.gizwits.com
*
**************************************/

#include "stdio.h"
#include "stdbool.h"
#include "string.h"
#include "ringbuffer.h"
#include "Protocol.h"
#include "stm32f10x_usart.h"
#include "Hal_Usart/hal_uart.h"
#include "Hal_rgb_led/Hal_rgb_led.h"
#include "rtc.h"        
extern uint16_t                                                                                time_num;                                                                                        //预约用的定时时间
extern uint16_t                                                                                min_num;                                                                                        //记录了多少分钟了
extern uint8_t                                                                                dis_flag;                                                                                        //远程控制标志
Pro_W2D_GetTimeTypeDef Pro_W2D_GetTimeStruct;//获取网络时间结构体
//环形缓冲区
RingBuffer u_ring_buff;
//串口接收信息
//__packed        typedef struct
//{
//    uint8_t                                     Message_Buf[Max_UartBuf]; //串口接收缓冲区
//    uint8_t                                     Message_Len;                  //接受到的数据长度
//} UART_HandleTypeDef;
UART_HandleTypeDef UART_HandleStruct;

//MCU设备信息
//__packed        typedef struct
//{
//    Pro_HeadPartTypeDef                                          Pro_HeadPart;
//    uint8_t                                                                        Pro_ver[8];
//    uint8_t                                                                        P0_ver[8];
//    uint8_t                                                                        Hard_ver[8];
//    uint8_t                                                                        Soft_ver[8];
//    uint8_t                                                                        Product_Key[32];
//    uint16_t                                                                Binable_Time;
//    uint8_t                                                                        Sum;

//} Pro_M2W_ReturnInfoTypeDef;
Pro_M2W_ReturnInfoTypeDef Pro_M2W_ReturnInfoStruct;

/*通用协议帧{
    Pro_HeadPartTypeDef{
        uint8_t                         Head[2];
        uint16_t                     Len;
        uint8_t                         Cmd;
        uint8_t                         SN;
        uint8_t                         Flags[2];
    }
        uint8_t                         Sum;
}*/
Pro_CommonCmdTypeDef Pro_CommonCmdStruct;

/*重发机制结构体
    uint32_t        SendTime;      //重发时记录的时间戳
    uint8_t                        SendNum;       //重发次数
    uint8_t                        Flag;          //1、作为需要等待WiFi应答的标志!!!!!
                                   //2、这个标志位也限制MCU上报数据!!!!!
                                   //   只要此标志置位,暂停上报
                                   //   复位标志,则重新允许上报
    uint16_t        ResendBufLen;  //长度
    uint8_t                        Cmd_Buff[Max_UartBuf];     //重发数据缓冲区
*/
Pro_Wait_AckTypeDef Wait_AckStruct;

/*带ActionBit时的P0命令报文头
    只有4.8WiFi读MCU 4.10WiFi控MCU的报文带ActionBit
    Pro_HeadPartTypeDef{
        uint8_t                         Head[2];
        uint16_t                     Len;
        uint8_t                         Cmd;
        uint8_t                         SN;
        uint8_t                         Flags[2];
    }
    P0_ActionTypeDef                Action;
*/
Pro_HeadPartP0CmdTypeDef Pro_HeadPartP0Cmd;

/*
    Pro_HeadPartTypeDef{
        uint8_t                         Head[2];
        uint16_t                     Len;
        uint8_t                         Cmd;
        uint8_t                         SN;
        uint8_t                         Flags[2];
    }
    uint16_t                Wifi_Status;
    uint8_t                                        Sum;
*/
Pro_W2D_WifiStatusTypeDef Pro_W2D_WifiStatusStruct;
/*由发送发给出,回复方原样返回即可*/
Pro_Wait_AckTypeDef Wait_AckStruct;
uint8_t SN; //程序中的SN,瞎写的,看来不影响报文通信
//ReadTypeDef是WiFi读设备时,读取的数据
//ReadTypeDef值存放至此数组
uint8_t g_DevStatus[MAX_P0_LEN];

uint8_t g_P0DataLen;
uint32_t SystemTimeCount;//系统时间计数 TIM3 1毫秒级中断
uint32_t Last_ReportTime;//用来记录"上一次上报Dev状态"的时间戳
uint32_t Last_Report_10_Time;//用来记录"每隔十分钟,定期上报Dev状态"的时间戳。此标志处理的不当bug
uint8_t timeoutFlag = 0;//Read error package , timeoutFlag 1//没用到

/*环形缓冲区,全局变量*/
uint8_t packageFlag = 0;
uint16_t dataLen = 0;
uint16_t count = 0;
uint8_t tmp_buf[MAX_PACKAGE_LEN] = {0};
uint8_t lastValue = 0;
uint8_t curValue = 0;
//以Pro_开头,表示协议处理函数
static uint8_t GizWits_W2D_AckCmdHandle(void);
static void Pro_W2D_GetMcuInfo(void);
static void Pro_W2D_CommonCmdHandle(void);
static void Pro_W2D_WifiStatusHandle(void);
static void Pro_W2D_GetTimeHandle(void);//获取网络时间函数
static void Pr0_W2D_RequestResetDeviceHandle(void);
static void Pro_W2D_ReadDevStatusHandle(void);
static void Pro_D2W_ReportDevStatusHandle(void);
static void Pro_UART_SendBuf(uint8_t *Buf, uint16_t PackLen, uint8_t Tag);
static uint8_t GizWits_W2D_AckCmdHandle(void);
static void Pro_W2D_ErrorCmdHandle(Error_PacketsTypeDef errorType);
static uint8_t Pro_GetFrame(void);
static uint8_t GizWits_D2W_Resend_AckCmdHandle(void);
extern uint8_t p0Flag ;  //WiFi控制命令【4.10】已经下达的标志


/************************ 重发机制 ******************************
*                   Wait_AckStruct.Flag 是需要等待WiFi应答的标志
*                   Wait_AckStruct当中,保存了需要重发的报文
************************************************************/
static uint8_t GizWits_D2W_Resend_AckCmdHandle(void)
{
    if(Wait_AckStruct.Flag == 1)
    {
        /*重发次数小于两次*/
        if(Wait_AckStruct.SendNum < Send_MaxNum)
        {
            if((SystemTimeCount - Wait_AckStruct.SendTime) > Send_MaxTime)//到达重发时间
            {
                Pro_UART_SendBuf((uint8_t *)&Wait_AckStruct.Cmd_Buff, Wait_AckStruct.ResendBufLen, 0);
#ifdef DEBUG
                printf("Send again\r\n");
#endif
                                Wait_AckStruct.SendTime = SystemTimeCount;//赋值新的系统时间
                Wait_AckStruct.SendNum++;//重发次数加1
                return 2;
            }
        }
        /*重发两次,不再发送此报文*/
        else
        {
            memset(&Wait_AckStruct, 0, sizeof(Wait_AckStruct)); //Wait_AckStruct.Flag = 0;收到Ack或重发了两次时,清空此Flag位
                        return 1;
        }
    }
    return 0;
}
/************************** 判断ACK **************************
*                                             需要等待Ack的地方:
*                                       MCU主动上报信息后
*                                       MCU通知WiFi模块配网后
*                                       MCU通知WiFi模块重启后
**********************************************************/
static uint8_t GizWits_W2D_AckCmdHandle(void)
{
    Pro_HeadPartTypeDef * Wait_Ack_HeadPart = (Pro_HeadPartTypeDef *)Wait_AckStruct.Cmd_Buff;
    Pro_HeadPartTypeDef * Recv_HeadPart = (Pro_HeadPartTypeDef *)UART_HandleStruct.Message_Buf;

    if(Wait_AckStruct.Flag == 1)
    {
        /*判断收到的报文命令码和报文序号,是否是需要等到的ACK*/
                                /*Ack信息的Cmd字段,总是比发送方的Cmd字段多1*/
        if((Wait_Ack_HeadPart->Cmd == (Recv_HeadPart->Cmd - 1)) && (Wait_Ack_HeadPart->SN == Recv_HeadPart->SN))
        {
            memset(&Wait_AckStruct, 0, sizeof(Wait_AckStruct)); //Wait_AckStruct.Flag = 0;收到Ack或重发了两次时,清空此Flag位
            return 0; //允许重新reprot //检查Ack成功,返回0
        }
    }
    return 1;
}


/*****************************************************
* Function Name  : UART_SendBuf
* Description    : 向串口发送数据帧
* Input          : buf:数据起始地址;
                                                                                packLen:数据长度;
                                                                                tag=0,不等待ACK;tag=1,等待ACK;
                                                                                需要等待Ack的地方:
                    MCU主动上报信息后
                    MCU通知WiFi模块配网后
                    MCU通知WiFi模块重启后
                                                                                需要等待ACK时,Wait_AckStruct.Flag 置位
                                                                                若等待ACK,按照协议失败重发3次;数据区出现FF,在其后增加55
*****************************************************/
static void Pro_UART_SendBuf(uint8_t *Buf, uint16_t PackLen, uint8_t Tag)
{
    uint16_t i;

    for(i=0; i<PackLen; i++)
    {
        UART2_Send_DATA(Buf);
        if(i >=2 && Buf == 0xFF)
        {
            UART2_Send_DATA(0x55);
        }
    }
    //需要实现重发的报文 当等不到Ack时重发
    if(Tag == 1)
    {
        Wait_AckStruct.SendTime = SystemTimeCount;
        Wait_AckStruct.SendNum = 0;
        Wait_AckStruct.Flag = 1;//这里添加Wait标志
        memcpy(Wait_AckStruct.Cmd_Buff, Buf, PackLen);//把发送的数据Buf,备份到Ack
    }
}

/*****************************************************
* Function Name  : exchangeBytes 大 小端转换
* Description    : 模拟的htons 或者 ntohs,如果系统支字节序更改可直接替换成系统函数
* Input          : value
* Output         : None
* Return         : 更改过字节序的short数值
* Attention                   : 从WIFI接收过来的数据 要转换,发送回去给WIFI也要再转换回去
*****************************************************/
short        exchangeBytes(short        value)
{
    short                        tmp_value;
    uint8_t                *index_1, *index_2;

    index_1 = (uint8_t *)&tmp_value;
    index_2 = (uint8_t *)&value;

    *index_1 = *(index_2+1);
    *(index_1+1) = *index_2;

    return tmp_value;
}

20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
7#
 楼主| 发表于 2016-7-29 17:30:41 | 只看该作者
gokit.h
#ifndef _GOKIT_H
#define _GOKIT_H

#include "stm32f10x.h"
#include "Hal_key/Hal_key.h"
#include "Hal_led/Hal_led.h"
#include "Hal_motor/Hal_motor.h"
#include "Hal_rgb_led/Hal_rgb_led.h"
#include "Hal_temp_hum/Hal_temp_hum.h"
#include "Hal_infrared/Hal_infrared.h"
#include "Hal_Usart/hal_uart.h"
#include "ringbuffer.h"
#include "Protocol.h"
#include <string.h>

//__packed        typedef struct       
//{
//        uint8_t                                LED_Cmd;
//        uint8_t                                LED_R;
//        uint8_t                                LED_G;  
//        uint8_t                                LED_B;       
//        MOTOR_T                                Motor;
//        uint8_t       Infrared;
//        uint8_t       Temperature;
//        uint8_t       Humidity;
//        uint8_t                                Alert;
//        uint8_t                                Fault;
//}ReadTypeDef_t; //发送 发给WIFI的数据
__packed        typedef struct        //把里的数据返回给APP
{
        uint8_t                                        LED_Cmd;//开关,是否启用定时器
        uint8_t                                        Week_Repeat;//每周重复
        uint16_t                                Time_On_Minute;  //定时开机
        uint16_t                                Time_Off_Minute;        //定时 关机
        uint16_t                                CountDown_Minute;//倒计时
        uint16_t               Power_Consumption;//能耗
}ReadTypeDef_t; //发送 发给WIFI的数据dev_status
//__packed typedef struct       
//{
//        uint8_t                                                        Attr_Flags;//信息位 是否有效的标志位
//        uint8_t                                                        LED_Cmd;
//        uint8_t                                                        LED_R;
//        uint8_t                                                        LED_G;  
//        uint8_t                                                        LED_B;
//        MOTOR_T                                                        Motor;               
//       
//}WirteTypeDef_t;
__packed typedef struct       
{
        uint8_t                                                        Attr_Flags;//信息位 是否有效的标志位
        uint8_t                                                        LED_Cmd;
        uint8_t                                        Week_Repeat;//每周重复
        uint16_t                                Time_On_Minute;  //定时开机
        uint16_t                                Time_Off_Minute;        //定时 关机
        uint16_t                                CountDown_Minute;//倒计时
        uint16_t               Power_Consumption;//能耗
       
}WirteTypeDef_t;//接收 WIFI发过来的数据

void HW_Init(void);
void Printf_SystemRccClocks(void);
void GizWits_GatherSensorData(void);
void GizWits_ControlDeviceHandle(void);
void SW_Init(void);
void KEY_Handle(void);
//void GizWits_WiFiStatueHandle(uint16_t wifiStatue);

#endif


20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
6#
 楼主| 发表于 2016-7-29 17:30:04 | 只看该作者
/*****************************************************
* Function Name  : GizWits_ControlDeviceHandle
* Description    : Analy P0 Package根据数据有效位标志,进行控制
    4.10 WiFi模组控制MCU
    WiFi发:
    Header(2B)__LEN(2B)__CMD(1B)__sn(1B)__falg(2B)__ActionBit(1B)__attrFlags(1B)__attrValue(6B)__CheckSum(1B)
    0xFFFF      0x000D   0x03     0x##    0x0000    0x01           标志位         控制值         0x##
    MCU 回通用消息帧:
    Header(2B)__LEN(2B)__CMD(1B)__sn(1B)__falg(2B)__CheckSum(1B)
    0xFFFF      0x0005   0x04     0x##    0x0000    0x##
   
        Bit0~5ED_ONOFF, LED_Color, R,G,B, Motor_speed

    WirteTypeDef_t{
        uint8_t                                                        Attr_Flags;      //信息位 是否有效的标志
        uint8_t                                                        LED_Cmd;
        uint8_t                                                        LED_R;
        uint8_t                                                        LED_G;  
        uint8_t                                                        LED_B;
        MOTOR_T                                                        Motor;               
        }
    依靠接收的数据帧,存储到WirteTypeDef,再更改设备状态
*****************************************************/
void GizWits_ControlDeviceHandle()  //WiFi模组控制MCU
{
        //标志位 0位开关 共1个字节
        if( (WirteTypeDef.Attr_Flags & (1<<0)) == (1<<0))//低位第0位ONOFF  是否设置标志位7位
        {
                        if((WirteTypeDef.LED_Cmd &(1<<0))== 0)
                        {
                                LED_RGB_Control(0,0,0);
                                LED_OFF(LED1);
                                ReadTypeDef.LED_Cmd &= ~(1<<0);//存储状态LED_OnOff a&=~(1<<i);//将a的bit i清0
                                printf("LED OFF \r\n");
                        }
                        if((WirteTypeDef.LED_Cmd &(1<<0))== (1<<0))
                        {
                                ReadTypeDef.LED_Cmd |= (1<<0);//LED_OnOn a|=1<<i;//将a的bit i置1
                                LED_ON(LED1);
                                LED_RGB_Control(254,0,0);//默认打开时,是红色
                                printf("LED ON \r\n");
                        }
        }
        //标志位是否启用定时器
        if( (WirteTypeDef.Attr_Flags & (1<<1)) == (1<<1))//低位第1位Time_OnOff
        {
                        if((WirteTypeDef.LED_Cmd & (1<<1))== 0)
                        {
                                //LED_RGB_Control(0,0,0);
                                LED_OFF(LED2);
                                ReadTypeDef.LED_Cmd &= ~(1<<1);//存储状态LED_OnOff a&=~(1<<i);//将a的bit i清0
                                printf("Time_OnOff OFF \r\n");
                        }
                        if((WirteTypeDef.LED_Cmd & (1<<1)) == (1<<1))
                        {
                                ReadTypeDef.LED_Cmd |= (1<<1);//LED_OnOn a|=1<<i;//将a的bit i置1
                                LED_ON(LED2);
                                //LED_RGB_Control(254,254,0);//
                                printf("Time_OnOff ON \r\n");
                        }
        }
        //标志位是否启用倒计时
        if( (WirteTypeDef.Attr_Flags & (1<<2)) == (1<<2))
        {
                        if((WirteTypeDef.LED_Cmd & (1<<2))== 0)
                        {
                                //LED_RGB_Control(0,0,0);
                                LED_OFF(LED3);
                                ReadTypeDef.LED_Cmd &= ~(1<<2);//存储状态LED_OnOff a&=~(1<<i);//将a的bit i清0
                                printf("Count_Down_OnOff OFF \r\n");
                                TIM_Cmd(TIM4,DISABLE);  //失能TIMx外设
                          time_min = 0;
                          time_sec = 0;
                                min_flag = 0;
                        }
                        if((WirteTypeDef.LED_Cmd & (1<<2)) == (1<<2))
                        {
                                ReadTypeDef.LED_Cmd |= (1<<2);//LED_OnOn a|=1<<i;//将a的bit i置1
                                LED_ON(LED3);
                                //LED_RGB_Control(254,254,254);//
                                printf("Count_Down_OnOff ON \r\n");
                                CountDown_Minute_time=exchangeBytes(ReadTypeDef.CountDown_Minute);//重新给当前设置的值给倒计时
                                if(CountDown_Minute_time!=0)
                                {
                                        TIM_Cmd(TIM4, ENABLE);  //使能TIMx外设
                                }
                        }
        }
        //标志位是否重复星期
        if( (WirteTypeDef.Attr_Flags & (1<<3)) == (1<<3))
        {
                ReadTypeDef.Week_Repeat=WirteTypeDef.Week_Repeat;
                GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
        }
        //标志位定时开机 注:时间以分钟为单位1小时=60分钟=0x3c 存储的是16进制
        if( (WirteTypeDef.Attr_Flags & (1<<4)) == (1<<4))
        {
                        printf("Time_On_Minute ON = %d \r\n",exchangeBytes(WirteTypeDef.Time_On_Minute));
                        if(exchangeBytes(WirteTypeDef.Time_On_Minute)<1441)
                        {
                                ReadTypeDef.Time_On_Minute=WirteTypeDef.Time_On_Minute;
                                CountDown_Time_On_Minute=exchangeBytes(ReadTypeDef.Time_On_Minute);//存储的是高低位改变过的
                                GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                        }
        }
        //标志位定时关机
        if( (WirteTypeDef.Attr_Flags & (1<<5)) == (1<<5))
        {
                        printf("Time_On_Minute OFF = %d \r\n",exchangeBytes(WirteTypeDef.Time_Off_Minute));
                        if(exchangeBytes(WirteTypeDef.Time_Off_Minute)<1441)
                        {
                                ReadTypeDef.Time_Off_Minute=WirteTypeDef.Time_Off_Minute;
                                CountDown_Time_Off_Minute=exchangeBytes(ReadTypeDef.Time_Off_Minute);//存储的是高低位改变过的
                                GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                        }
        }
        //标志位倒计时
        if( (WirteTypeDef.Attr_Flags & (1<<6)) == (1<<6))
        {
                printf("CountDown_Minute T = %d \r\n",exchangeBytes(WirteTypeDef.CountDown_Minute));
                if(exchangeBytes(WirteTypeDef.CountDown_Minute)<1441)
                {
                        ReadTypeDef.CountDown_Minute=WirteTypeDef.CountDown_Minute;
                        GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                        CountDown_Minute_time=exchangeBytes(ReadTypeDef.CountDown_Minute);//当前设置的值给倒计时
                        if(((ReadTypeDef.LED_Cmd & (1<<2)) == (1<<2))&&(CountDown_Minute_time!=0))
                        {
                          time_min = 0;
                          time_sec = 0;
                                min_flag = 0;
                                TIM_Cmd(TIM4, ENABLE);  //使能TIMx外设
                        }
                }
        }
}
/*****************************************************
* Function Name  : GizWits_GatherSensorData();
* Description    : Gather Sensor Data
* Input          : None
* Output         : None
* Return         : None
* Attention                 : None
*****************************************************/
void GizWits_GatherSensorData(void)
{
//        ReadTypeDef.Infrared = IR_Handle();
//        DHT11_Read_Data(&curTem, &curHum);
//        ReadTypeDef.Temperature = (curTem + lastTem) /2;
//        ReadTypeDef.Humidity = (curHum + lastHum)/2;

//        ReadTypeDef.Temperature = ReadTypeDef.Temperature + 13;//Temperature Data Correction//根据协议,矫正数据
//        lastTem = curTem;
//        lastHum = curHum;
}
/*****************************************************
* Function Name  : KEY_Handle
* Description    : Key processing function
*                     KEY1 短按 : None
*                     KEY1 长按 : None
*                     KEY2 短按 : SoftAP方式配置WiFi模组
*                     KEY2 长按 : AirLink方式配置WiFi模组

* 4.13获取网络时间
__packed        typedef struct
{
    Pro_HeadPartTypeDef            Pro_HeadPart;
    uint16_t                year;
          uint8_t                 month;
          uint8_t                 day;
          uint8_t                 hour;
          uint8_t                 minute;
          uint8_t                 second;
          uint32_t                other;
    uint8_t                                                                        Sum;
} Pro_W2D_GetTimeTypeDef;
*****************************************************/
void KEY_Handle(void)
{
        uint8_t Key_return =0;       
        Key_return = ReadKeyValue();       
        if(Key_return & KEY_UP)
        {
                if(Key_return & PRESS_KEY1)//短按K1
                {
#ifdef PROTOCOL_DEBUG
                                  printf("KEY1 PRESS\r\n");
#endif               
                        GizWits_D2WGetCmd();
                }
                if(Key_return & PRESS_KEY2)//短按K2
                {
#ifdef PROTOCOL_DEBUG
                        printf("KEY2 PRESS ,Soft AP mode\r\n");
#endif       
                        //Soft AP mode, RGB red
                        LED_RGB_Control(255, 0, 0);
                        GizWits_D2WConfigCmd(SoftAp_Mode);
                        NetConfigureFlag = 1;
                }                               
        }

        if(Key_return & KEY_LONG)
        {
                if(Key_return & PRESS_KEY1)//长按K1
                {
#ifdef PROTOCOL_DEBUG
                                printf("KEY1 PRESS LONG ,Wifi Reset\r\n");
#endif                       
                        GizWits_D2WResetCmd();//解绑WIFI
                }
                if(Key_return & PRESS_KEY2)//长按K2
                {
                        //AirLink mode, RGB Green
#ifdef PROTOCOL_DEBUG
                                printf("KEY2 PRESS LONG ,AirLink mode\r\n");
#endif       
                        LED_RGB_Control(0, 128, 0);
                        GizWits_D2WConfigCmd(AirLink_Mode);//进入AirLink_Mode模式
                        NetConfigureFlag = 1;
                }
        }
}
/*****************************************************
* Function Name  : GizWits_WiFiStatueHandle
* Description    : Callback function , Judge Wifi statue
* Input          : None
* Output         : None
* Return         : Bit , Attr_Flags
* Attention                 :
*****************************************************/
void GizWits_WiFiStatueHandle(uint16_t wifiStatue)
{       
        if(((wifiStatue & Wifi_ConnClouds) == Wifi_ConnClouds) && (NetConfigureFlag == 1))
        {
                printf("W2M->Wifi_ConnClouds\r\n");
                NetConfigureFlag = 0;
                LED_RGB_Control(0,0,0);
        }
}
/************* (C) COPYRIGHT 2011 STMicroelectronics ****END OF FILE***/

20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
5#
 楼主| 发表于 2016-7-29 17:29:37 | 只看该作者
main.c
/**
**************************************
*
* @file      main.c
* @author    Gizwtis
* @version   V2.3
* @date      2015-07-06
*
* @brief     机智云 只为智能硬件而生
*            Gizwits Smart Cloud  for Smart Products
*            链接|增值|开放|中立|安全|自有|自由|生态
*            www.gizwits.com
*                                                        APP打开,会发一条CMD03查询当前的状态命令ff ff  0  6  3  9  0  0  2 14
                                                                                                                                回复[208527] MCU   : ff ff  0 10  4  9  0  0  3  0  0  0  0  0  0  0  0  0  0 20
                                                                                                                                                                                                                 ff ff  0 10  4 23  0  0  3  2 10 3c  0  0  0  0  0  0  0 88
                                                                                                                                                                 如果没有收到会等待查询很久,最后提示断开连
WIFI状态改变,会把时间信息给MCU,同时MCU打开自己的RTC进行时钟,没有网络的情况下,都能正常执行预约和定时开关

**************************************/

/* Includes ------------------------------------------------------------------*/
#include "gokit.h"
#include "rtc.h"
/*Global Variable*/

extern _calendar_obj calendar;        //日历结构体

extern Pro_W2D_GetTimeTypeDef Pro_W2D_GetTimeStruct;//获取网络时间结构体
uint16_t  time_min;//分钟计时
uint32_t  time_sec;//秒种计时
uint8_t   min_flag;//分钟到标志
uint16_t                                                                                CountDown_Minute_time;                     //定时器存的时间当前剩余时间
uint16_t                                                                                CountDown_Time_On_Minute;                        //存储定时开的时间
uint16_t                                                                                CountDown_Time_Off_Minute;                //存储定时关的时间
uint32_t ReportTimeCount = 0;  //没用到
uint8_t  gaterSensorFlag = 0;         //MCU收集外设信息标志,每隔1s被TIM3中断函数置位一次
uint8_t  Set_LedStatus = 0;                 //枚举量 方式更改等颜色,这种方式下更改IoE中颜色、或者开闭灯,无效。
uint8_t  NetConfigureFlag = 0;  //是否 打印WiFi配置结果 的标志
uint8_t  curTem = 0, curHum = 0;//DHT11数据
uint8_t  lastTem = 0,lastHum = 0;

//注意是head指向了读区域,tail指向了写区域
//typedef struct {
//    size_t rb_capacity;//缓冲区容量
//    char  *rb_head;//用于读出的指针
//    char  *rb_tail;//用于写入的指针
//    char  rb_buff[256];//缓冲区实体
//}RingBuffer;
extern RingBuffer u_ring_buff;

uint8_t p0Flag = 0;//WiFi控制设备命令,主要是CMD0X03已经下达的标志

WirteTypeDef_t        WirteTypeDef; //WiFi发来的数据                   MCU要接收 WIFI发过来的数据
ReadTypeDef_t          ReadTypeDef;        //WiFi要读取的数据     MCU要发送发给WIFI的数据 接收到的数据如果是U16以上要exchangeBytes函数转换

/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
int main(void)
{
        uint8_t p0_control_buf[MAX_P0_LEN];//存储控制命令
       
        SystemInit();        //开始初始化
        HW_Init();
        Printf_SystemRccClocks();
        SW_Init();               
        while(1)
        {
                        KEY_Handle();        //处理按键       
                        GizWits_MessageHandle(p0_control_buf, sizeof(WirteTypeDef_t));//如果是控制命令,则把控制信息 放到p0_ctl_buf中
                        if(p0Flag == 1)//控制命令已经下达标志
                        {
                                //控制信息 转存到WirteTypeDef
                                memcpy((uint8_t *)&WirteTypeDef, p0_control_buf, sizeof(WirteTypeDef_t));
                                //靠WirteTypeDef来解析控制命令,控制设备
                                GizWits_ControlDeviceHandle();
                                //GizWits_DevStatusUpgrade(uint8_t *P0_Buff, uint32_t Time, uint8_t flag)
                                GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);//flag=1,立即汇报
                                p0Flag =0;
                        }
                        //此标志每隔1s被TIM3中断函数置位一次
                        if(gaterSensorFlag != 0)
                        {
                                if((ReadTypeDef.LED_Cmd & (1<<1)) == (1<<1))//如果打开了定时功能才进入
                                {
                                        if((ReadTypeDef.Week_Repeat & ( 1<<(calendar.week-1)))==( 1<<(calendar.week-1)))//先判断星期是否是设置的。然后判断小时,分钟
                                        {
                                                        printf("t=%d",((calendar.hour*60)+calendar.min));
                                                        if(CountDown_Time_On_Minute==((calendar.hour*60)+calendar.min))//如果设置的小时数与现在的小时数相同 16进制表示
                                                        {
                                                                LED_RGB_Control(254,0,0);//默认打开时,是红色
                                                        }
                                                        if(CountDown_Time_Off_Minute==((calendar.hour*60)+calendar.min))
                                                        {
                                                                LED_RGB_Control(0,0,0);//关灯
                                                        }
                                         }
                            }
                                        GizWits_GatherSensorData(); //没有用到
                                        gaterSensorFlag = 0;
                        }
      GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 0);//更新数据等待定时上报
                        //-----------------------------{
                        if(min_flag)//如果启用了预约功能
                        {
                                min_flag=0;
                                CountDown_Minute_time--;
                                if(CountDown_Minute_time<=0)//减到0
                                {
                                                TIM_Cmd(TIM4,DISABLE);  //失能TIMx外设
                                                time_min = 0;
                                          time_sec = 0;
                                                CountDown_Minute_time = 0;
                                                if((ReadTypeDef.LED_Cmd &(1<<0))== 0)
                                                        {
                                                                LED_RGB_Control(254,0,0);//打开时,是红色
                                                                LED_ON(LED1);
                                                                ReadTypeDef.LED_Cmd |= (1<<0);//LED_OnOn a|=1<<i;//将a的bit i置1如果以前是关的,现在要开
                                                                printf("TIME LED ON \r\n");
                                                        }
                                                        else if((ReadTypeDef.LED_Cmd &(1<<0))== (1<<0))
                                                        {
                                                                ReadTypeDef.LED_Cmd &= ~(1<<0);//存储状态LED_OnOff a&=~(1<<i);//将a的bit i清0如果以前是开的,现在要关
                                                                LED_OFF(LED1);
                                                                LED_RGB_Control(0,0,0);
                                                                printf("TIME LED OFF \r\n");
                                                        }
                                                        LED_OFF(LED3);
                                                        ReadTypeDef.LED_Cmd &= ~(1<<2);//预约时间已经到了,就要关闭预约开关
                                                        GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                                 }
                                ReadTypeDef.CountDown_Minute=exchangeBytes(CountDown_Minute_time);
                                GizWits_DevStatusUpgrade((uint8_t *)&ReadTypeDef, 10*60*1000, 1);
                                       
                        }
                        //-----------------------------}
        }
}
/** @addtogroup GizWits_HW_Init
  * @{
  */
void HW_Init(void)
{
        Delay_Init(72);       
        UARTx_Init();
  RGB_KEY_GPIO_Init();
        RGB_LED_Init();       
        LED_GPIO_Init();       
        KEY_GPIO_Init();
        TIM3_Int_Init(7199,9);   //ms interrupt       
        TIM4_Int_Init(10000,7199);//产生1s的定时TIM4_Int_Init(10000,7199);
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
        Motor_Init();       
        DHT11_Init();       
        IR_Init();       
        RTC_Init();                                  //RTC初始化
}
/** @addtogroup GizWits_SW_Init
  * @{
  */
void SW_Init()
{
        ReadTypeDef.LED_Cmd = 0;
        ReadTypeDef.Week_Repeat = 0;
        ReadTypeDef.Time_On_Minute = 0;  
        ReadTypeDef.Time_Off_Minute = 0;
        ReadTypeDef.CountDown_Minute = 0;
        GizWits_init(sizeof(ReadTypeDef_t));
        printf("Gokit Init Ok ...\r\n");
}
/** @addtogroup Printf_SystemRccClocks
  * @{
  */
void Printf_SystemRccClocks(void)
{
        uint8_t SYSCLKSource;

        RCC_ClocksTypeDef  SystemRCC_Clocks;
        printf("System start...\r\n");
        SYSCLKSource = RCC_GetSYSCLKSource();
        if(SYSCLKSource==0x04)
                printf("SYSCLKSource is HSE\r\n");
        else if(SYSCLKSource==0x00)
                printf("SYSCLKSource is HSI\r\n");
        else if(SYSCLKSource==0x08)
                printf("SYSCLKSource is PL!\r\n");
       
        RCC_GetClocksFreq(&SystemRCC_Clocks);
        printf("SYS clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.SYSCLK_Frequency/1000000);
        printf("HCLK clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.HCLK_Frequency/1000000);
        printf("PCLK1 clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.PCLK1_Frequency/1000000);
        printf("PCLK2_clock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.PCLK2_Frequency/1000000);       
        printf("SADCCLK_Frequencyclock =%dMHz \r\n",(uint32_t)SystemRCC_Clocks.ADCCLK_Frequency/1000000);

}



20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
地板
 楼主| 发表于 2016-7-29 17:26:53 | 只看该作者
注册成为机智云开发者,手机加虚拟设备快速开发
上面主要是了解配置安卓编译环境,和修改APP几个主要的参数。下面我们要了解的是硬件。智能云插座是怎样工作的。MCU代码主要是机智云给出的。我只是在上面 把一个通用的代码变为配合公版APP智能云插座就能工作的一个过程。


首先下载GOKIT开发板代码http://site.gizwits.com/zh-cn/de ... hardware?type=GoKit
我这里使用的是版本号: 2.3.2更新时间: 2016.1.04 12:20


在我们去修改MCU代码之前,我想解释下这个插座的功能,虽然大家都知道,但我还是要结合APP讲一下操作过程
1.在我们拿到开发板,或者是智能云插座硬件时,第一步是连接WIFI网络。
按下开发板的KEY2键,用长按AIRLINK连接方式,绿灯长亮,说明是这个配置模式
这时,我们可以USB连接电脑,用串口工作查看打印出来的信息
//------------------------------------------
KEY2 PRESS LONG ,AirLink mode
[9487240] MCU   : ff ff  0  6  9 27  0  0  2 38
GAgentToMCU: ff ff  0  5  a 27  0  0 36
ACK: SUCCESS! ...
Time:2016-7-29 16:51:27-5
GAgentToMCU: ff ff  0  7  d 75  0  0  6  e 9d
[9487821] MCU   : ff ff  0  5  e 75  0  0 88
W2D_WifiStatusStruct.Wifi_Status=3590Time:2016-7-29 16:51:28-5

//------------------------------------------
KEY2 PRESS LONG ,AirLink mode 说明我们进行了长按操作  并进入了AirLink mode
[9487240] MCU   : ff ff  0  6  9 27  0  0  2 38   前面是打印当前发数据时的系统时间 协议分析大家还是很容易理解的。




APP已经配置成功了。
这时我们看串口打印出来的信息
GAgentToMCU: ff ff  0  7  d 8c  0  0  6 3a e0
[93134] MCU   : ff ff  0  5  e 8c  0  0 9f

GAgent就是WIFI模块,它向MCU发送了命令码为0X0D的WIFI状态变化指令。 6 3a 就是当前WIFI模块的状态,可以查协议得知具体是什么状态
按协议,MCU是要回复一个通用状态帧
W2M->Wifi_ConnClouds 打印出WIFI配置结束,
是下面这个函数里。
void GizWits_WiFiStatueHandle(uint16_t wifiStatue)
{
if(((wifiStatue & Wifi_ConnClouds) == Wifi_ConnClouds) && (NetConfigureFlag == 1))
{
printf("W2M->Wifi_ConnClouds\r\n");
NetConfigureFlag = 0;
LED_RGB_Control(0,0,0);
}
}
如果WIFI连接到了网络。我们会发送一条获取网络时间的命令给WIFI,因为我们插座有一个定时 开与关的功能,只要获取一次就可以了,MCU自带RTC功能,时钟可以自己走。
[93153] MCU   : ff ff  0  5 17  2  0  0 1e   申请获取网络时间
GAgentToMCU: ff ff  0 10 18  2  0  0  7 e0  7 1d 11  6 28 57 9b 1c a0 22  获取到的网络时间
如果当前WIFI没有连接上路由,获取到的时间是1970年的。
Time:2016-7-29 17:6:39-5  这是解析出来显示的时间 年月日 ,时分秒 最后重要的是星期 因为我们APP里面要设置星期几执行开关功能。没有选中的星期几,不能执行开关动作。
[2016] year   : [7] month   : [29] day   : [17] hour   : [6] minute   : [40] second   : 这里是RTC时钟显示的时间。
APP上有一个是预约功能,一个是定时开关功能。我们使用的是两套计时方法。互相独立。
上面解释的是一个APP登入的过程。MCU需要获取的数据
协议里面的一些心跳,我们不用关心。








20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
板凳
 楼主| 发表于 2016-7-29 16:32:56 | 只看该作者
首先大家下载公版APP智能云插座的源代码 然后导入,再修改成与自己关联的。每个APP要包含自己的APPID PRODUCT_KEY  APP_SECRET,如果用我的APP是连接不上你的硬件产品的。
https://git.oschina.net/dantang/Gizwits-SmartSocket_Android


解压之后把源码文件夹放到workspace文件夹里
目录每个人安装路径不一样,结果也不一样,我的是C:\Users\JIPINZN\workspace
导入刚下载的APP源码项目
然后双击Existing Projectts into Workspace
如果看到下面打抅,说明是有效的。可以导入


导入进来之后,第一步是要修改成自己的APPID PRODUCT_KEY  APP_SECRET

/**
* app配置参数.
*
* @author Lien
*/
public class Configs {
      
      /**  设备名字符显示长度. */
      public staticfinal int DEVICE_NAME_KEEP_LENGTH = 8;
      
      /**  设定是否为debug版本. */
      public staticfinal boolean DEBUG = true;
      
      /**  设定AppID,参数为机智云官网中查看产品信息得到的AppID. */
      public staticfinal String APPID = "a932138570e24574890c4032d20bb319";
      
      /**  指定该app对应设备的product_key,如果设定了过滤,会过滤出该peoduct_key对应的设备. */
      public staticfinal String PRODUCT_KEY = "8a2d232e461e4de1843b7b827debe57d";
      
      /**  设定日志打印级别. */
      public staticfinal XPGWifiLogLevel LOG_LEVEL = XPGWifiLogLevel.XPGWifiLogLevelAll;
      
      /**  日志保存文件名. */
      public staticfinal String LOG_FILE_NAME = "BassApp.log";
      
      /** 产品密钥 */
      public staticfinal String APP_SECRET = "532a1c88bb7f4dc2a13381791a666890";

}
把自己的APPID  PRODUCT_KEY  APP_SECRET输入到里面
这三个信息在机智云后台上找得到
http://site.gizwits.com/zh-cn/developer/product 点机智云硬件接入,添加新应用

这样生成的APP,就可以连接到自己的硬件开发板上了。

COMDEBUGpng.png (42.71 KB, 下载次数: 380)

COMDEBUGpng.png

微信截图_20160729115219.png (57.7 KB, 下载次数: 365)

微信截图_20160729115219.png

微信截图_20160729141001.png (42.24 KB, 下载次数: 356)

微信截图_20160729141001.png

微信截图_20160729153815.png (41.92 KB, 下载次数: 372)

微信截图_20160729153815.png

20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
沙发
 楼主| 发表于 2016-7-29 16:24:07 | 只看该作者
第五步:为Eclipse安装ADT插件
前面我们已经配置好了java的开发环境,安装了开发AndroidIDE,下载安装了Android SDK,但是Eclipse还没有和Android SDK进行关联,也就是它们现在是互相独立的,就好比**和**分开了。为了使得Android应用的创建,运行和调试更加方便快捷,Android的开发团队专门针对Eclipse IDE定制了一个插件:Android Development ToolsADT)。
下面是在线安装ADT的方法:
启动Eclipse,点击 Help菜单 -> Install New Software… ?,点击弹出对话框中的Add… 按钮。



然后在弹出的对话框中的Location中输入:http://dl-ssl.google.com/android/eclipse/,Name可以输入ADT,点击“OK”按钮


安装好后会要求你重启EclipseEclipse会根据目录的位置智能地和它相同目录下Android sdk进行关联,如果你还没有通过sdk manager工具安装Android任何版本的的sdk,它会提醒立刻安装它们。

在弹出的对话框选择要安装的工具,然后下一步就可以了



如果Eclipse没有自动关联Android sdk的安装目录,那么你可以在打开的Eclipse选择 Window -> Preferences ,在弹出面板中就会看到Android设置项,填上安装的SDK路径,则会出现刚才在SDK中安装的各平台包,按OK完成配置。



到这里,我们在windows上的Android上的开发环境搭建就完成了,这时候,你用EclipseFile——New——Project...新建一个项目的时候,就会看到建立Android项目的选项了。

//-----------------------------------------------------------------
上面安装方法都是从网上找的。这里方便学习大家我转进来。


20

主题

112

帖子

1626

积分

金牌会员

Rank: 6Rank: 6

积分
1626
楼主
 楼主| 发表于 2016-7-29 16:19:45 | 只看该作者
第四步:下载安装Android SDK
配置了JDK变量环境,安装好了Eclipse,这个时候如果只是开发普通的JAVA应用程序,那么Java的开发环境已经准备好了。我们要通过Eclipse来开发Android应用程序,那么我们需要下载Android SDK(Software Development Kit)和在Eclipse安装ADT插件,这个插件能让Eclipse和Android SDK关联起来。
Android SDK提供了开发Android应用程序所需的API库和构建、测试和调试Android应用程序所需的开发工具。
打开http://developer.android.com/sdk/index.html,我们发现google提供了集成了Eclipse的Android Developer Tools,因为我们这次是已经下载了Eclipse,所以我们选择单独下载Android SDK。

下载后双击安装,指定Android SDK的安装目录,为了方便使用Android SDK包含的开发工具,我们在系统环境变量中的Path设置Android SDK的安装目录下的tools目录。
Android SDK的安装目录下,双击“SDK Manager.exe”,打开Android SDK ManagerAndroid SDK Manage负责下载或更新不同版本的SDK包,我们看到默认安装的Android SDK Manager只安装了一个版本的sdk tools

打开Android SDK Manager,它会获取可安装的sdk版本,但是国内有墙,有时候会出现获取失败的情况。


//这里要注意了,正常的网络我们是不能下载的,这里要翻墙才能正常下载。
我们可以下载 离线包安装。没有安装的是不能编译的。这一步是必须要做的,文件蛮大。刚开始我没有怎么理解,网上下载了一个几十MB的,根本没有。
Android SDK Manage上的https请求改成http请求
打开Android SDK Manager,在Tools下的 Options 里面,有一项 Force https://..sources to be fetched using http://... 将这一项勾选上,就可以了。


再打开Android SDK Manager.exe,正常情况下就可以下载Android的各个版本的sdk了。你只需要选择想要安装或更新的安装包安装即可。这里是比较耗时的过程,还会出现下载失败的情况,失败的安装包只需要重新选择后再安装就可以了。




如果通过更改DNS也无法下载Android SDK,还有两个方法,第一个是自备梯子FQ,第二个是从这个网站上下载,下载的地址是:http://www.androiddevtools.cn/
//----------------------------------------------------



您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

加入Q群 返回顶部

版权与免责声明 © 2006-2024 Gizwits IoT Technology Co., Ltd. ( 粤ICP备11090211号 )

快速回复 返回顶部 返回列表