研究筆記 - LASS on LinkItOne Code Trace

最後編輯:2019-02-21 建立:2016-07-11 歷史紀錄

 

  • 2016/7/10 updated
  • git rev: 01e0e13
    Andrew其實我還沒有真實地在硬體上運作測試,僅稍微看了一下 code,所以如果有誤解或是寫錯的地方請指正(請直接下 comment),感謝!

    1. 前言

 

ANDREW我雖然一直有關注 LASS,但因為工作忙碌,所以一直沒有時間好好研究。直到現在 LASS 已經漸漸發展到一個稍具規模的專案了。這篇文章記錄我在颱風假時邊看邊研究的歷程。主要的重點放在了解程式怎麼運作、以及 "猜測" 背後的設計想法(畢竟工程師很不愛寫文件的 = =)。

 

1.1. 起手式

 

    資源

LASS 的分工算是很精細的,資源整理都做得很不錯。facebook 就是哈拉討論和活動發布。hackpad 上面整理很多文件、資源,以及正在進行中的專案。基本上 hackpad 看 「LASS - README」就夠了,它是一個不錯的入口頁面。

 

 

因為是 code trace,所以我會把重點放在 github。

 

1.2. github

 

LASS 的 github 名稱是 LinkItONEDevGroup,原因是第一版的 LASS,就是用 LinkItOne 做出來的。現在已經漸漸移植到不同種類的開發板了。目前 github (rev:01e0e13) 上面的資料夾如下:

 

  • LASS/
  • |-- 3dp # 各個專案的 3D 列印外殼檔,有 .stl 檔,有的甚至有安裝說明
  • |-- Companion-module # 其實我不知道這是哪個專案用的,裡面有 SSD1306 OLED 的 lib,
  • | 還有一支 python 寫的測試程式
  • |-- DataPresentation # 看起來像是把資料呈現在網頁的展示頁
  • |
  • |-- Device_Ameba # Realtek Ameba 的子專案,看起來有用到 Gemtek LoRa Module
  • |-- Device_ArduinoCrossFit # 不知道是什麼東西,但重點似乎是 PM2.5
  • |-- Device_ArduinoLike # 看起來像是要移植到 Arduino 的樣子?
  • |
  • |-- Device_LinkItOne # 老實說 LinkItOne 的主專案還是比較完整
  • | |-- Blynk * 可以透過 app UI 控制的東西吧?
  • | |-- Derivative * 位置安排的怪怪的,裡面有 "魚菜共生" (Aquaponics)
  • | |-- Example * Sensors 的驗證測試程式
  • | |-- LASS * 主程式
  • | `-- Libraries * 函示庫
  • | |-- AWSArduinoMediaTekLibrary.zip
  • | |-- Blynk_v0.3.3.zip
  • | |-- DHT_linkit.zip
  • | |-- Grove_Digital_Light_Sensor.zip
  • | |-- HP20x_dev.zip
  • | |-- HardwareLibrary.zip
  • | |-- PubSubClient.zip
  • | `-- arduino-sht.zip
  • |
  • |-- Device_LinkItSmart7688Duo # Smart7688Duo 的版本,裡面有 python 和 node.js 版本
  • |-- Device_Rpi # 目前沒東西 (其實我覺得純用 Pi 做比較辛苦)
  • |-- Doc # 專案介紹的投影片
  • |
  • |-- IASS # 由凌陽創新科技釋出的室內環境控制系統,蠻完整的。
  • | | 文件、程式碼在 github 上都整理得蠻好的
  • | |-- IASS_BASIC
  • | | |-- Devices # 他們訂了三個應用的場域,居家安全、機房、辦公室
  • | | |-- Docs # 文件蠻詳細的,主要以 Arduino UNO 為 based
  • | | |-- IASS_Server
  • | | |-- Sensors_support
  • | | `-- arch.gif # 這個看一下
  • | `-- README.md
  • |
  • |-- LASS4U # 室內環境檢測的子計畫,主要增加 CO2 的檢測
  • | 其實它應該算是個蠻完整的專案了(都生產了) 但是 github 上面沒什麼資源
  • |
  • |-- LASS_DB # 用 MongoDB 和 BSON 格式。README.md 看一下
  • |-- LICENSE
  • |-- QandA.txt
  • |-- README.md
  • |-- SensingOfRiceFields # 農業感測計畫
  • `-- WeatherBox # 農業感測計畫的子計畫: 用來偵測大氣氣候

 

1.3. github: Device_LinkItOne

 

我想最完整的概念和實作應該還是在 LinkItOne 的版本中。以這個專案當切入點應該不錯!

 

  • Device_LinkItOne
  • |-- Blynk
  • |-- Derivative
  • |-- Example
  • |-- LASS
  • `-- Libraries
  • |-- AWSArduinoMediaTekLibrary.zip
  • |-- Blynk_v0.3.3.zip
  • |-- DHT_linkit.zip
  • |-- Grove_Digital_Light_Sensor.zip
  • |-- HP20x_dev.zip
  • |-- HardwareLibrary.zip
  • |-- PubSubClient.zip
  • `-- arduino-sht.zip

 

1.4. Device_LinkItOne/Libraries

 

  • HardwareLibrary.zip (這命名實在是…其實是三軸加速度感應器: ADXL345)
  • PubSubClient.zip
    • 比較接近 pubsubclient v1.9.1, 2012/11/12 released。
    • 有一些修改,commit log 寫: remove “Icon” in the Zip and make it compatiable with MS Windows system
    • 修改的部分有:
      • unsigned int 改為 uint16_t
      • MQTT_KEEPALIVE 從 15 -> 120 (keepAlive interval in Seconds)
      • MQTT_MAX_PACKET_SIZE 從 128 -> 768 (Maximum packet size)
      • 因為 size 變化所做的調整 (PubSubClient.cpp)
  • arduino-sht.zip (支援 SHTC1, SHT3x 濕度感應器)
  • AWSArduinoMediaTekLibrary.zip (連接到 AWS 的 lib)
    • ithub: aws-sdk-arduino 可以下載到
    • 套件裡面就是 aws-sdk-arduino/src/common 以及 aws-sdk-arduino/src/mediatek 的綜合體。
      • 簡單的修改 AWSClient2.h 變數名稱
      • AmazonDynamoDBClient.cpp 中修改了 calss AttributeValue 的成員名稱 (我看不懂,跳過 XD)

.

  • aws-sdk-arduino
  • |-- LICENSE.txt
  • |-- NOTICE.txt
  • |-- README.md
  • |-- samples
  • | |-- EdisonSNSSample.ino
  • | |-- Edison_Maraca
  • | |-- GalileoSample.ino
  • | |-- MediaTek_Maraca_HTTPS
  • | |-- SparkGetItemSample.ino
  • | |-- SparkPutItemSample.ino
  • | `-- SparkSNSSample.ino
  • `-- src
  • |-- common #<= 在這裡!!
  • |-- edison
  • |-- galileo
  • |-- mediatek #<= 在這裡!!
  • `-- sparkcore

 

1.5. code trace tools

 

如果要在 Linux 上面 code trace 的話, vim 的 syntax plugin 可以裝。

 

  • " ++++++++++ for arduino +++++++++++++
  • autocmd! BufNewFile,BufRead *.ino setlocal ft=arduino
  • autocmd! BufNewFile,BufRead *.pde setlocal ft=arduino
  • ctags 指令: (重點是 --langmap 那個參數)
  • find . -type f -name ".[ch]" -o -name ".cpp" -o -name ".ino" -o -name ".pde" | sed -e ‘s/^/"/’ -e ‘s/$/"/’ | xargs /usr/bin/ctags -a --langmap=c++:.ino
  • $ vi LASS/LASS.ino # enjoy your ctags

 

 

    2. 主程式 LASS.ino

 

ANDREW2.1. Code Comment Info

 

裡面有些資訊,既然它寫很長,表示有詳細的說明先看吧:

 

    Board jumper setting:

  • SPI/SD => SPI
  • MS/UART => UART
  • USB/BAT => USB

 

    Default Output PIN:

  • ARDUINO_LED_PIN = 13
  • STORAGE_CHIP_SELECT_PIN = 10 (Reserved)

 

    Sensor Input PIN:

  • SOUND_SENSOR_PIN = A1
  • DUST_SENSOR_PIN = 8, cal
  • UV_SENSOR_PIN = A0
  • TEMP-HUMID_SENSOR_PIN = 2
  • BAROMETER_SENSOR_PIN -> I2C
  • LIGHT_SENSOR -> I2C

 

    Action Output PIN:

  • BUZZER_ALARM_PIN = 3

 

    Sensor position definition:

  • 0-9 (System sensor)
    • reserved for system sensor, should not be modified for individual application purpose.
  • 10-19 (User sensor)
    • user customization purpose, user can freely customize this area

Note: 這些註解現在還是這樣嗎?

 

    Default system sensor order:

  • 0: record_id
  • 1: battery level
  • 2: battery charging
  • 3: ground speed ( Km/hour )

 

    Default user sensor order:

  • 10: dust sensor
  • 11: UV sensor
  • 12: sound sensor

Note: 這些註解現在還是這樣嗎?

 

    Default user sensor order in APP-3 (MAPS):

  • 10: barometer sensor (high accuracy)
  • 11&12: temperature & humidity sensor pro
  • 13: digital light sensor

Note: 這些註解現在還是這樣嗎?

 

    Default Sensor Type:

  • -: void; 0-9: reserved for system sensor
  • A-Z: LASS default sensors
  • a-z: reserved for other sensors

Note: 這些註解現在還是這樣嗎?

 

  • -: unused
  • 0: record ID
  • 1: battery level
  • 2: battery charging
  • 3: ground speed
  • 4: wifi debug: reconnect count
  • d: dust sensor
  • u: UV sensor
  • s: sound sensor
  • b: barometer sensor (hPa)
  • t: temperature sensor (degree C)
  • h: humidity sensor (%)
  • l: light sensor (LUX)

 

    Optional sample sensor: (幾乎都是 seeedstudio 的 Grove 模組)

Note: 其實我不知道那個 AP1,..AP4 代表什麼意思

 

    Optional alarm:

 

2.2. configuration.h

 

第一步,先設定 WiFi SSID & PASSWD,預設使用 WPA

 

  • //LASS CONFIGURATION FILE
  • #include "Arduino.h"
  • //Step 1: How you Connect WIFI....Basic things.
  • //WIFI
  • //System default wifi setting: SSID=LASS, PASS=LASS123456, WIFI_AUTH=LWIFI_WPA
  • #define WIFI_SSID "LASS" // REPLACE: your network SSID (name)
  • #define WIFI_PASS "LASS123456" // REPLACE: your network password (use for WPA, or use as key for WEP)
  • #define WIFI_AUTH LWIFI_WPA //Default:LWIFI_WPA // choose from LWIFI_OPEN, LWIFI_WPA, or LWIFI_WEP.
  • //-----------------------------------------------------------

 

是否使用 Blynk。如果要使用還需要填入 blynk_auth ID

 

  • //Step 2:Do you use Blyak.If yes,fill info below.
  • //Blynk-IoT
  • #define BLYNK_ENABLE 0 // deafult(0) 0: If you don't need to support BLYNK, 1: support BLYNK
  • char blynk_auth[] = "yourBlynkID"; // REPLACE: your Blynk auto id
  • //-----------------------------------------------------------

 

設定 MQTT,主要是設定 DEVICE_ID

 

  • //Step 3:MQTT info
  • //MQTT-IoT
  • #define MQTT_PROXY_IP "gpssensor.ddns.net" // Current LASD server , dont change!
  • #define DEVICE_TYPE "LinkItONE" // since there is only one device LASS supported now,dont change!
  • #define DEVICE_ID "FT1_999" // REPLACE: The device ID you like, please start from LASD. Without this prefix, maybe it will be filter out.
  • #define MQTT_TOPIC_PREFIX "LASS/Test" // CAN REPLACE if you like //Dont Replace IF YOU ARE FIELD-TRY USER
  • #define PARTNER_ID "LASS-Partner1" // CAN REPLACE if you like

 

設定 GPS。設定 FAKE_GPS=1 可以使用假的 GPS 位置傳資料,位置定義於 gps_lat, gps_lon, gps_alt。

GPS_SIGNAL_NOCHECK: 我猜是要不要檢查 GPS 訊號正常才傳送?

 

  • //Step 4:GPS
  • //Do you want to use gps? 0:YES 1:FAKE GPS
  • #define FAKE_GPS 0 // FAKE_GPS : 0: default format with gps, 1: default format but gps is fix data, need to update GPS_FIX_INFOR
  • //NOTICE:If you choose 1 modify "FAKE" GPS location. Fill info below
  • const char gps_lat[]= "23.000000"; // device's gps latitude
  • const char gps_lon[]= "120.000000"; // device's gps longitude
  • const char gps_alt[]= "30.0"; // device's gps altitude
  • #define GPS_SIGNAL_NOCHECK 1 // 0: log or send only when GPS have signal, 1: always log and send even when GPS have no signal

 

LASS 設定。APP_ID 分為三種,system/public/provate,有不同的 base number

 

  • //NOTICE: for Field TRY-PM2.5 DONT CHANGE AFTER THIS LINE! --2015/11/09
  • //-----------------------------------------------------------
  • //Step 5:About LASS
  • #define APP_ID (APPTYPE_SYSTEM_BASE+1) // REPLACE: this is your unique application 0-255: system reserved, 256-32767: user public use, 32768-65536: private purpose
  • #define APPTYPE_SYSTEM_BASE 0
  • #define APPTYPE_PUBLIC_BASE 256
  • #define APPTYPE_PRIVATE_BASE 32768
  • #define SERIAL_BAUDRATE 115200
  • //NOTICE: You are ready to ROCK, NO MORE TO SETUP!!!!
  • //-----------------------------------------------------------

 

要不要發出警訊。包含蜂鳴器和做 MQTT callback

 

  • //For ADVANCED user ONLY
  • #define ALARM_ENABLE 0 // default(0) 0: disable alarm, 1: enable alarm
  • #if ALARM_ENABLE==1
  • #define BUZZER_ALARM_PIN 3
  • #endif

 

感測器設定

 

  • //----- USER SENSOR CONFIG -----
  • #define SENSOR_CNT 25 // REPLACE: the sensors count that publish to server.
  • #define SENSOR_STRING_MAX 300
  • #define SENSOR_ID_RECORDID 0
  • #define SENSOR_ID_BATTERYLEVEL 1
  • #define SENSOR_ID_BATTERYCHARGING 2 // battery is charging: (0) not charging, (1) charging
  • #define SENSOR_ID_GROUNDSPEED 3
  • #define SENSOR_ID_DEBUGWIFI 4

 

這應該是 Arduino 內建特殊功能用的 pin

 

  • //----- DEAFULT PIN DEFINE -----
  • enum pinConfig{
  • ARDUINO_LED_PIN = 13,
  • STORAGE_CHIP_SELECT_PIN = 10
  • };

 

這一大段是各個 "APP" 用的。第一個 #if 是 system 用的

 

  • //LASS's OPEN PM2.5 Field-TRY
  • #if APP_ID==(APPTYPE_SYSTEM_BASE+1)
  • #define USE_PM25_G3
  • //#define USE_PM25_A4
  • #define USE_DHT22 // not recommend for DHT series sensors
  • //#define USE_SHT31
  • #define SENSOR_ID_DUST 10
  • #define SENSOR_ID_TEMPERATURE 11
  • #define SENSOR_ID_HUMIDITY 12
  • #define SENSOR_ID_DUST10 13
  • #define SENSOR_ID_DUST_BLYNK 6
  • #define SENSOR_ID_TEMPERATURE_BLYNK 7
  • #define SENSOR_ID_HUMIDITY_BLYNK 8
  • #define SENSOR_ID_DUST10_BLYNK 9

 

後面 #elif 是各個使用者定義的 public 區塊

 

  • //LASS's start up project by wuloong
  • #elif APP_ID==(APPTYPE_PUBLIC_BASE+1)
  • #define SENSOR_ID_DUST 10
  • #define SENSOR_ID_UV 11
  • #define SENSOR_ID_SOUND 12
  • // in order to prevent blynk not support that many virtual gpio in the macro. we setup virtual GPIO in lower pin
  • #define SENSOR_ID_DUST_BLYNK 4
  • #define SENSOR_ID_UV_BLYNK 5
  • #define SENSOR_ID_SOUND_BLYNK 6
  • enum pinSensorConfig{
  • DUST_SENSOR_PIN = 8,
  • SOUND_SENSOR_PIN = A1,
  • UV_SENSOR_PIN = A0,
  • TEMP_HUMID_SENSOR_PIN = 2,
  • };
  • //LASS's PM2.5 project by RODODO-MINGWEI
  • #elif APP_ID==(APPTYPE_PUBLIC_BASE+2)
  • #define SENSOR_ID_DUST 10
  • #define SENSOR_ID_DUST10 13
  • #define SENSOR_ID_DUST_BLYNK 4
  • #define SENSOR_ID_DUST10_BLYNK 7
  • //LASS project by Academia Sinica-LJ
  • #elif APP_ID==(APPTYPE_PUBLIC_BASE+3)
  • #define SENSOR_ID_BAROMETER 10
  • #define SENSOR_ID_TEMPERATURE 11
  • #define SENSOR_ID_HUMIDITY 12
  • #define SENSOR_ID_LIGHT 13
  • // in order to prevent blynk not support that many virtual gpio in the macro. we setup virtual GPIO in lower pin
  • #define SENSOR_ID_BAROMETER_BLYNK 4
  • #define SENSOR_ID_TEMPERATURE_BLYNK 5
  • #define SENSOR_ID_HUMIDITY_BLYNK 6
  • #define SENSOR_ID_LIGHT_BLYNK 7
  • //#endif
  • //LASS project by Academia Sinica-LJ
  • #elif APP_ID==(APPTYPE_PUBLIC_BASE+4)
  • #define USE_PM25_G3
  • #define SENSOR_ID_BAROMETER 10
  • #define SENSOR_ID_TEMPERATURE 11
  • #define SENSOR_ID_HUMIDITY 12
  • #define SENSOR_ID_LIGHT 13
  • #define SENSOR_ID_DUST 14
  • #define SENSOR_ID_DUST10 15
  • // in order to prevent blynk not support that many virtual gpio in the macro. we setup virtual GPIO in lower pin
  • #define SENSOR_ID_BAROMETER_BLYNK 4
  • #define SENSOR_ID_TEMPERATURE_BLYNK 5
  • #define SENSOR_ID_HUMIDITY_BLYNK 6
  • #define SENSOR_ID_LIGHT_BLYNK 7
  • #define SENSOR_ID_DUST_BLYNK 8
  • #define SENSOR_ID_DUST10_BLYNK 9
  • //#endif
  • //LASS project by Air-1
  • #elif APP_ID==(APPTYPE_PUBLIC_BASE+12)
  • #error 請在此選擇你的感測器,選擇完請刪除此行。
  • #define USE_PM25_G3
  • //#define USE_PM25_A4
  • #define USE_DHT22
  • //#define USE_SHT31
  • #define SENSOR_ID_DUST 10
  • #define SENSOR_ID_TEMPERATURE 11
  • #define SENSOR_ID_HUMIDITY 12
  • #define SENSOR_ID_DUST10 13
  • #define SENSOR_ID_NH3 14
  • #define SENSOR_ID_CO 15
  • #define SENSOR_ID_NO2 16
  • #define SENSOR_ID_C3H8 17
  • #define SENSOR_ID_C4H10 18
  • #define SENSOR_ID_CH4 19
  • #define SENSOR_ID_H2 20
  • #define SENSOR_ID_C2H5OH 21
  • #define SENSOR_ID_DUST_BLYNK 6
  • #define SENSOR_ID_TEMPERATURE_BLYNK 7
  • #define SENSOR_ID_HUMIDITY_BLYNK 8
  • #define SENSOR_ID_DUST10_BLYNK 9
  • #endif

 

系統其它參數設定。很多,看 code 的時候回來查就好

 

  • //SYSTEM PARAMETERS
  • #define DELAY_SYS_EARLY_WAKEUP_MS 11
  • #define POLICY_ONLINE_ALWAYS 1
  • #define POLICY_ONLINE_LESS 2
  • #define POLICY_ONLINE_DEFAULT 0
  • #define POLICY_POWER_DONTCARE 0
  • #define POLICY_POWER_SAVE 1
  • #define POLICY_POWER_AUTO 2
  • #define LED_MODE_DEFAULT 0 // to show system status and behavior
  • #define LED_MODE_OFF 1 // To not disturbe the environment, never have LED on
  • #define ADJ_MODE_NORMAL 0 // default system behavior, no special adjustment
  • #define ADJ_MODE_FLY 1 // for fly mode, speed up sensing, less wifi check
  • #define SETTING_MODE_CODE // user setting from code
  • #define SETTING_MODE_FLASH // user setting from flash
  • #define SETTING_VERSION 2
  • #define PERIOD_SENSING_IDX 0
  • #define PERIOD_UPLOAD_IDX 1
  • #define PERIOD_WIFICHECK_IDX 2
  • #define POLICY_ONLINE POLICY_ONLINE_ALWAYS //1: POLICY_ONLINE_ALWAYS 2: POLICY_ONLINE_LESS
  • #define POLICY_POWER POLICY_POWER_DONTCARE //2: POLICY_POWER_AUTO(Auto power saving mode) 0: POLICY_POWER_DONTCARE 1: POLICY_POWER_SAVE
  • // policy auto check if not charging and battery lower than seting of battery level, switch to power saving mode.
  • #define POWER_POLICY_BATTERY_LEVEL 70 // When battery level lower than this, trigger power saving mode when power policy is AUTO
  • #define LED_MODE LED_MODE_DEFAULT
  • #define ADJ_MODE ADJ_MODE_NORMAL // Some special adjustment for different scenario
  • #define SETTING_MODE SETTING_MODE_CODE
  • // The logic decide if we should do something
  • #define LOGIC_WIFI_NEED_CONNECT 1
  • #define LOGIC_MQTT_NEED_SEND 2
  • #define LOGIC_DATA_NEED_SAVETOFLASH 3
  • #define LOGIC_WHAT_LED_STATE 4
  • #define LOGIC_LOG_NEED_SEND 5
  • #define LED_STATE_OFF 0
  • #define LED_STATE_READY 1
  • #define LED_STATE_ERROR 2

 

2.3. Code Trace呼叫階層關係

 

    BLYNK_READ (有一堆 XD)

  • 設定手機介面需要的虛擬 sensor (看不懂,先跳過 XD)

 

    msgCallback(): 由 PubSubClient callback

  • * msgDisplay()
  • * alarmHandlerCentral()
  • * alarm_buzzer_set()
  • * alarmHandlerPartner()
  • * getComma()
  • * getDoubleNumber()
  • * getComma()

 

    setting_verify(): setting init/save/load (debug 用平常不呼叫)

  • * setting_init(), setting_show()
  • * setting_save(), setting_show()
  • * setting_load(), setting_show()
  • * setting_versioncheck()
  • * setting_init()
  • * setting_save()

 

    setup()

  • * sensor_setup()
  • * setup_mgs()
  • * alarm_setup()
  • * setting_load()
  • * setting_versioncheck()
  • * setting_init()
  • * setting_save()
  • * setting_init()
  • * setting_save()
  • * checkWifiConnected()
  • * webserver_loop()
  • * setting_save()
  • * SendWebPage()
  • * printwebWifiStatus()
  • * lightBlink()
  • * setting_show()
  • * display_current_setting()
  • * init_sensor_data()
  • * retrieveNtpTime()
  • * sendNTPpacket()

 

    loop()

  • * logic_select()
  • * wifiConnecting()
  • * Mtk_Wifi_Setup_TryCnt()
  • * checkWifiConnected()
  • * wifiConnected()
  • * logic_select()
  • * logSend()
  • * checkWifiConnected()
  • * mqttSubscribeRoutine()
  • * mqttPublishRoutine()
  • * blynk_setup()
  • * //alarm_self_handler()
  • * packInfo()
  • * getCurrentTime()
  • * parseGPGGA()
  • * getComma()
  • * getDoubleNumber()
  • * getComma()
  • * getIntNumber()
  • * getComma()
  • * parseGPRMC
  • * getComma()
  • * parseGPVTG()
  • * getComma()
  • * getDoubleNumber()
  • * getComma()
  • * get_sensor_data()
  • * getBatteryStatus()
  • * pm25sensorG3()
  • * pm25sensorA4()
  • * createThread()
  • * dht_thread()
  • * get_sensor_data_mgs()
  • * get_sensor_data_dust()
  • * pulseInNoWaitStart()
  • * blynk_loop1()
  • * get_sensor_data_uv()
  • * get_sensor_data_sound()
  • * get_sensor_data_barometer()
  • * get_sensor_data_temperature()
  • * get_sensor_data_humidity()
  • * get_sensor_data_light()
  • * checkWifiConnected()
  • * mqttSubscribeRoutine()
  • * mqttPrintCurrentMsg()
  • * mqttPublishRoutine()
  • * getBatteryStatus()
  • * adjustCurrentPowerPolicy()
  • * lightLed()
  • * blynk_loop1()

 

2.4. 流程 (巨觀)

 

  • setup() {
  • 1. sensor_setup()
  • * DHT22, SHT31, Gas, Sound, Dust, Light, Barometer, LCD...
  • * 主要根據 APP_ID 的定義,決定 init 哪寫 sensors
  • * 還有像是 USE_DHT22, USE_SHT31 的 define
  • 2. alarm_setup()
  • * 設定 buzzer
  • 3. GPS power on
  • 4. Flash init via chip-select opera
  • 5. 從 internal flash 讀取 setting.bin。如果這次啟動有新的設定就覆寫。
  • 6. 嘗試連線 WiFi
  • 7. webserver_loop()
  • * 好像是用來連到 MQTT server 的?
  • 8. 把一些設定值 print 出來
  • 9. 初始化 sensorType[ ] 填入 type 編號
  • 10. 處理 FAKE_GPS
  • }

 

setup() 裡判斷 APP_ID 的機制有點像是 profiles,不同的 user 可以自己定義 APP_ID。每個 APP_ID 可以對應不同的 sensors。例如有的人可能使用 DHT22 量測溫溼度,有的人則使用 SHT31。為什麼這樣設計,細節還不是很清楚。

 

  • loop() {
  • 1. logic_select(): 執行 WiFi 連線
  • * 有點像 state machine,定義 5 種狀態
  • * LOGIC_WIFI_NEED_CONNECT: 執行 WiFi 連線
  • * LOGIC_MQTT_NEED_SEND: 透過 MQTT 傳送
  • * LOGIC_DATA_NEED_SAVETOFLASH: 將資料存入 flash
  • * LOGIC_WHAT_LED_STATE: 取得 LED 目前狀態
  • * LOGIC_LOG_NEED_SEND: 傳送 log
  • 2. 取得 GPS info
  • 3. get_sensor_data(): 取得 sensors 資料
  • * 更新 sensorValue[ ],放進 msg_sensor,再放入 sensorUploadString[ ]
  • 4. packInfo(INFO_MQTT)
  • * 將 sensorUploadString[ ] 放入 msg_tmp,再放入 msg
  • * msg 變數的內容,就是最後會傳出去的 data
  • 5. 當 need_send=1,把資料送出去 (MQTT publish)
  • * logic_select(LOGIC_MQTT_NEED_SEND) 會決定何時讓它 =1 (還有省電模式,就是晚點送啦)
  • 6. 將資料 save to flash
  • 7. 取得電池資訊並更新 power policy (影響 delay time)
  • }

 

loop() 從巨觀來看蠻合理的,WiFi 連線 -> 收資料 -> 傳出去,主要大概是這樣。我覺得 logic_select() 和 packInfo() 的作法應該可以更精簡。

 

另外,這篇: 如何加入新感測器 也稍微提到了幾個重點 function()

 

 

    3. Data Format

 

應該要了解到底送了什麼資料出去,以及 LASS 是怎麼規劃資料格式的。

 

3.1. hackpad Ref

 

 

3.2 MQTT Record definition

 

資料格式從 0.7.3 以後就是下面的樣子 (目前是 0.8.3。看 LASS.ino 的 VER_APP)

下面直接由 sample 說明。

 

前半段是一些 global data:

 

  • |ver_format=3 # MQTT record format version
  • ver_format=0 表示 user defined format

 

下面這兩個跟是否使用 fake GPS 資料有關,奇怪的是 code 裡面用上面的格式。文件說的卻是下面的格式?

 

  • |FAKE_GPS=0 # 0: data from gps, 1: gps data is fix data
  • |fmt_opt=0 # 0: default, 1: gps info invalid (我猜是 FAKE_GPS 用的)

 

(updated) 這裡有說明 V0.8 後 Fake GPS說明。看起來 FAKE_GPS 才是目前的做法 (跟 code 一樣就對了 XD)

 

  • |app=PM25 # system wide unique application name
  • 所以不能跟其他人重複 (在 "App Lists" 註冊)
  • |ver_app=0.7.3 # LASS version
  • |device_id=LJ_PM25_001 # unique in your application
  • |tick=26795810 # system tick (系統時鐘)
  • |date=2015-10-15 # 從 gps info 拿到的 yyyy-mm-dd
  • |time=22:35:07 # 從 gps info 拿到的 hh:mm:ss
  • |device=LinkItONE # 目前有 {LinkItONE, Ameba}

 

s_n 是 “sensor type” 由 [type]+[sequence] 組成,目前的格式看起來有兩種:

 

  • s_[c]: 1 個 char 代表是 system sensor (大多用 MTK 的 API 取得 data)。例如:
    • s_0: 應該是傳送的序列號
    • s_1: battery level
    • s_2: battery mode {0: not charging 1:charging}
    • s_3: ground speed (從 gps 取得)
  • s_[cc]: 2 個 chars 代表是 user defined sensors
    • 第一個 char 代表 sensor 類別
      • b: barometer
      • d: dust sensor
      • g: gas related
      • h: humidity
      • l: light
      • o: other, misc
      • t: temperature
      • w: wind
      • r: rain
    • 第二個 char 是 seq number, 從 0 開始
    • 有點像 Linux device file 的 minor & major number XD
    • 例如: (小心比對現有的編號,你應該優先使用現有的)
      • s_d0: G3/G5 dust sensor PM2.5
      • s_d3: Panasonic SN-GCHA1 dust sensor PM2.5
      • s_g1: CO
      • s_g8: SenseAir S8 CO2 (有的 define 很奇怪,到底是 by 不同氣體還是 by 不同 sensor)
      • s_h0: DHT22 sensor
      • s_h2: SHT31 sensor

 

  • |s_0=2234.00
  • |s_1=100.00
  • |s_2=1.00
  • |s_3=0.00
  • |s_4=1 # 看 code 應該是 retry wifi connect 的次數?
  • |s_d0=39.00 # G3/G5 dust sensor PM2.5
  • |s_t0=25.50 # DHT22 sensor
  • |s_h0=65.80 # DHT22 sensor (跟 t0 一樣,因為 DHT22 是 "溫濕度" 感應器)

 

GPS 有很多種格式,LASS 使用 GPGGA 當作預設的格式

 

  • |gps_lat=25.025362 # latitude 緯度
  • |gps_lon=121.371038 # longitude 經度
  • |gps_fix=1 # fix quality? {0: invalid, 1: GPS fix, 2: DGPS fix}
  • DGPS: 差分式全球定位系統 (其實我根本不知道這是啥)
  • |gps_num=9 # 參與衛星定位的衛星數量
  • |gps_alt=2 # 海平面以上高度

 

總之,最大的傳輸量是 512-1

 

  • #define MSG_BUFFER_MAX 512
  • char msg[MSG_BUFFER_MAX];

 

3.3. MQTT Topic definition

 

MQTT 發布或訂閱時需要知道的 topic name

 

  • LASS 的定義為 “LASS/Group/APP”
  • 例如:
    • LASS/Test/Default (APP_ID=0)
    • LASS/Test/PM25
    • LASS/Test/Wuulong
    • LASS/Test/LinkItSmart7688-Test
    • LASS/Test/LASS4U
  • 目前 code 裡面直接定義 MQTT_TOPIC_PREFIX “LASS/Test”

 

3.4. APP_ID

 

App Lists 可以看大家上傳檔案的格式。而且這個可以對照 configuration.h 那一堆 APP_ID #ifdef

概念是每個人的開發板可能都使用不同的 sensors 組合,而有不同的應用。所以這個 “App Lists” 頁面就是用來告訴大家目前的應用 APP(lication) 有哪些,以及該訂閱哪個 MQTT topic。

 

APP_ID 由 [application type] 和 [序列 number] 所組成。

 

    application type

LASS 定義了三種 app type:

  • System application
    • 屬於 LASS 官方套件的,都歸在這一類。
    • 目前有 PM25 和 LASS4U 都屬於 System APP
  • Public application
    • Wuulong、EXAMPLE_APP1、MAPS、FlyPm25…都屬於這一類,一般來說數量比較大
  • Private application
    • 目前沒有人使用

 

APP_ID 最後的值,會落在三個區間。這三個區間表示他們所屬的 application type

  • 0-255: System APP (APPTYPE_SYSTEM_BASE=0)
  • 256-32767: Public APP (APPTYPE_PUBLIC_BASE=256)
  • 32768-65536: Private APP (APPTYPE_PRIVATE_BASE=32768)

 

Note: 如果有新增,必須更新 App Lists

 

    幾個特別的 APP_ID

LASS/configuration.h 裡面應該可以看到

  • #if APP_ID==(APPTYPE_SYSTEM_BASE+1)
  • #define USE_PM25_G3
  • #define USE_DHT22
  • ...

 

然後 LASS/LASS.ino 又有這一段

  • #if (APP_ID==(APPTYPE_SYSTEM_BASE+1) || APP_ID==(APPTYPE_PUBLIC_BASE+12))
  • #define APP_NAME "PM25" # 其實寫在 configuration.h 就好了呀 = =
  • ...

 

APP_ID==(APPTYPE_SYSTEM_BASE+1) 其實 code 裡面就是 APP_ID=1,因為在 0~255 之間,所以它是一個 System APP。

 

看 code 可以知道,通常決定 APP_ID 之後還會決定一個 APP_NAME,APP_ID=1 的 APP_NAME=“PM25”。剛好 mapping 最後的 MQTT topic: LASS/Test/PM25

 

APP_ID 還有個比較特別的是 APP_ID=0, 它的 APP_NAME=“Default”,MQTT topic: LASS/Test/Default。它的內容應該只有四個:

  • SENSOR_ID_RECORDID 0
  • SENSOR_ID_BATTERYLEVEL 1
  • SENSOR_ID_BATTERYCHARGING 2 // (0) not charging, (1) charging
  • SENSOR_ID_GROUNDSPEED 3
  • SENSOR_ID_DEBUGWIFI 4

 

其實正好就是對應到 system sensor 的 s_0, s_1, s_2, s_3, s_4。

 

Note: 其實文件中沒提到 s_4 但是 code 裡面有 @@!

 

一路看到這邊後,覺得 APP_ID 很奇怪,它似乎不再傳送的 MQTT 封包內容裡?

結果剛剛看到這篇: 如何加入新的 APP_ID

 

  • APP_ID/APP_NAME 是在 LASS 用來區分應用情境的方式。APP_ID 和 APP_NAME 的對應是一對一的,
  • APP_ID 基本上只使用在 Code 中,在 Data 是看不到的,
  • APP_NAME 才是對使用者有意義的,也存在於 DATA 中。

 

看吧!!!

 

3.5. DEVICE_ID

 

Device ID 的定義在這: Device ID definition

編碼格式原則是 LASS-YYY_xxx

  • YYY 為一到三碼
  • xxx 為一碼含以上流水號
  • 其中 LASS-TST_xxx 是測試用的,不能保證有唯一性 (看運氣 XD)

 

    4. Others

 

LASS Specification 這份文件提到 LASS 系統巨觀應該提供怎樣的功能。若是想使用非 LinkItOne 的平台,應該儘可能地做到符合 LASS 的 spec.

 

  • ANDREW小心得: 在 open source 又是多人參與的專案中,文件並不一定會一直同步更新或是持續被維護。看 source code 比較準!!

 

~ END ~