紅外線收發器 - Part 2

總覽

本文件是 LinkIt 7687 HDK 紅外線收發器教學的第二部.您將建立一個 IR 發送器,連接聯發科技雲服務 (MCS) 和使用 HTTP 協議來發送 IR 指令和數據.除此之外,您還將學習如何操作無線韌體升級 (FOTA)。

簡介

本教學的第二部將會介紹以下內容:

  • 如何將紅外線發送器所使用的硬體組合起來。
  • 如何使 LinkIt 7687 HDK 以無線 Station 模式操作。
  • 如何將紅外線發送器連接 MCS, 和建立 data channel 以發送指令。
  • 如何建立 MCS 和紅外線發送器的介面軟體並使用 IRTX Hardware Abstraction Layer (HAL) API 來執行數據通訊。
  • 如何使用 MCS 來執行無線韌體升級 (FOTA)。

您可以在以下按鈕下載本教學的完整原始碼。. 

 

開始之前

若您之前不曾使用 7687 HDK 來開發專案,請先安裝 LinkIt SDK v3.3.1 並進行開發環境設定,相關細節請參考 LinkIt 開發平台 for RTOS 入門手冊

啟用您的聯發科技雲服務帳號

您可以通過聯發科技創意實驗室網站註冊來啟用免費的聯發科技雲服務以建立您自己的裝置和應用。註冊後您還可以獲得硬體參考設計資源和參與開發者論壇社群.

安卓裝置

此教學支援安卓 4.0 或以上的智慧手機和平板電腦. 若採用這些裝置請先連接好無線網路或電信網路, 但這些裝置不是必要的.

硬體設置

本節將介紹所需要的硬體組件。

必備

除了LinkIt 7687 HDK (由品佳集團提供) 之外, 您還需要準備以下組件。 

組件說明來源
線 (Cable) Micro-USB cable 
IR 發射器Grove 紅外線發射器Grove Infrared Emitter
Grove Base Shield 擴充底板Seeed Bazaar

組件圖顯示如下: 

Listed components

您也可以使用一個基本 麵包板 來代替 Grove Base Shield。

組合組件


以下步驟介紹如何把此教學專案硬體組合起來。
  1. 將 Grove base sheild 架在 LinkIt 7687 開發板上。
  2. 將 IR emitter 連接到 Grove Base Shield 的 D5 埠。 D5 對應到 LinkIt 7687 HDK 的 GPIO 33

Final hardware setup

這樣就完成了 IR transmitter 硬體組合。

設定 MCS

在這個專案中,你將使用MCS發送命令或執行 FOTA 功能。 MCS 設置將分成兩部分描述:首先您將建立一個新的原型器 (紅外線發射器),然後一個新裝置以與您的真實硬體進行交互 。

MCS 應用開發步驟

本節是依照一般 MCS 應用開發基本步驟介紹.請啟用您的 MCS 帳號

建立一個新的紅外線發射原型器

原型器就像是一個實際硬件設置的藍圖。所述原型器是由一個或多個 data channel 包括顯示器,控制器等所構成, 和由 <b> Data channel name , <b>Data channel id  和 <b>Data type  參數所定義.您可以在MCS 的 關鍵概念 了解各種數據類型和原型的整體結構。

本專案的 IR transmitter 原型僅採用了一個 data channel 來發送命令。 本節說明如何建立和設定此原型器。

  1. 由聯發科技創意實驗室帳號登入 MCS。. 
    Signing into MCS with a labs account
  2. 點擊 Development 連結, 選擇 Prototype,並點擊 Create 如下圖: 
    Create a new prototype

  3. 輸入原型名稱,版本,並選擇硬體平台,產業,之後點擊儲存按鈕。 

    Note

    () 代表必填。

  4. 點擊您剛建立的原型內的詳情按鈕 Detail, 如下圖: 
    Click Details to view the prototype

  5. 點擊 Exit 以跳過初始程序, 如下圖:
    Bypassing the data channel initiation instructions

增加 data channel

您將在這節建立 data channel。

  1. 點選 Data channel 之後點選新增按鈕 Add。如下圖:
    Add a data channel to the prototype
  2. 選擇資料通道型態 Controller。例如控制器,顯示器,或是綜合型控制顯示器。之後點選新增按鈕 Add。如下圖: 
    Data channel types
  3. 輸入資料通道名稱,資料通道 ID,描述,並選擇資料型態。 如下圖, 然後點擊儲存按鈕 Save 。
    Data channel details for the controller
    您的資料通道已建立。您可以在資料通道名稱下方查看您的資料通道 Id 。您將會在未來呼叫測試裝置取得資料或是下達指令時,需要此資訊。 本專案將通過 MCS 來控制一個電視機。
     
  4. 將 Data type 定義為遊戲鍵盤 GamePad 以啟用按鈕向上,下,左,右,按鈕 A,按鈕 B。 欲了解各種數據類型和原型的整體結構請查看MCS 的關鍵概念
    這六種按鈕將對應數字1至6 , 列如下表。 當按下遊戲鍵盤時,IR 發射器會根據對應值發送不同 IR 指令。  

    Channel name: controller_id

    Game Pad 按鈕電視功能
    1 上 (Up)增加音量
    2下 (Down)減少音量
    3左 (Left)轉台減少
    4右 (Right)轉台增加
    5按鈕 A電視開/關
    6按鈕 B靜音

您現在已建立好一個 IR 發射控制原型器。

建立新裝置

在 MCS 裡的每個原型器都是以特定硬體平台所定義。本教學所採用的硬體平台是 LinkIt 7687 HDK。您將建立一個對應到 IR 發射器的新裝置原型器。

IR 發射原型器是通過採取以下步驟對應到該新裝置(實際硬體)。

  1. 點擊 Development 然後點選 IR transmitter Prototype detail。
  2. 點擊Create test device 以配置新裝置。 
    Creating a test device for the IR transmitter prototype
  3. 提供 Device name, 如下範例, 然後點擊 Create。 
    Test device configuration
  4. 點擊 Go to detail , 以查看裝置資料, 如下圖。 
    Confirmation a device for the IR transmitter prototype has been created

請務必保存  DeviceID  和  DeviceKey  或者將它們編入您的專案原始碼以啟動連接功能以及呼叫 API。

Device details for the IR transmitter device

您已建立好與 IR 發射器對應的新裝置原型器了。 接下來您將建立軟體。

軟體實作

此一節說明如何使用 IRTX HAL API 並通過 IR 發射遙控器發送命令, Wi-Fi API 來設定 Station 模式, HTTP client API 來連接 MCS 和 C 語言原始碼總概觀。

開始之前, 請確認您已熟悉如何在某個開發環境下建立專案, 若還沒有, 請參考 聯發科技 LinkIt™ 開發平台 for RTOS 入門手冊

請由 GitHub下載原始碼, 解壓縮檔案內容並複製到 HDK 的範例專案目錄, 例如: MediaTek LinkIt SDK\3.3.1\project\mt7687_hdk\apps

此專案完整原始碼保存在 GitHub repository

專案概觀

此專案將上傳並執行一個 “main.c” 到 LinkIt 7687 HDK, 以建立能控制您的電視機的紅外線發射遙控器。.

您將實作以下軟體:

  • 為 HAL IR, Wi-Fi 和 MCS 連接增加支援庫。
  • 設定 HTTP 協議和配置裝置 。
  • 連接 MCS 到電腦或手機。
  • 初始化 IR transmitter 根據 MCS 指令。

以及執行以下文檔:

  • main.c - 應用入點。
  • mcs.c - 提供 HTTP 協議並使用 deviceId and deviceKey 來連接 MCS。
  • mcs.h - MCS 頭文件( 需要修改)。
  • ir_data.h - IR PWD data 頭文件( 需要修改)。
  • sta_network.c - Wi-Fi 配置設定( 需要修改)。

增加支援庫

此專案使用 IRTX HAL API 來發送 IR data。 欲了解更多關於使用該 APIs, 請於 API 參考查看 HAL IRTX API 章節 

在 main.c 中所需要的支援庫頭文件列表如下:

#include <stdint.h>
#include <stdio.h>
#include <string.h>
 
#include "FreeRTOS.h"
#include "task.h"
#include "os.h"
#include "sys_init.h"
#include "wifi_api.h"
#include "sta_network.h"
 
#include "sntp.h"
#include "syslog.h"
#include "hal_rtc.h"
 
#include "mcs.h"
/* hal includes */
#include "hal.h"
/*hal pinmux define*/
#include "hal_pinmux_define.h"
 
/* Header file for IR PWD Data that needs to be emitted/broadcast */
#include "ir_data.h"

定義 static 變數

定義 main() 函數裡使用的 static 變數, 如下:

 

#define MAX_STRING_SIZE 1024
/*  Task handle for mcs_listener, ir_listener   */
static TaskHandle_t mcs_iremitter_task_handle = NULL;

main() 函式

main 程式是應用的入點. 在 main() 函數裡您將初始化裝置以 Wi-Fi Station 模式連接 MCS, 步驟說明如下:

  1. 呼叫 system_init() 函數以初始化硬體系統。
  2. 呼叫 sta_network_init() 函數以將HDK 設定為 station 模式並連接至 Wi-Fi router 。
  3. 建立一個 task 以連接 MCS, 並由 IR 發射器 的 IR TX 模組取得指令以控制電視機。
int main(void)
{
    system_init();
      
    sta_network_init();
     
    xTaskCreate(mcs_iremitter_task, "mcs", 2048, NULL, 1 , &mcs_iremitter_task_handle);
 
    vTaskStartScheduler();
    for ( ;; );
}

配置網路設定

依照您的 Wi-Fi 路由器 設定來修改 sta_network.c 以設定 WIFI_SSID 和 WIFI_PASSWORD

建立 task (mcs_iremitter_task())

實行 task 函式 mcs_iremitter_task() 將包含執行以下函式:

  • 等待 IR transmitter 成功的連接網路 - sta_network_ready()
  • 使用一個 socket 來連接 MCS 指令伺服器- mcs_connect()
  • 等待socket 收到的數據 - mcs_waitfor_mcsdata()
  • 解析緩衝器裡的數據和辯認指令 - mcs_identify_command()
  • 初始化和發送數據 - send_ir_data()
void mcs_iremitter_task(void *args)
{   int ret;
    LOG_I(common, "--- mcs_listener_task begin ---\r\n");
    for (;;) {
        
        /*  Network must be ready & get connected with 7687 before MCS socket connection */
        sta_network_ready();
         
         /* Start MCS connection and keep receiving data over socket */
        ret = mcs_connect();
        if(ret < 0)
        {
            LOG_I(common, "Error: Could not connect to MCS Server.");
        }
        else
        {
            char dataBuffer[MAX_STRING_SIZE] = {0};
            int ret,command;
            while(1)
            {
                LOG_I(common, "While loop --> waiting for data");
                ret = mcs_waitfor_mcsdata(dataBuffer);
                if(ret < 0)
                {
                    LOG_I(common, "Error: Discard the received buffer.");
                }
                else
                {
                    command = mcs_identify_command(dataBuffer);
                    if(command > 0)
                    {
                        send_ir_data(command);
                    }
                    else
                    {
                        LOG_I(common, "Undefined MCS Command.");
                    }
                }
            }
          }
         
    }
    //vTaskDelete(NULL);
}

配置裝置設定

在 mcs.h 頭文件裡應提供device ID 和 device key 資料。 該 device ID 和 device key 資料是在建立 IR transmitter 原型時產生並用來辨認硬體的。 請查看 建立新裝置 以了解細節。在 mcs.h 文件裡 device ID 和 device key 是常數, 您可以在下面範例中於引號中進行修改:

/* MCS Device Id and Devicekey 
   Modify these values to your deviceId and deviceKey
*/
#define DEFAULT_DEVICEKEY "yourDeviceKey"
#define DEFAULT_DEVICEID "yourDeviceID"

定義遊戲鍵盤的 controller ID:

/* MCS Data controller channel id you have given in the MCS cloud service for gamepad 
   Modify the "controller_id" string, if you have given different controller channel Id in MCS.
*/
#define IRDA_CHANNEL_CONTROLLER "controller_id"

賦值給 controller:

/* MCS Data controller channel values, you have given in the MCS gamepad controller.
   Modify these values (1-6) if you have given different values for the game pad controllers.
 */
 
#define IR_COMMAND_VOLUMEINC  1
#define IR_COMMAND_VOLUMEDEC  2
#define IR_COMMAND_CHANNELINC 3
#define IR_COMMAND_CHANNELDEC 4
#define IR_COMMAND_ONOFF      5
#define IR_COMMAND_MUTE       6

MCS 連接設定

與 MCS 建立通信和接收數據有兩種方法,您可以選擇建立一個 TCP 連接,或者建立 MQTT 連接來與 MCS 伺服務器進行通信。通過 MQTT 連接您能從手機或者 MCS 控制台發送命令到裝置, 也能接收命令,這是雙向通信模式。 TCP 則是單向通信, 支援由 MCS 控制台發送命令到裝置。欲瞭解更多關於 MCS TCP and MQTT 連接功能請點擊這裡

為建立 TCP 連接,裝置需要先發送一個 REST API GET 請求來得取 MCS 伺服器的 IP 地址。MCS 則將與伺服器 IP 地址和端口資料回應給裝置。一旦裝置獲取該資料後就應該發送心跳信號回 MCS 伺服務器以被識別和進行連接,該裝置還將以每120 秒持續發送心跳以保持連接服務,避免伺服務器與裝置斷線。一旦TCP 連接已建立成功, 您的裝置就能接收MCS 伺服器指令了。HTTP GET API 的端點網址是: http://api.mediatek.com/mcs/v2/devices/ 。 欲了解更多關於 MCS 連接API 詳細信息,請點擊這裡

發送 HTTP GET 請求以獲取 IP address

MCS 伺服器的 HTTP GET 請求 URL 位置在  https://api.mediatek.com/mcs/v2/devices/:deviceId/connections  。 deviceId 是您在 MCS 控制台設定原型的 deviceId , 請查看 建立新裝置 以了解細節。然後 HTTP 回應資料將被解析以辨認 IP address 來完成裝置以及MCS 之間的 TCP 連接。

該 IP address 將保存在一個全域變數 MCS_TCPIP_ADDRESS

static int getmcsIP()
{
    HTTPCLIENT_RESULT ret = HTTPCLIENT_ERROR_CONN;
    char mcscnnectionURL[70] = {0};
      
    construct_mcs_httpurl(&mcscnnectionURL);
    printf("======= URL : %s ======== \n", mcscnnectionURL);  
  
    ret = make_mcs_http_connection(mcscnnectionURL);
    if(ret != HTTPCLIENT_OK)
    {
        printf(" httpclient_connect FAILED: Error code:%d ",ret);
        return ret;
    }
      
    char *pDataBuffer = NULL;
    pDataBuffer = pvPortMalloc(BUF_SIZE);
    if (pDataBuffer == NULL) {
        return ret;
    }
    pDataBuffer[0] = '\0';
      
    ret = send_httprequestto_mcs(mcscnnectionURL,pDataBuffer);
      
    if(ret == HTTPCLIENT_OK)
    {
            fill_ipaddr_from_response(pDataBuffer);
    }
    else
    {
         printf("Http Request/Response FAILED.");
    }
      
    vPortFree(pDataBuffer);
    httpclient_close(&client, HTTP_PORT);
    return ret;
}
construct_mcs_httpurl()  將使用代碼裡的  deviceId  產生 URL。  make_mcs_http_connection()  函式將與MCS 伺服器產生 HTTP 連接。 它將以 deviceKey  為頭文件發送 HTTP 請求並等待回應。
int make_mcs_http_connection(char* pMCSConnectionURL)
{
    int ret = HTTPCLIENT_ERROR_CONN;
    ret = httpclient_connect(&client, pMCSConnectionURL, HTTP_PORT);  
    return ret;
}
  
int send_httprequestto_mcs(char* pMCScnnectionURL,char* pBuffer)
{
  int ret = HTTPCLIENT_ERROR_CONN ;
  httpclient_data_t client_data = {0};
    
  /* Set header */
  char header[40] = {0};
  strcat(header, "deviceKey:");
  strcat(header, device_key);
  strcat(header, "\r\n");
    
  client_data.response_buf     = pBuffer;
  client_data.response_buf_len = BUF_SIZE;
  httpclient_set_custom_header(&client, header);
  
  ret = httpclient_send_request(&client, pMCScnnectionURL, HTTPCLIENT_GET, &client_data);
  if (ret < 0)
  {
    return ret;
  }
  
    ret = httpclient_recv_response(&client, &client_data);
    if (ret < 0) {
        return ret;
    }
  
    printf("Response content:%s\n", client_data.response_buf);
    if (200 == httpclient_get_response_code(&client))
    {
        ret = HTTPCLIENT_OK;
    }
    else
    {
        ret = HTTPCLIENT_ERROR_CONN;
    }
    
  return ret;  
}


HTTP 回應將被解析以取得 IP address。

void fill_ipaddr_from_response(char* pResponseBuffer)
{
  char split_buf[MAX_STRING_SIZE] = {0};
  char *arr[2];
  char *del = ",";
  strcpy(split_buf, pResponseBuffer);
  mcs_split(arr, split_buf, del);
  strcpy(MCS_TCPIP_ADDRESS,arr[0]);
}

MCS TCP 連接

一旦與 MCS伺服器 IP address 建立成 HTTP 通訊, 您將建立一個 socket connection 來接收指令。 您可以使用lwip 功能來建立 socket 然後通過 IP address 來與 MCS 伺服器連接。

lint mcs_socket_connect()
{  
    int ret;
    struct sockaddr_in addr;
    os_memset(&addr, 0, sizeof(addr));
    addr.sin_len = sizeof(addr);
    addr.sin_family = AF_INET;
    addr.sin_port = htons(SOCK_TCP_SRV_PORT);
    /* IP address of the MCS command server received from HTTP response */
    addr.sin_addr.s_addr = inet_addr(MCS_TCPIP_ADDRESS);
  
    /* create the socket */
    s = lwip_socket(AF_INET, SOCK_STREAM, 0);
    if (s < 0)
    {
        LOG_I(common, "tcp client create fail 0\n");
        return -1;
    }
    ret = lwip_connect(s, (struct sockaddr *) &addr, sizeof(addr));
    if (ret < 0)
    {
        lwip_close(s);
        LOG_I(common, "tcp client connect fail 1\n");
        return -1;
    }
    return 0;
}

通過建立好的 socket 來持續的發送心跳以保持裝置和 MCS 伺服器之間的連接。 您可以使用一個記時器函式  tcpTimerCallback()  來達成此目標。

/* Create a timer and keep sending heartbeat message to MCS server to keep the connection alive  */
heartbeat_timer = xTimerCreate("HeartbeatMsgTimer", (30 * 1000 / portTICK_RATE_MS), pdTRUE, (void *) 0, tcpTimerCallback);
xTimerStart(heartbeat_timer, 0);
send_heartbeatmsg();

心跳資料包含有  deviceId ,  deviceKey  和  timestamp 。 Timestamp 是 UNIX time 格式。 若要跳過只需要將 timestamp field 指定 0 就可以了。
void tcpTimerCallback(TimerHandle_t pxTimer)
{
 /* Keep sending heartbeat message to keep the connection alive */
  send_heartbeatmsg();
}
/* Send heartbeat message to the MCS command server though the socket */int send_heartbeatmsg()
{
 int ret;
 char cmd_buf [50] = {0};
 /* Format of the heartbeat message is : "deviceid,devicekey" */
 strcat(cmd_buf, device_id);
 strcat(cmd_buf, ",");
 strcat(cmd_buf, device_key);
 strcat(cmd_buf, ",0");
 ret = lwip_write(s, cmd_buf, sizeof(cmd_buf));
 return ret;
}

接收與解析 MCS 數據

通過 MCS socket 接收數據

當 MCS socket 連接已建立完成, main() 函式將呼叫 mcs_waitfor_mcsdata() 函式以等待數據,呼叫 mcs_identify_command()以辯試指令和 呼叫 lwip_recv() 函式以接收數據。

int mcs_waitfor_mcsdata(char* pBuffer)
{
  int rcv_len, rlen;   
  char rcv_buf[MAX_STRING_SIZE] = {0};
    
  rcv_len = 0;
  LOG_I(common, "MCS tcp-client waiting for data...");
  rlen = lwip_recv(s, &rcv_buf[rcv_len], sizeof(rcv_buf) - 1 - rcv_len, 0);
  rcv_len += rlen;
  if (0 == rcv_len)
  {
      LOG_I(common, "MCS tcp-client disconnected !");
      return -1;
  }
  strcpy(pBuffer,rcv_buf);
  return 0;
}

解析 MCS 數據

呼叫 mcs_identify_command 函式以解析數據。

遊戲鍵盤指令的格式是:

deviceId,deviceKey,timestamp,dataChnId,{up/down/right/left/A/B value| press(1) or release(0)}

數據解析程序是以逗號作為數據分隔和使用函式 mcs_split_n() 將數據複製到一個陣列, 每個陣列元素包含 timestamp, data channel ID 和 data 的訪問是由陣列索引,例如 TIMESTAMP_INDEX (2), CHANNEL_INDEX (3), CHANNEL_INDEX (4) 進行。

Data channel 名稱會與 IRDA_CHANNEL_CONTROLLER (controller_id) 比較以確定數據是從 MCS 控制台裡的 IR data channel 建立的。 最後,此函式將返回1 到 6之間數字為通道指令,請參閱裝置設定。

int mcs_identify_command(char *arg)
{
    /* Split received string */
    char *mcs_split_buffer[MAX_SPLIT] = {0};
      
    /*Check whether the command is to do FOTA. If yes do the FOTA, otherwise identify the IR command */
    if( checkforFOTA(arg))
    {
        return 0;
    }
      
    mcs_split_n(mcs_split_buffer, arg, MCS_DELIMITER, MAX_SPLIT);
    if (mcs_split_buffer[TIMESTAMP_INDEX] == NULL) {
        LOG_I(common, "mcs_tcp_init_callback(): timestamp must not be null, format error.\r\n");
        return -1;
    }
    if (strcmp(mcs_split_buffer[TIMESTAMP_INDEX], MCS_HEARTBEAT_TIMESTAMP) != 0) {
        if (mcs_split_buffer[VALUE_INDEX] == NULL) {
            LOG_I(common, "mcs_tcp_init_callback(): value must not be null when packet is not a heatbeat packet.\r\n");
             return -1;
        }
        if (strcmp(mcs_split_buffer[CHANNEL_INDEX], IRDA_CHANNEL_CONTROLLER) == 0) {          
            uint32_t code;
            sscanf(mcs_split_buffer[VALUE_INDEX], "%u", &code);
            LOG_I(common, "\r\n Received Command Code = %d",code);
            return code;
        }  
        else {
            LOG_I(common, "Unknown channel: %s Switches on/on++", mcs_split_buffer[CHANNEL_INDEX]);
        }
    } else {
        LOG_I(common, "MCS Heartbeat packet\r\n");
    }
    return -1;
}

發送 IR 數據

本教學專案使用 HAL IRTX API 來發送數據。 請參考 HAL IRTX API 以了解更多使用細節。

LinkIt 7687 HDK 支援四種 IR 編碼模式:

  • NEC 模式。 NEC 編碼格式是IR 協議普遍常用的, 能直接由硬體發送。
  • RC5 模式。 Philips RC5 IR 發射協議是使用 Manchester 編碼 格式。 能直接由硬體發送。
  • RC6 模式。 與 RC-5 類似。 能直接由硬體發送。
  • Pulse Width Detection (PWD) 模式。 能以IR 發射任何代碼, 代碼大小則能由波長度而判斷。

此專案的 IR transmitter 使用 PWD 模式來發送 IR 數據。

send_ir_data() 函式初始化 GPIO 33 也就是 IRTX 埠, 配置 IRTX, 發送 IR 數據然後取消初始化 IRTX GPIO 33。

void send_ir_data(int command)
    {
        /* Set frequency to 40Khz*/
        uint16_t frequency = 40;
        /* Set duty cycle to 25%*/
        uint8_t duty_cycle = 25;
     
        hal_gpio_init(HAL_GPIO_33);
        /* Call hal_pinmux_set_function to set GPIO pinmux. */
        hal_pinmux_set_function(HAL_GPIO_33, HAL_GPIO_33_IR_TX);    
        hal_irtx_configure_pulse_data_carrier(frequency, duty_cycle);
        send_ir_tv_data(command);  
        hal_gpio_deinit(HAL_GPIO_33);   
        log_hal_info("\n Sending IR data completed.");
    }

呼叫函式 send_ir_tv_data() 以從 GPIO 埠 33 連接的 IR emitter 發送 IR 指令。 這些指令包含 開關 ON/OFF, 靜音, 音量增加或減少, 轉台上或下。 其中指令之一將會發送到 IR TX 模組。

呼叫 HAL IRTX API hal_irtx_send_pulse_data(base_period, volumeInc, data_number) 以發送 IR 指令。 該函式是在 mcs.h 頭文件定義。

uint8_t base_period = 80;
result = hal_irtx_send_pulse_data(base_period, PWDIRDATA_SWITCHONOFF, PWDIRDATA_SWITCHONOFF_LENGTH);

專案裡的 inc 文件夾的 ir_data.h 頭文件定義了IR 數據長度。 在 PuTTY 控制台輸出的 IR 數據陣列是存儲在頭文件裡。

IR 數據 PWDIRDATA_SWITCHONOFF 和 PWDIRDATA_SWITCHONOFF_LENGTH 也是在 ir_data.h 頭文件定義的。

// Switch Off/On IR PWD data and length
#define PWDIRDATA_SWITCHONOFF_LENGTH 67
uint8_t PWDIRDATA_SWITCHONOFF[PWDIRDATA_SWITCHONOFF_LENGTH] =
{
        0x72,0x70,0x0f,0x29,0x0f,0x29,0x0e,0x29,0x0e,0x0d,0x0f,0x0d,0x0e,0x0d,0x0e,0x0d,
        0x0e,0x0d,0x0f,0x29,0x0f,0x29,0x0e,0x29,0x0f,0x0c,0x0e,0x0d,0x0e,0x0d,0x0f,0x0d,
        0x0e,0x0d,0x0f,0x0c,0x0f,0x29,0x0e,0x0d,0x0f,0x0c,0x0f,0x0d,0x0e,0x0d,0x0e,0x0d,
        0x0e,0x0d,0x0f,0x29,0x0e,0x0d,0x0f,0x29,0x0f,0x29,0x0e,0x2a,0x0f,0x29,0x0e,0x29,
        0x0e,0x29,0x0f
};

您能在 GitHub 找到完整原始碼。

無線韌體升級 (FOTA)

MCS 指令伺服器能用來執行無線韌體升級 (FOTA) 或者通過MCS 控制台建立的遊戲鍵盤發送 IR 指令。

一旦裝置連接上MCS 伺服器後, 您就能上傳 LinkIt 7687 HDK 韌體到 MCS 控制台, 請依照 韌體管理 教學以了解上傳步驟和配置指令來使用 FOTA。 從 MCS 使用 FOTA 的格式是如下:

deviceId,deviceKey,timestamp,FOTA,version,MD5,URL 
mcs.c  原始碼裡有 FOTA 實行函式, 例如  checkforFOTA() , 以檢查數據是否要實行 FOTA, 若要, 就會發送 HTTP POST 到 MCS 伺服器以更新 FOTA 狀態並呼叫 FOTA API  fota_download_by_http()  以執行韌體更新。 您可以在  FOTA API Reference  找到更多關於FOTA 的細節。

int checkforFOTA(char* pBufferReceived)
{
    /* split the string of rcv_buffer */
    char split_buf[MAX_STRING_SIZE] = {0};
    strcpy(split_buf, pBufferReceived);
     
    char *arr[7];
    char *del = ",";
    mcs_split(arr, split_buf, del);
    /* Check whether the command message is to do FOTA */
    if (0 == strncmp(arr[3], "FOTA", 4)) 
    {
        LOG_I(common, "Command is for FOTA : fota url: %s\n", s);
         
        /* Make the FOTA URL from https to http */
        char *s = mcs_replace(arr[6], "https", "http");
        char data_buf [100] = {0};
         
        strcat(data_buf, "status");
        strcat(data_buf, ",,fotaing");
        /* Inform MCS about FOTA status */
        mcs_upload_datapoint(data_buf);
         
        LOG_I(common, "Starting FOTA....\n");
        /* Trigger FOTA with the http URL */
        fota_download_by_http(s);
         
        return 1;
    } 
    else
    {
        return 0;
    }
}

最後一步是執行  mcs_upload_datapoint()  函式以發送 .csv  格式的數據值到 MCS。 

int mcs_upload_datapoint(char *value)
{
    /* upload mcs datapoint */
    httpclient_t client = {0};
    char *buf = NULL;
 
    int ret = HTTPCLIENT_ERROR_CONN;
    httpclient_data_t client_data = {0};
    char *content_type = "text/csv";
 
 
    /* Set post_url */
    char post_url[70] = {0};
 
    if (strcmp(host, "com") == 0) {
        strcat(post_url, HTTPS_MTK_CLOUD_URL_COM);
    } else {
        strcat(post_url, HTTPS_MTK_CLOUD_URL_CN);
    }
 
    strcat(post_url, device_id);
    strcat(post_url, "/datapoints.csv");
 
    /* Set header */
    char header[40] = {0};
    strcat(header, "deviceKey:");
    strcat(header, device_key);
    strcat(header, "\r\n");
 
    printf("header: %s\n", header);
    printf("url: %s\n", post_url);
    printf("data: %s\n", value);
 
    buf = pvPortMalloc(BUF_SIZE);
    if (buf == NULL) {
        printf("buf malloc failed.\r\n");
        return ret;
    }
    buf[0] = '\0';
    ret = httpclient_connect(&client, post_url, HTTP_PORT);
 
    client_data.response_buf = buf;
    client_data.response_buf_len = BUF_SIZE;
    client_data.post_content_type = content_type;
    client_data.post_buf = value;
    client_data.post_buf_len = strlen(value);
     
    httpclient_set_custom_header(&client, header);
    ret = httpclient_send_request(&client, post_url, HTTPCLIENT_POST, &client_data);
    if (ret < 0) {
        return ret;
    }
    ret = httpclient_recv_response(&client, &client_data);
    if (ret < 0) {
        return ret;
    }
    printf("\n************************\n");
    printf("httpclient_test_keepalive post data every 5 sec, http status:%d, response data: %s\r\n", httpclient_get_response_code(&client), client_data.response_buf);
    printf("\n************************\n");
    vPortFree(buf);
    httpclient_close(&client, HTTP_PORT);
    return ret;
}

您已經成功的跑完 FOTA 程序了。

執行您的程式

本文件相關的程式碼皆可自行下載,並依照 LinkIt 7687 HDK 入門手冊的步驟進行程式的上傳與執行。 您可以使用SSH 和 telnet client, 列如 PuTTY 以在console 觀看output。

  1. 使用 PuTTY 來與硬體連接並按下 reset button。
  2. 使用一個遙控器, 指向電視機並按下任何按鈕 (可參考教學第一部)。
  3. 使用瀏覽器或者手機登入 MCS, 點選您的原型器然後選擇 “Test device” , 您將看見控制指令包含 開關 On/Off, 靜音, 音量增減, 等。
    MCS UI on an Android device
  4. 點選您要執行的控制動作然後觀察 PuTTY 控制台收到的指令。 最佳情況是電視機收到了該IR 指令並且執行了正確的動作。
    觀察 PuTTY 控制台。
    Message log example on PuTTY

結語

透過此教學,您學到如何在 LinkIt 7687 開發板上使用 IRTX HAL API , 以 PWD 模式發送 IR 資料並將資料展示於控制台。 您還學到使用 HTTP Client API 來連接 MCS 和建立 socket 並使用 lwip API 接收數據。欲瞭解更多關於 MediaTek LinkIt 7687 開發板的資訊,請參考 LinkIt development platform for RTOS 開發者指南