├── .cproject
├── .gitignore
├── .project
├── .pydevproject
├── .settings
├── language.settings.xml
└── org.eclipse.cdt.codan.core.prefs
├── CHANGELOG.md
├── Jenkinsfile
├── LICENSE
├── Makefile
├── README.md
├── bin
├── coredump.sh
├── coredump2.sh
├── debug.sh
├── deploy_ota.sh
├── dev_tests.sh
├── erase.sh
├── find_esp_device.py
├── firmware_installer.py
├── flash-monitor.sh
├── make_default.sh
├── make_test_menuconfig.sh
├── make_tests.sh
├── read_serial.py
├── run_tests.py
└── test_components.sh
├── components
├── oap-aws
│ ├── awsiot.c
│ ├── awsiot_common.h
│ ├── awsiot_rest.c
│ ├── awsiot_rest.h
│ ├── component.mk
│ ├── include
│ │ └── awsiot.h
│ ├── test
│ │ ├── 1cbf751210-certificate.pem.crt
│ │ ├── 1cbf751210-private.pem.key
│ │ ├── 1cbf751210-public.pem.key
│ │ ├── component.mk
│ │ └── test_awsiot.c
│ └── verisign_root_ca.pem
├── oap-common
│ ├── c_list.c
│ ├── component.mk
│ ├── default_config.json
│ ├── include
│ │ ├── c_list.h
│ │ ├── oap_common.h
│ │ ├── oap_data.h
│ │ ├── oap_data_env.h
│ │ ├── oap_data_pm.h
│ │ ├── oap_debug.h
│ │ ├── oap_publisher.h
│ │ ├── oap_storage.h
│ │ └── oap_version.h
│ ├── oap_common.c
│ ├── oap_debug.c
│ ├── oap_storage.c
│ ├── oap_version.c
│ └── test
│ │ ├── .gitignore
│ │ ├── component.mk
│ │ ├── include
│ │ └── oap_test.h
│ │ ├── oap_test.c
│ │ ├── sandbox.c
│ │ ├── test_oap_storage.c
│ │ └── test_oap_version.c
├── oap-http
│ ├── LICENSE
│ ├── README.md
│ ├── component.mk
│ ├── esp_request.c
│ ├── include
│ │ ├── esp_request.h
│ │ ├── req_list.h
│ │ └── uri_parser.h
│ ├── req_list.c
│ ├── test
│ │ ├── component.mk
│ │ └── test_esp_request.c
│ └── uri_parser.c
├── oap-hw-bmx280
│ ├── Kconfig
│ ├── bmx280.c
│ ├── component.mk
│ ├── i2c_bme280.c
│ ├── i2c_bme280.h
│ ├── include
│ │ └── bmx280.h
│ └── test
│ │ ├── component.mk
│ │ └── test_bmx280.c
├── oap-hw-ext
│ ├── Kconfig
│ ├── component.mk
│ ├── ctrl_btn.c
│ ├── include
│ │ ├── ctrl_btn.h
│ │ └── rgb_led.h
│ └── rgb_led.c
├── oap-hw-pmsx003
│ ├── Kconfig
│ ├── component.mk
│ ├── include
│ │ └── pmsx003.h
│ ├── pmsx003.c
│ └── test
│ │ ├── component.mk
│ │ └── test_pmsx003.c
├── oap-meter
│ ├── Kconfig
│ ├── component.mk
│ ├── include
│ │ ├── meas_continuous.h
│ │ ├── meas_intervals.h
│ │ └── pm_meter.h
│ ├── meas_continuous.c
│ ├── meas_intervals.c
│ ├── pm_meter.c
│ └── test
│ │ ├── component.mk
│ │ └── test_pm_meter.c
├── oap-ota
│ ├── Kconfig
│ ├── comodo_ca.pem
│ ├── component.mk
│ ├── digicert_ca.crt
│ ├── digicert_ca.pem
│ ├── include
│ │ └── ota.h
│ ├── ota.c
│ ├── ota_int.h
│ └── test
│ │ ├── component.mk
│ │ ├── files
│ │ ├── hello-world.bin
│ │ ├── index-sha-mismatch.txt
│ │ └── index.txt
│ │ └── test_ota.c
├── oap-thingspk
│ ├── component.mk
│ ├── include
│ │ └── thing_speak.h
│ ├── test
│ │ ├── component.mk
│ │ └── test_thing_speak.c
│ └── thing_speak.c
└── oap-wifi
│ ├── Kconfig
│ ├── bootwifi.c
│ ├── component.mk
│ ├── cpanel.c
│ ├── cpanel.h
│ ├── include
│ ├── bootwifi.h
│ └── server_cpanel.h
│ ├── index.html
│ ├── mongoose.c
│ ├── mongoose.h
│ ├── server.c
│ ├── server.h
│ ├── server_cpanel.c
│ └── test
│ ├── component.mk
│ └── test_bootwifi.c
├── doc
├── BST-BME280_DS001-10.pdf
├── BST-BMP280-DS001-11.pdf
├── api
│ ├── README.md
│ └── state.json
├── images
│ ├── ESP32-DevBoard.jpg
│ ├── prototype.jpg
│ ├── schema.jpg
│ └── sensor_settings.png
└── plantower-pms5003-manual_v2-3.pdf
├── main
├── Kconfig.projbuild
├── component.mk
├── main.c
└── oap_config.txt
├── partitions.csv
├── sdkconfig.defaults
└── unit-test-app
├── .gitignore
├── Makefile
├── README.md
├── components
└── unity
│ ├── component.mk
│ ├── include
│ ├── test_utils.h
│ ├── unity.h
│ ├── unity_config.h
│ └── unity_internals.h
│ ├── license.txt
│ ├── ref_clock.c
│ ├── test_utils.c
│ ├── unity.c
│ └── unity_platform.c
├── main
├── app_main.c
└── component.mk
├── partition_table_unit_test_app.csv
└── sdkconfig.defaults
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | sdkconfig
3 | sdkconfig.old
4 | sdkconfig.bak
5 | .DS_Store
6 | main/*.bak
7 | core.dat
8 | /tmp
9 | /logs
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | pmsensor
4 |
5 |
6 |
7 |
8 |
9 | org.python.pydev.PyDevBuilder
10 |
11 |
12 |
13 |
14 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
15 | clean,full,incremental,
16 |
17 |
18 |
19 |
20 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
21 | full,incremental,
22 |
23 |
24 |
25 |
26 |
27 | org.eclipse.cdt.core.cnature
28 | org.eclipse.cdt.core.ccnature
29 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
30 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
31 | org.python.pydev.pythonNature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/.pydevproject:
--------------------------------------------------------------------------------
1 |
2 |
3 | Default
4 | python interpreter
5 |
6 |
--------------------------------------------------------------------------------
/.settings/language.settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # 1.2.0
2 |
3 | - a few IDF configuration changes (run on single core, reduce flash freq)
4 | - clean up logs
5 | - update esp-idf 2.1 to include KRACK fix
6 |
7 | # 1.1.0
8 |
9 | - reboot after crash or when watchdog detects hanging task for 10sec ([#43](https://github.com/openairproject/sensor-esp32/issues/43))
10 |
11 | # 1.0.0
12 |
13 | - use stable esp-idf release instead of working version (too many issues with wifi/ssl)
14 | - ability to reset to factory firmware ([#40](https://github.com/openairproject/sensor-esp32/issues/40))
15 |
16 | # 0.6.0
17 |
18 | - fix wifi issues ([#32](https://github.com/openairproject/sensor-esp32/issues/32)), ([#19](https://github.com/openairproject/sensor-esp32/issues/19))
19 | - wifi / control panel refactored and unit-tested
20 |
21 |
22 | # 0.5.1
23 |
24 | - configurable OTA interval ([#28](https://github.com/openairproject/sensor-esp32/issues/28))
25 | - refactored thingspeak client and generic 'publisher' interface
26 |
27 | # 0.5.0
28 |
29 | - enable Jenkins build and automated unit tests ([#4](https://github.com/openairproject/sensor-esp32/issues/4))
30 |
31 | # 0.4.3
32 |
33 | - OTA updates ([#2](https://github.com/openairproject/sensor-esp32/issues/2))
34 | - fix NVS crash after fresh install ([#14](https://github.com/openairproject/sensor-esp32/issues/14))
35 | - fix non-unique SSID in AP mode ([#21](https://github.com/openairproject/sensor-esp32/issues/21))
36 |
37 | # 0.4.0
38 |
39 | - support two PM sensors ([#8](https://github.com/openairproject/sensor-esp32/issues/8))
40 | - update ESP-IDF to 2.1 ([#1](https://github.com/openairproject/sensor-esp32/issues/1))
41 | - track firmware version ([#9](https://github.com/openairproject/sensor-esp32/issues/9))
42 | - display firmware version ([#11](https://github.com/openairproject/sensor-esp32/issues/11))
43 | - add unit tests ([#3](https://github.com/openairproject/sensor-esp32/issues/3))
44 |
45 | # 0.3.0
46 |
47 | - support two (internal and external) bmx sensors
48 | - support optional fan and heater
49 |
50 | # 0.2.0
51 |
52 | - support for bmp280 and bme280
53 | - basic rest client for AWS IoT
54 |
55 | # 0.1.1
56 |
57 | - all main features working (some issues with bmp280)
58 | - thingspeak client
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | pipeline {
2 | agent any
3 | stages {
4 | stage('build') {
5 | steps {
6 | checkout scm
7 | sh 'rm -rf build'
8 | sh 'bin/make_default.sh'
9 | }
10 | }
11 | stage('test') {
12 | steps {
13 | sh '/opt/oap/dev/tty_refresh.sh'
14 | sh 'bin/make_tests.sh'
15 | sh 'sleep 3'
16 | sh 'bin/run_tests.py /opt/oap/dev/ttyOAP.TEST'
17 | }
18 | }
19 | stage('archive') {
20 | steps {
21 | sh 'cat build/sensor-esp32.bin | openssl dgst -sha256 > build/sensor-esp32.bin.sha256'
22 | }
23 | post {
24 | success {
25 | archiveArtifacts artifacts: 'build/sensor-esp32.*', fingerprint: true
26 | archiveArtifacts artifacts: 'build/partitions.bin', fingerprint: true
27 | archiveArtifacts artifacts: 'build/bootloader/bootloader.bin', fingerprint: true
28 | }
29 | }
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := sensor-esp32
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
10 |
--------------------------------------------------------------------------------
/bin/coredump.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | $IDF_PATH/components/espcoredump/espcoredump.py info_corefile -t b64 -c logs/core.dat build/sensor-esp32.elf
--------------------------------------------------------------------------------
/bin/coredump2.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | $IDF_PATH/components/espcoredump/espcoredump.py dbg_corefile -t b64 -c logs/core.dat build/sensor-esp32.elf
--------------------------------------------------------------------------------
/bin/debug.sh:
--------------------------------------------------------------------------------
1 | xtensa-esp32-elf-gdb build/sensor-esp32.elf
2 |
--------------------------------------------------------------------------------
/bin/deploy_ota.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # $1 - release version
5 | #
6 |
7 | INDEX_FILE=build/index.txt
8 | DEST_FOLDER=s3://openairproject.com/ota
9 |
10 | printf "$1|$1/sensor-esp32.bin|" > $INDEX_FILE
11 |
12 | cat build/sensor-esp32.bin | openssl dgst -sha256 -binary | xxd -p -c 100 >> $INDEX_FILE
13 | cat $INDEX_FILE
14 |
15 | aws s3 cp build/sensor-esp32.bin $DEST_FOLDER/$1/sensor-esp32.bin --profile oap
16 | aws s3 cp $INDEX_FILE $DEST_FOLDER/index.txt --profile oap
--------------------------------------------------------------------------------
/bin/dev_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #https://www.esp32.com/viewtopic.php?t=2867
4 |
5 | bin="$(dirname "$0")"
6 | . bin/test_components.sh
7 | project=`pwd`
8 | echo $TEST_COMPONENTS
9 | make -C unit-test-app EXTRA_COMPONENT_DIRS=$project/components TEST_COMPONENTS="$TEST_COMPONENTS" all flash monitor -j5
--------------------------------------------------------------------------------
/bin/erase.sh:
--------------------------------------------------------------------------------
1 | python $IDF_PATH/components/esptool_py/esptool/esptool.py -p /opt/oap/dev/ttyOAP -b 115200 erase_flash
2 |
--------------------------------------------------------------------------------
/bin/find_esp_device.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 |
3 | import sys
4 | import glob
5 | import subprocess
6 | import os
7 | import re
8 |
9 | #
10 | # allows mapping connected ESP32 devices based on their chipId.
11 | # Using chipId is necessary since all devboards report the same serial num and other
12 | # attrbbutes that are usually used to map serial devices to persistent names
13 | #
14 | # Usage:
15 | #
16 | # find_esp_devices.py '/dev/ttyUSB?' '0xac240ac4020c' '$HOME/dev1' '0xd30aea4014e' '$HOME/dev0'
17 | #
18 | # 1st argument is a mask to look for connected devices,
19 | # then each pair of arguments defines a mapping between chipId => symlink to create
20 | #
21 | # chipId must be in the exact format as returned by esptool.
22 | # You can display it using
23 | #
24 | # esptool.py --port '/dev/ttyUSB0' chip_id
25 | #
26 |
27 | chipToSymlink={}
28 | for i in xrange(2, len(sys.argv), 2):
29 | chipToSymlink[sys.argv[i].strip()]=os.path.expandvars(sys.argv[i+1].strip())
30 |
31 | print 'look for devices \"'+sys.argv[1]+'\" and try to map links ',
32 | print chipToSymlink
33 |
34 | devices = glob.glob(sys.argv[1])
35 |
36 | esptool = os.path.expandvars('$IDF_PATH')+'/components/esptool_py/esptool/esptool.py'
37 | print 'esp tool path: '+esptool
38 |
39 | chipToTTY={}
40 |
41 | for device in devices:
42 | print 'checking '+device
43 | proc = subprocess.Popen([esptool,'--port',device,'chip_id'],stdout=subprocess.PIPE)
44 | while True:
45 | line = proc.stdout.readline()
46 | if line == '':
47 | break
48 | matcher = re.match('Chip ID: (0x.*)', line, re.M|re.I)
49 | if matcher:
50 | print 'chip:'+matcher.group(1)
51 | chipToTTY[matcher.group(1)]=device
52 | break
53 |
54 | proc.wait()
55 | if proc.returncode != 0:
56 | print 'exit due to problem with esptool ('+proc.returncode+')'
57 | sys.exit(proc.returncode)
58 |
59 | print 'found following devices ',
60 | print chipToTTY
61 |
62 | for chipId in chipToSymlink:
63 | link = chipToSymlink[chipId]
64 | if os.path.islink(link):
65 | os.unlink(link)
66 | try:
67 | tty = chipToTTY[chipId]
68 | print 'create link '+link+'=>'+tty
69 | os.symlink(tty, link)
70 | except KeyError, e:
71 | pass
72 |
73 | print 'done'
--------------------------------------------------------------------------------
/bin/firmware_installer.py:
--------------------------------------------------------------------------------
1 | 1. ask for UART NAME
2 | 2.
3 | make TEMP_DIR
4 | git clone https://github.com/espressif/esptool.git -o TEMP_DIR
5 | 3.
6 | TEMP_DIR/esptool.py --port /dev/tty.SLAB_USBtoUART --after no_reset chip_id
7 | 4.
8 | fetch https://openairproject.com/ota/index.txt to TEMP_DIR
9 | parse first line
10 | fetch binaries to TEMP_DIR
11 | test sha
12 | 5.
13 | fetch partitions_two_ota.bin
14 | fetch bootloader.bin
15 | 6.
16 | python TEMP_DIR/esptool.py --chip esp32 --port /dev/tty.SLAB_USBtoUART --baud 921600 --before default_reset
17 | --after hard_reset write_flash -u --flash_mode dio --flash_freq 40m --flash_size detect
18 | 0x1000 TEMP_DIR/bootloader.bin 0x10000 TEMP_DIR/sensor-esp32.bin 0x8000 TEMP_DIR/partitions_two_ota.bin
--------------------------------------------------------------------------------
/bin/flash-monitor.sh:
--------------------------------------------------------------------------------
1 | make flash monitor -j5 | tee logs/`date +%Y-%m-%d%H%M`.log
2 |
3 |
--------------------------------------------------------------------------------
/bin/make_default.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | export BATCH_BUILD=1
4 | make defconfig all $1 -j5 > /dev/null
--------------------------------------------------------------------------------
/bin/make_test_menuconfig.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | bin="$(dirname "$0")"
4 | . bin/test_components.sh
5 | project=`pwd`
6 | echo $TEST_COMPONENTS
7 | make -C unit-test-app EXTRA_COMPONENT_DIRS=$project/components TEST_COMPONENTS="$TEST_COMPONENTS" menuconfig
--------------------------------------------------------------------------------
/bin/make_tests.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #https://www.esp32.com/viewtopic.php?t=2867
4 |
5 | bin="$(dirname "$0")"
6 | . bin/test_components.sh
7 | export BATCH_BUILD=1
8 | project=`pwd`
9 |
10 | make -C unit-test-app EXTRA_COMPONENT_DIRS=$project/components TEST_COMPONENTS="$TEST_COMPONENTS" defconfig all flash $1 -j5 > /dev/null
--------------------------------------------------------------------------------
/bin/read_serial.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import serial
3 | import sys
4 | import time
5 |
6 | ser = serial.Serial(None,115200,timeout=None,rtscts=False,xonxoff=True)
7 | ser.port=sys.argv[1]
8 | ser.dtr=False
9 | ser.rts=False #otherwise it will wait for download after reboot
10 | ser.open()
11 |
12 | try:
13 | while True:
14 | line = ser.readline()
15 | print line,
16 | #to work with 'tee'
17 | sys.stdout.flush()
18 | finally:
19 | ser.close()
--------------------------------------------------------------------------------
/bin/run_tests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import serial
3 | import sys
4 | import time
5 |
6 | #'/dev/tty.SLAB_USBtoUART'
7 |
8 | ser = serial.Serial(sys.argv[1],115200,timeout=1)
9 |
10 | def readall(exp, timeout = 5):
11 | line = ser.readline()
12 | lastline = ''
13 | start = time.time()
14 | while line != exp:
15 | lastline = line
16 |
17 | if line == 'Rebooting...':
18 | lastline = 'UNEXPECTED REBOOT'
19 | break
20 |
21 | if ":FAIL" in line or ":PASS" in line:
22 | start = time.time()
23 |
24 | if time.time() - start > timeout:
25 | lastline = 'TIMEOUT after '+str(timeout)+' seconds'
26 | break
27 |
28 | line = ser.readline()
29 | sys.stdout.write(line)
30 | sys.stdout.flush()
31 | line = line.strip()
32 | return lastline
33 |
34 | def wait_for_test_result():
35 | return readall('Enter next test, or \'enter\' to see menu',30)
36 |
37 | ser.write('\n');
38 | readall('Here\'s the test menu, pick your combo:')
39 | readall('')
40 | ser.write('*' if len(sys.argv) <= 2 else sys.argv[2])
41 | ser.write('\n')
42 | result = wait_for_test_result().strip()
43 | sys.stdout.write('TEST RESULT: '+result)
44 | ser.close()
45 | sys.exit(0 if result == 'OK' else 1)
--------------------------------------------------------------------------------
/bin/test_components.sh:
--------------------------------------------------------------------------------
1 | TEST_COMPONENTS='oap-common oap-hw-bmx280 oap-hw-pmsx003 oap-meter oap-http oap-aws oap-thingspk oap-ota oap-wifi'
--------------------------------------------------------------------------------
/components/oap-aws/awsiot_common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * awsiot_common.h
3 | *
4 | * Created on: Feb 18, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_AWSIOT_AWSIOT_COMMON_H_
24 | #define COMPONENTS_AWSIOT_AWSIOT_COMMON_H_
25 |
26 |
27 |
28 |
29 |
30 | #endif /* COMPONENTS_AWSIOT_AWSIOT_COMMON_H_ */
31 |
--------------------------------------------------------------------------------
/components/oap-aws/awsiot_rest.c:
--------------------------------------------------------------------------------
1 | /*
2 | * aws_iot_rest.c
3 | *
4 | * Created on: Feb 18, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include
24 | #include
25 | #include "freertos/FreeRTOS.h"
26 | #include "freertos/task.h"
27 | #include "freertos/event_groups.h"
28 | #include "esp_wifi.h"
29 | #include "esp_event_loop.h"
30 | #include "esp_log.h"
31 | #include "esp_system.h"
32 | #include "nvs_flash.h"
33 |
34 | #include "awsiot_rest.h"
35 | //#include "ssl_client.h"
36 | #include "oap_common.h"
37 | #include "oap_debug.h"
38 | #include "esp_request.h"
39 |
40 | //#define WEB_SERVER "a32on3oilq3poc.iot.eu-west-1.amazonaws.com"
41 | //#define WEB_PORT "8443"
42 | //#define WEB_URL "/things/pm_wro_2/shadow"
43 |
44 | static const char *TAG = "awsiot";
45 |
46 | extern const uint8_t verisign_root_ca_pem_start[] asm("_binary_verisign_root_ca_pem_start");
47 | extern const uint8_t verisign_root_ca_pem_end[] asm("_binary_verisign_root_ca_pem_end");
48 |
49 | static int download_callback(request_t *req, char *data, int len) {
50 | ESP_LOGI(TAG, "response:%s", data);
51 | return 0;
52 | }
53 |
54 | esp_err_t awsiot_update_shadow(awsiot_config_t* awsiot_config, char* body) {
55 | char uri[100];
56 | sprintf(uri, "https://%s:%d", awsiot_config->endpoint, awsiot_config->port);
57 |
58 | request_t* req = req_new(uri);
59 | if (!req) {
60 | return ESP_FAIL;
61 | }
62 |
63 | req->ca_cert = req_parse_x509_crt((unsigned char*)verisign_root_ca_pem_start, verisign_root_ca_pem_end-verisign_root_ca_pem_start);
64 | if (!req->ca_cert) {
65 | req_clean(req);
66 | ESP_LOGW(TAG, "Invalid CA cert");
67 | return ESP_FAIL;
68 | }
69 |
70 | req->client_cert = req_parse_x509_crt((unsigned char*)awsiot_config->cert, strlen(awsiot_config->cert)+1);
71 | if (!req->client_cert) {
72 | req_clean(req);
73 | ESP_LOGW(TAG, "Invalid client cert");
74 | return ESP_FAIL;
75 | }
76 | req->client_key = req_parse_pkey((unsigned char*)awsiot_config->pkey, strlen(awsiot_config->pkey)+1);
77 |
78 | if (!req->client_key) {
79 | req_clean(req);
80 | ESP_LOGW(TAG, "Invalid client key");
81 | return ESP_FAIL;
82 | }
83 |
84 | char path[100];
85 | sprintf(path, "/things/%s/shadow", awsiot_config->thingName);
86 |
87 |
88 | req_setopt(req, REQ_SET_METHOD, HTTP_POST);
89 | req_setopt(req, REQ_SET_PATH, path);
90 | //req_setopt(req, REQ_SET_HEADER, host_header);
91 | req_setopt(req, REQ_SET_HEADER, HTTP_HEADER_CONTENT_TYPE_JSON);
92 | req_setopt(req, REQ_SET_HEADER, HTTP_HEADER_CONNECTION_CLOSE);
93 | req_setopt(req, REQ_SET_DATAFIELDS, body);
94 |
95 | req_setopt(req, REQ_FUNC_DOWNLOAD_CB, download_callback);
96 |
97 | int status = req_perform(req);
98 | req_clean(req);
99 |
100 | if (status != 200) {
101 | ESP_LOGW(TAG, "Invalid response code: %d", status);
102 | return ESP_FAIL;
103 | } else {
104 | return ESP_OK;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/components/oap-aws/awsiot_rest.h:
--------------------------------------------------------------------------------
1 | /*
2 | * awsiot_rest.h
3 | *
4 | * Created on: Feb 18, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_AWSIOT_INCLUDE_AWSIOT_REST_H_
24 | #define COMPONENTS_AWSIOT_INCLUDE_AWSIOT_REST_H_
25 |
26 | typedef struct {
27 | int configured;
28 | char* endpoint;
29 | int port;
30 | char* thingName;
31 | char* cert;
32 | char* pkey;
33 | } awsiot_config_t;
34 |
35 | esp_err_t awsiot_update_shadow(awsiot_config_t* awsiot_config, char* body);
36 |
37 | #endif /* COMPONENTS_AWSIOT_INCLUDE_AWSIOT_REST_H_ */
38 |
--------------------------------------------------------------------------------
/components/oap-aws/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
10 | COMPONENT_EMBED_TXTFILES := verisign_root_ca.pem
--------------------------------------------------------------------------------
/components/oap-aws/include/awsiot.h:
--------------------------------------------------------------------------------
1 | /*
2 | * awsiot_client.h
3 | *
4 | * Created on: Feb 18, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_AWSIOT_INCLUDE_AWSIOT_H_
24 | #define COMPONENTS_AWSIOT_INCLUDE_AWSIOT_H_
25 |
26 | #include "oap_common.h"
27 | #include "oap_publisher.h"
28 |
29 | oap_publisher_t awsiot_publisher;
30 |
31 | #endif /* COMPONENTS_AWSIOT_INCLUDE_AWSIOT_H_ */
32 |
--------------------------------------------------------------------------------
/components/oap-aws/test/1cbf751210-certificate.pem.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDWjCCAkKgAwIBAgIVAKFzi5PjNi9O8WR8Nc5U8/vPVRZGMA0GCSqGSIb3DQEB
3 | CwUAME0xSzBJBgNVBAsMQkFtYXpvbiBXZWIgU2VydmljZXMgTz1BbWF6b24uY29t
4 | IEluYy4gTD1TZWF0dGxlIFNUPVdhc2hpbmd0b24gQz1VUzAeFw0xNzA5MTExOTE3
5 | MDdaFw00OTEyMzEyMzU5NTlaMB4xHDAaBgNVBAMME0FXUyBJb1QgQ2VydGlmaWNh
6 | dGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCWJaW0JqRg8pMYZm6L
7 | fSuMlGzAmElbArKDXe4f+LA3dzsSZG7ZxX6p/yEcPwx5dMtJjhq1BOlJu/pL+8Lk
8 | JkfluUeVt7oemdRJN1A/gcfwN+OY7bT1RQ3cGbeCZP5Y+APcfS1Cag25i0E9gweI
9 | Om9aEDb23hAr02FosQQjeaDOHpz4QelPnCGvyiQAktxjyG77RXRg0H9csgPwkklc
10 | fnEt0z9Bsh9dqdH5R6tkdJz8oTlbBFC5VLu20Kcu1LdG82GIJ6p24uXcJLKNWcsm
11 | 6Cc/nqxfxTkzKrgI+4si4Yya/nUJSkTYnnFW8zgk3Fw8dNCnpfMfgyZ0mhoXOvFt
12 | 7iKPAgMBAAGjYDBeMB8GA1UdIwQYMBaAFKQWUtvRdE8V1KemiV6qOWgmc+86MB0G
13 | A1UdDgQWBBRkSSPHlb6NyJff0KbedYJCRIxFXzAMBgNVHRMBAf8EAjAAMA4GA1Ud
14 | DwEB/wQEAwIHgDANBgkqhkiG9w0BAQsFAAOCAQEAfptO2uTC3w1r5dIsv/CaURns
15 | xGyvOBKKwl3kZdSMDSvRYpktVBSbQLMcBx35eutvlc/ICgV0PoBUKtcSFuYSHP7n
16 | 4zPSU7mDoAaX3sikLLPzZMxHmWalhJMKezl9leRJsJKPa7YTqelaaZAuq6w8G6x8
17 | Q+1LIeSUrPr0yN4+uCW1VdtZT6AVYD+rnjLhmUx6HvhKSbByR1oMsuDExckTpIAO
18 | TOpmQ2jB7xISa2n9zCgndqZd3TsVhOKtQ6kAWw208O6aHhEcLamQiv2X2XgZhbZg
19 | slJkauJ8k+s9Uv+I/0pBcTfWathGsnuKXogIlqKRud6J0Mv4lZqHb0Oq/Kp3tg==
20 | -----END CERTIFICATE-----
21 |
--------------------------------------------------------------------------------
/components/oap-aws/test/1cbf751210-private.pem.key:
--------------------------------------------------------------------------------
1 | -----BEGIN RSA PRIVATE KEY-----
2 | MIIEpAIBAAKCAQEAliWltCakYPKTGGZui30rjJRswJhJWwKyg13uH/iwN3c7EmRu
3 | 2cV+qf8hHD8MeXTLSY4atQTpSbv6S/vC5CZH5blHlbe6HpnUSTdQP4HH8DfjmO20
4 | 9UUN3Bm3gmT+WPgD3H0tQmoNuYtBPYMHiDpvWhA29t4QK9NhaLEEI3mgzh6c+EHp
5 | T5whr8okAJLcY8hu+0V0YNB/XLID8JJJXH5xLdM/QbIfXanR+UerZHSc/KE5WwRQ
6 | uVS7ttCnLtS3RvNhiCeqduLl3CSyjVnLJugnP56sX8U5Myq4CPuLIuGMmv51CUpE
7 | 2J5xVvM4JNxcPHTQp6XzH4MmdJoaFzrxbe4ijwIDAQABAoIBAQCSlji7tApBuDHR
8 | 3ZdJSa/ttK6kLUlYuD5uMJMd1Z682APtBe6PX9g0waeiuw9DuLoLmtgKKLxVx1cr
9 | PaVdNt50sjnoOpJT890kigMnrV308aubj19fIcbRPq5BeLY1SBYE+pToRUAXCJRu
10 | KHF/F4XFCRWQWOay0tFD86ZVuBY9hHcw1148hfMcQK7aDjrA1PKStAFi4gqeTcm+
11 | UNFa7HNHq4LG7fuaEsmd9iBh9gooWsJiSmbcrG3knXwVJd2DuaTqou9jQqr/qQae
12 | CyB3uDEwbhSLx8ypMsiqSvoLO3qMRh/q359SfPnQCUS8EcbBELaOuSjE/em7DyPn
13 | wDnNbkpBAoGBANebbUx/Vmf8xAlro+aHqP4RFVMrCZNwbZMd05nA4nsZzSUo5ejq
14 | bgKzqcHHWvFDaxivO+33V4aJhId8NpfTN/3gHg+zZVAQHsJsPw7D7Wj/3yI2bfH+
15 | R3NH823YWS2St4G2qua+u53rslnVUNFLx5mFVfN+pByt8FWkkDgzNFqvAoGBALJG
16 | vQiy2xYmq+Adg224La/u1LeTD2MGcdYqbQiZu8bhller5MwOweP4bvFU1NYGb7Ad
17 | 7xZim0mWEE0XXFKeivAWrO2GW6zTZaV1CzOjkOQzWxfV7vLcNd79ngJGbvs6EE2e
18 | ZYDgvuQfk7QM1lr1xKKVt143iFQJLmw5lEZ/DS4hAoGAfoIOUdJtqrpfdH+aPgvf
19 | lqQDdTdNeRuAz8+ydwb8XOq4ulMTA+V6A0/UDYWh0OqUDnnTmj+FNcW+45h4mAEx
20 | W1+DhAbpLV8oDUBih5Fi3jc0f+ib/mALIJNZPFyzhtANqKi8AoRrpa/EiH1n3Eaw
21 | qV3ZHvRx6voMiNP0Y2V4FLUCgYAHgrVqDWbveveYvIWR9MVv+QbbKQXn7RiUpjrr
22 | ttZTXaOg0+wSsLh4azn5TtKcpa7E463z6nmSUxEivk40aNt/m+TzKMrp8AoDO3ga
23 | V9S92HAJBAlKD/7xAwxKGj+Is/yF2Jt8H3vLTo1Bc50APgRnuRj9jidfKvfatV5K
24 | zgV3IQKBgQDN27WFS8rnhM6tgq+hwCoecPQjomHQnTb/RR6doSBIYh7sTm9iuFSi
25 | LjEfl1cGGaE2GP+SyPb2kvLnQSymd/S5LwffO33p1yGyhTXtl0vF7sy3VggBtpJl
26 | 8dNyo8v+IIYgmxZ0OT6YmCQZgi9bsJVEGmWnSn4iX1CGQXcAmU7XCg==
27 | -----END RSA PRIVATE KEY-----
28 |
--------------------------------------------------------------------------------
/components/oap-aws/test/1cbf751210-public.pem.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PUBLIC KEY-----
2 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAliWltCakYPKTGGZui30r
3 | jJRswJhJWwKyg13uH/iwN3c7EmRu2cV+qf8hHD8MeXTLSY4atQTpSbv6S/vC5CZH
4 | 5blHlbe6HpnUSTdQP4HH8DfjmO209UUN3Bm3gmT+WPgD3H0tQmoNuYtBPYMHiDpv
5 | WhA29t4QK9NhaLEEI3mgzh6c+EHpT5whr8okAJLcY8hu+0V0YNB/XLID8JJJXH5x
6 | LdM/QbIfXanR+UerZHSc/KE5WwRQuVS7ttCnLtS3RvNhiCeqduLl3CSyjVnLJugn
7 | P56sX8U5Myq4CPuLIuGMmv51CUpE2J5xVvM4JNxcPHTQp6XzH4MmdJoaFzrxbe4i
8 | jwIDAQAB
9 | -----END PUBLIC KEY-----
10 |
--------------------------------------------------------------------------------
/components/oap-aws/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
7 | COMPONENT_EMBED_TXTFILES := 1cbf751210-certificate.pem.crt
8 | COMPONENT_EMBED_TXTFILES += 1cbf751210-private.pem.key
--------------------------------------------------------------------------------
/components/oap-aws/test/test_awsiot.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include "unity.h"
6 | #include "oap_storage.h"
7 | #include "awsiot.h"
8 | #include "oap_test.h"
9 |
10 | static const char* TAG = "test_awsiot";
11 |
12 | extern const uint8_t device_cert_pem_start[] asm("_binary_1cbf751210_certificate_pem_crt_start");
13 | extern const uint8_t device_cert_pem_end[] asm("_binary_1cbf751210_certificate_pem_crt_end");
14 |
15 | extern const uint8_t device_pkey_pem_start[] asm("_binary_1cbf751210_private_pem_key_start");
16 | extern const uint8_t device_pkey_pem_end[] asm("_binary_1cbf751210_private_pem_key_end");
17 |
18 | static esp_err_t publish() {
19 | oap_measurement_t meas = {
20 | .local_time = 1505156826
21 | };
22 |
23 | oap_sensor_config_t sensor_config = {
24 | .0
25 | };
26 | return awsiot_publisher.publish(&meas, &sensor_config);
27 | }
28 |
29 | static void setup() {
30 | cJSON* cfg = cJSON_CreateObject();
31 | cJSON_AddNumberToObject(cfg, "enabled", 1);
32 | cJSON_AddStringToObject(cfg, "thingName", "test_device_1");
33 | cJSON_AddStringToObject(cfg, "endpoint", "a32on3oilq3poc.iot.eu-west-1.amazonaws.com");
34 | cJSON_AddNumberToObject(cfg, "port", 8443);
35 | char* cert = str_make((void*)device_cert_pem_start, device_cert_pem_end-device_cert_pem_start);
36 | char* pkey = str_make((void*)device_pkey_pem_start, device_pkey_pem_end-device_pkey_pem_start);
37 | cJSON_AddStringToObject(cfg, "cert", cert);
38 | cJSON_AddStringToObject(cfg, "pkey", pkey);
39 |
40 | TEST_ESP_OK(awsiot_publisher.configure(cfg));
41 | cJSON_Delete(cfg);
42 | free(cert);
43 | free(pkey);
44 | }
45 |
46 | TEST_CASE("publish to awsiot", "[awsiot]")
47 | {
48 | setup();
49 | test_require_wifi();
50 | size_t curr_heap = 0;
51 | size_t prev_heap = 0;
52 |
53 | /*
54 | * heap consumption goes to 0 after ~40 requests
55 | */
56 | for (int i = 0; i < 1; i++) {
57 | curr_heap = xPortGetFreeHeapSize();
58 | ESP_LOGW(TAG, "REQUEST %d (heap %u, %d bytes)", i, curr_heap, curr_heap-prev_heap);
59 | prev_heap = curr_heap;
60 | TEST_ESP_OK(publish());
61 | if (i) test_delay(1000);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/components/oap-aws/verisign_root_ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
3 | yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
4 | ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
5 | U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
6 | ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
7 | aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
8 | MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
9 | ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
10 | biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
11 | U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
12 | aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
13 | nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
14 | t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
15 | SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
16 | BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
17 | rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
18 | NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
19 | BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
20 | BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
21 | aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
22 | MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
23 | p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
24 | 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
25 | WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
26 | 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
27 | hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
28 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/components/oap-common/c_list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * c_utils.c
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 |
25 |
26 | #include
27 |
28 | #include "c_list.h"
29 |
30 | /**
31 | * A list is an ordered set of entries. We have the following primitives:
32 | * * list_create() - Create an empty list. The return is the list pointer.
33 | * * list_delete() - Delete the list and optionally free all its entries.
34 | * * list_first() - Return the first item in the list.
35 | * * list_insert() - Add an item to the end of the list.
36 | * * list_insert_after() - Add an item to the list after a given entry.
37 | * * list_insert_before() - Add an item to the list before a given entry.
38 | * * list_next() - Get the next item in the list.
39 | * * list_remove() - Remove a specific item from the list.
40 | * * list_removeByValue() - Find the first element in the list with a matching value and remove it.
41 | */
42 |
43 | /**
44 | * Create a new list.
45 | */
46 | list_t *list_createList() {
47 | list_t *pList = malloc(sizeof(list_t));
48 | pList->next = NULL;
49 | pList->prev = NULL;
50 | pList->value = NULL;
51 | return pList;
52 | } // list_createList
53 |
54 | /**
55 | * Delete a list.
56 | */
57 | void list_deleteList(list_t *pList, int withFree) {
58 | list_t *pNext;
59 | while(pList != NULL) {
60 | pNext = pList->next;
61 | if (withFree) {
62 | free(pList->value);
63 | }
64 | free(pList);
65 | pList = pNext;
66 | }
67 | } // list_deleteList
68 |
69 | void list_deleteListAndValues(list_t *pList, node_value_predicate disposer) {
70 | list_t *pNext;
71 | while(pList != NULL) {
72 | pNext = pList->next;
73 | if (pList->value) {
74 | disposer(pList->value);
75 | }
76 | free(pList);
77 | pList = pNext;
78 | }
79 | }
80 |
81 | /**
82 | * Insert a new item at the end of the list.
83 | *[A] -> [endOLD] ------> [A] -> [endOLD] -> [X]
84 | *
85 | */
86 | void list_insert(list_t *pList, void *value) {
87 | while(pList->next != NULL) {
88 | pList = pList->next;
89 | }
90 | list_insert_after(pList, value);
91 | } // list_insert
92 |
93 | /**
94 | * [pEntry] -> [B] ------> [pEntry] -> [X] -> [B]
95 | *
96 | */
97 | void list_insert_after(list_t *pEntry, void *value) {
98 | list_t *pNew = malloc(sizeof(list_t));
99 | pNew->next = pEntry->next;
100 | pNew->prev = pEntry;
101 | pNew->value = value;
102 |
103 | // Order IS important here.
104 | if (pEntry->next != NULL) {
105 | pEntry->next->prev = pNew;
106 | }
107 | pEntry->next = pNew;
108 | } // list_insert_after
109 |
110 | /**
111 | * [A] -> [pEntry] ------> [A] -> [X] -> [pEntry]
112 | *
113 | */
114 | void list_insert_before(list_t *pEntry, void *value) {
115 | // Can't insert before the list itself.
116 | if (pEntry->prev == NULL) {
117 | return;
118 | }
119 | list_t *pNew = malloc(sizeof(list_t));
120 | pNew->next = pEntry;
121 | pNew->prev = pEntry->prev;
122 | pNew->value = value;
123 |
124 | // Order IS important here.
125 | pEntry->prev->next = pNew;
126 | pEntry->prev = pNew;
127 | } // list_insert_before
128 |
129 | /**
130 | * Remove an item from the list.
131 | */
132 | void list_remove(list_t *pList, list_t *pEntry, int withFree) {
133 | while(pList != NULL && pList->next != pEntry) {
134 | pList = pList->next;
135 | }
136 | if (pList == NULL) {
137 | return;
138 | }
139 | pList->next = pEntry->next;
140 | if (pEntry->next != NULL) {
141 | pEntry->next->prev = pList;
142 | }
143 | if (withFree) {
144 | free(pEntry->value);
145 | }
146 | free(pEntry);
147 | } // list_delete
148 |
149 | /**
150 | * Delete a list entry by value.
151 | */
152 | void list_removeByValue(list_t *pList, void *value, int withFree) {
153 | list_t *pNext = pList->next;
154 | while(pNext != NULL) {
155 | if (pNext->value == value) {
156 | list_remove(pList, pNext, withFree);
157 | return;
158 | }
159 | } // End while
160 | } // list_deleteByValue
161 |
162 | /**
163 | * Find a list node with given value
164 | */
165 | list_t *list_find(list_t *pList, node_value_predicate predicate) {
166 | list_t *pNext = pList->next;
167 | while(pNext != NULL && !predicate(pNext->value)) {
168 | pNext = pNext->next;
169 | }
170 | return pNext;
171 | }
172 |
173 | /**
174 | * Get the next item in a list.
175 | */
176 | list_t *list_next(list_t *pList) {
177 | if (pList == NULL) {
178 | return NULL;
179 | }
180 | return (pList->next);
181 | } // list_next
182 |
183 |
184 | list_t *list_first(list_t *pList) {
185 | return pList->next;
186 | } // list_first
187 |
188 | void *list_get_value(list_t *pList) {
189 | return pList->value;
190 | }
191 |
--------------------------------------------------------------------------------
/components/oap-common/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
10 | COMPONENT_EMBED_TXTFILES := default_config.json
--------------------------------------------------------------------------------
/components/oap-common/default_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "wifi": {
3 | "ssid": "",
4 | "password": "",
5 | "ip": "",
6 | "gw": "",
7 | "netmask": ""
8 | },
9 | "thingspeak": {
10 | "enabled": 0,
11 | "apikey": ""
12 | },
13 | "awsiot" : {
14 | "enabled": 0,
15 | "endpoint" : "a32on3oilq3poc.iot.eu-west-1.amazonaws.com",
16 | "port" : 8443
17 | },
18 | "ota" : {
19 | "interval" : 3600
20 | },
21 | "sensor" : {
22 | "config" : {
23 | "indoor" : 0,
24 | "led" : 1,
25 | "fan" : 1,
26 | "heater" : 1,
27 | "measTime" : 60,
28 | "warmUpTime": 30,
29 | "measInterval": 300,
30 | "test" : 0,
31 | "measStrategy": 0
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/components/oap-common/include/c_list.h:
--------------------------------------------------------------------------------
1 | /*
2 | * c_utils.h
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_C_UTILS_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_C_UTILS_H_
25 |
26 |
27 | /*
28 | * c_utils.h
29 | *
30 | * Created on: Nov 15, 2016
31 | * Author: kolban
32 | */
33 |
34 | typedef struct _list_t {
35 | void *value;
36 | struct _list_t *next;
37 | struct _list_t *prev;
38 | } list_t;
39 |
40 | //typedef int(*node_value_comparator)(void* a, void* b);
41 | typedef int(*node_value_predicate)(void* data);
42 |
43 | list_t *list_createList();
44 | void list_deleteList(list_t *pList, int withFree);
45 | void list_deleteListAndValues(list_t *pList, node_value_predicate disposer);
46 | void list_insert(list_t *pList, void *value);
47 | void list_remove(list_t *pList, list_t *pEntry, int withFree);
48 | list_t *list_next(list_t *pList);
49 | void list_removeByValue(list_t *pList, void *value, int withFree);
50 | list_t *list_first(list_t *pList);
51 | void list_insert_after(list_t *pEntry, void *value);
52 | void list_insert_before(list_t *pEntry, void *value);
53 | void *list_get_value(list_t *pList);
54 | list_t *list_find(list_t *pList, node_value_predicate predicate);
55 |
56 |
57 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_C_UTILS_H_ */
58 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_common.h:
--------------------------------------------------------------------------------
1 | /*
2 | * common.h
3 | *
4 | * Created on: Feb 9, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_COMMON_COMMON_H_
24 | #define MAIN_COMMON_COMMON_H_
25 |
26 | #include "oap_version.h"
27 | #include
28 | #include
29 | #include
30 | #include
31 | #include
32 | #include "c_list.h"
33 | #include "esp_err.h"
34 | #include "esp_log.h"
35 | #include "freertos/FreeRTOS.h"
36 |
37 | //to silence eclipse errors
38 | typedef unsigned short uint16_t;
39 |
40 |
41 |
42 | #define DEFAULT_TASK_PRIORITY (10)
43 |
44 | int is_reboot_in_progress();
45 | void oap_reboot(char* cause);
46 |
47 | long oap_epoch_sec();
48 | long oap_epoch_sec_valid();
49 |
50 | //from esp-arduino
51 |
52 | /**
53 | * creates a new string terminated with 0 from passed data.
54 | * free it after use.
55 | */
56 | char* str_make(void* data, int len);
57 |
58 | /*
59 | * allocates mem and copies src->dest
60 | */
61 | char* str_dup(char* src);
62 |
63 | //#define ESP_REG(addr) *((volatile uint32_t *)(addr))
64 | #define NOP() asm volatile ("nop")
65 |
66 | uint32_t micros();
67 | uint32_t millis();
68 | void delay(uint32_t);
69 | void delayMicroseconds(uint32_t us);
70 |
71 | #endif /* MAIN_COMMON_COMMON_H_ */
72 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_data.h
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_H_
25 |
26 | #include "oap_data_pm.h"
27 | #include "oap_data_env.h"
28 |
29 | typedef struct {
30 | pm_data_t* pm;
31 | pm_data_t* pm_aux;
32 | env_data_t* env;
33 | env_data_t* env_int;
34 | long int local_time;
35 | } oap_measurement_t;
36 |
37 | typedef struct {
38 | int led;
39 | int heater;
40 | int fan;
41 |
42 | int indoor;
43 | int warm_up_time;
44 | int meas_time;
45 | int meas_interval;
46 | int meas_strategy; //interval, continuos, etc
47 | int test;
48 | } oap_sensor_config_t;
49 |
50 |
51 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_H_ */
52 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_data_env.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_data_env.h
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_ENV_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_ENV_H_
25 |
26 | typedef struct {
27 | double temp;
28 | double pressure;
29 | double humidity;
30 | uint8_t sensor_idx;
31 | } env_data_t;
32 |
33 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_ENV_H_ */
34 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_data_pm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_data_pm.h
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_PM_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_PM_H_
25 |
26 | typedef struct {
27 | uint16_t pm1_0;
28 | uint16_t pm2_5;
29 | uint16_t pm10;
30 | uint8_t sensor_idx;
31 | } pm_data_t;
32 |
33 | typedef void(*pm_data_callback_f)(pm_data_t*);
34 |
35 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_OAP_DATA_PM_H_ */
36 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_debug.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_debug.h
3 | *
4 | * Created on: Mar 13, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | typedef struct heap_log {
24 | size_t heap;
25 | char* tag;
26 | struct heap_log* next;
27 | } heap_log;
28 |
29 | void heap_log_print(heap_log* log, heap_log* prev);
30 | heap_log* heap_log_take(heap_log* log, const char* msg);
31 | void heap_log_free(heap_log* log);
32 |
33 | size_t avg_free_heap_size();
34 |
35 | void log_task_stack(const char* task);
36 | void log_heap_size(const char* msg);
37 | void reduce_heap_size_to(size_t size);
38 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_publisher.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_publisher.h
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_OAP_PUBLISHER_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_OAP_PUBLISHER_H_
25 |
26 | #include "cJSON.h"
27 | #include "oap_data.h"
28 | #include "esp_err.h"
29 |
30 | typedef esp_err_t(*oap_publisher_configure_f)(cJSON* config);
31 | typedef esp_err_t(*oap_publisher_publish_f)(oap_measurement_t* meas, oap_sensor_config_t* sensor_config);
32 |
33 | typedef struct {
34 | char* name;
35 | oap_publisher_configure_f configure;
36 | oap_publisher_publish_f publish;
37 | } oap_publisher_t;
38 |
39 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_OAP_PUBLISHER_H_ */
40 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_storage.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_storage.h
3 | *
4 | * Created on: Feb 11, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_INCLUDE_OAP_STORAGE_H_
24 | #define COMPONENTS_OAP_COMMON_INCLUDE_OAP_STORAGE_H_
25 |
26 | #include
27 | #include "cJSON.h"
28 |
29 |
30 | /**
31 | * @brief initialise storage and config
32 | */
33 | void storage_init();
34 |
35 | /**
36 | * @brief return config for given submodule
37 | *
38 | * @param[in] module name of a submodule, e.g. 'wifi' or NULL to retrieve full config tree
39 | *
40 | * @return config JSON. DO NOT free or modify the result, it is a singleton!
41 | */
42 | cJSON* storage_get_config(const char* module);
43 |
44 |
45 | /**
46 | * @brief returns config json as a string
47 | *
48 | * sensitive data (wifi password) is replaced with constant string
49 | *
50 | * @return config json. free it after use!
51 | */
52 | cJSON* storage_get_config_to_update();
53 |
54 |
55 | /**
56 | * @bried updates json config
57 | *
58 | * sensitive data (wifi password) that has not been changed is being replaced with proper values.
59 | *
60 | * @param[in] json config
61 | */
62 | void storage_update_config(cJSON* config);
63 |
64 |
65 | #endif /* COMPONENTS_OAP_COMMON_INCLUDE_OAP_STORAGE_H_ */
66 |
--------------------------------------------------------------------------------
/components/oap-common/include/oap_version.h:
--------------------------------------------------------------------------------
1 | /*
2 | * version.h
3 | *
4 | * Created on: Sep 7, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_INCLUDE_OAP_VERSION_H_
24 | #define MAIN_INCLUDE_OAP_VERSION_H_
25 |
26 | /**
27 | * http://semver.org/
28 | *
29 | * Given a version number MAJOR.MINOR.PATCH, increment the:
30 | *
31 | * MAJOR version when you make incompatible API changes,
32 | * MINOR version when you add functionality in a backwards-compatible manner, and
33 | * PATCH version when you make backwards-compatible bug fixes.
34 | */
35 |
36 | #include
37 | #include "esp_err.h"
38 |
39 | #define OAP_VER_MAJOR 1
40 | #define OAP_VER_MINOR 2
41 | #define OAP_VER_PATCH 0
42 |
43 | typedef struct {
44 | uint8_t major;
45 | uint8_t minor;
46 | uint8_t patch;
47 | } oap_version_t;
48 |
49 | oap_version_t oap_version();
50 | char* oap_version_str();
51 | char* oap_version_format(oap_version_t ver);
52 | esp_err_t oap_version_parse(char* str, oap_version_t* ver);
53 | unsigned long oap_version_num(oap_version_t ver);
54 |
55 | #endif /* MAIN_INCLUDE_OAP_VERSION_H_ */
56 |
--------------------------------------------------------------------------------
/components/oap-common/oap_common.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_common.c
3 | *
4 | * Created on: Feb 22, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 | #include
25 | #include
26 | #include "freertos/FreeRTOS.h"
27 | #include
28 | #include "oap_common.h"
29 | #include "esp_attr.h"
30 | #include "esp_log.h"
31 | #include "esp_system.h"
32 | #include "freertos/task.h"
33 |
34 | static const long FEB22_2017 = 1487795557;
35 |
36 | static int _reboot_in_progress = 0;
37 | int is_reboot_in_progress() {
38 | return _reboot_in_progress;
39 | }
40 | void oap_reboot(char* cause) {
41 | ESP_LOGW("oap", "REBOOT ON DEMAND (%s)", cause);
42 | _reboot_in_progress = 1;
43 | esp_restart();
44 | }
45 |
46 | long oap_epoch_sec() {
47 | struct timeval tv_start;
48 | gettimeofday(&tv_start, NULL);
49 | return tv_start.tv_sec;
50 | }
51 |
52 | long oap_epoch_sec_valid() {
53 | long epoch = oap_epoch_sec();
54 | return epoch > FEB22_2017 ? epoch : 0;
55 | }
56 |
57 | char* str_make(void* data, int len) {
58 | char* str = malloc(len+1);
59 | memcpy(str, data, len);
60 | str[len] = 0;
61 | return str;
62 | }
63 |
64 | char* str_dup(char* src) {
65 | char* dest = malloc(strlen(src)+1);
66 | strcpy(dest, src);
67 | return dest;
68 | }
69 |
70 | void yield()
71 | {
72 | vPortYield();
73 | }
74 |
75 | uint32_t IRAM_ATTR micros()
76 | {
77 | uint32_t ccount;
78 | __asm__ __volatile__ ( "rsr %0, ccount" : "=a" (ccount) );
79 | return ccount / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
80 | }
81 |
82 | uint32_t IRAM_ATTR millis()
83 | {
84 | return xTaskGetTickCount() * portTICK_PERIOD_MS;
85 | }
86 |
87 | void delay(uint32_t ms)
88 | {
89 | vTaskDelay(ms / portTICK_PERIOD_MS);
90 | }
91 |
92 | void IRAM_ATTR delayMicroseconds(uint32_t us)
93 | {
94 | uint32_t m = micros();
95 | if(us){
96 | uint32_t e = (m + us) % ((0xFFFFFFFF / CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) + 1);
97 | if(m > e){ //overflow
98 | while(micros() > e){
99 | NOP();
100 | }
101 | }
102 | while(micros() < e){
103 | NOP();
104 | }
105 | }
106 | }
107 |
108 |
109 |
--------------------------------------------------------------------------------
/components/oap-common/oap_debug.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_debug.c
3 | *
4 | * Created on: Mar 13, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include
24 | #include
25 | #include "freertos/FreeRTOS.h"
26 | #include
27 | #include "oap_debug.h"
28 | #include "esp_attr.h"
29 | #include "esp_log.h"
30 | #include "freertos/task.h"
31 |
32 | #define TAG "mem"
33 | /**
34 | * this method is surprisingly stack heavy - it takes ~ 1000 bytes.
35 | * before using it, adjust task stack accordingly.
36 | */
37 | void log_task_stack(const char* task) {
38 | //uxTaskGetStackHighWaterMark is marked as UNTESTED
39 | #if !CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION
40 | ESP_LOGD(TAG, "stack min %d (task %s)", uxTaskGetStackHighWaterMark( NULL ), task);
41 | #endif
42 | }
43 |
44 | /**
45 | * current free heap is not very useful because it changes dynamically with multiple tasks running in parallel.
46 | * to detect any leaks, we use a time window and choose the max value as real 'free heap'
47 | */
48 | #define SAMPLES 10
49 | static size_t heap_samples[SAMPLES] = {.0};
50 | uint8_t sample_idx = 0;
51 |
52 | size_t avg_free_heap_size() {
53 | size_t max = 0;
54 | for (int i = 0; i < SAMPLES; i++) {
55 | if (heap_samples[i] > max) max = heap_samples[i];
56 | }
57 | return max;
58 | }
59 |
60 | void log_heap_size(const char* msg) {
61 | size_t free_heap = xPortGetFreeHeapSize();
62 | if (heap_samples[sample_idx%SAMPLES] == 0) heap_samples[sample_idx%SAMPLES] = free_heap;
63 |
64 | ESP_LOGD(TAG, "heap min %d avg %d (%s)",
65 | xPortGetMinimumEverFreeHeapSize(),
66 | avg_free_heap_size(),
67 | msg);
68 | heap_samples[sample_idx%SAMPLES] = free_heap;
69 | sample_idx++;
70 | }
71 |
72 | static void* dummy;
73 | void reduce_heap_size_to(size_t size) {
74 | size_t reduce_by = xPortGetFreeHeapSize() - size;
75 | if (reduce_by > 0) {
76 | ESP_LOGE(TAG, "********************** REDUCE HEAP BY %d TO %d bytes !!!!!!!!!!!", reduce_by, size);
77 | do {
78 | size_t block = reduce_by > 10000 ? 10000 : reduce_by;
79 | reduce_by-=block;
80 | dummy = malloc(block);
81 | if (!dummy) {
82 | ESP_LOGE(TAG, "FAILED TO ALLOCATE!");
83 | }
84 | } while (reduce_by > 0);
85 | }
86 | }
87 |
88 | static int heap_log_count = 0;
89 |
90 | /*
91 | | 100 |
92 | | -1 |
93 | 99 | | 100 (c=1)
94 | | -10 |
95 | | -1 |
96 | 88 | | 90 (c=2)
97 | */
98 |
99 | void heap_log_list(heap_log* log) {
100 | heap_log* prev = NULL;
101 | int c = 0;
102 | while (log) {
103 | c++;
104 | heap_log_print(log, prev);
105 | prev = log;
106 | log = log->next;
107 | }
108 | }
109 |
110 | void heap_log_print(heap_log* log, heap_log* prev) {
111 | size_t comp_heap = log->heap + heap_log_count * sizeof(heap_log);
112 | if (prev == NULL) {
113 | ESP_LOGD("debug", "----------> heap %25s: %d", log->tag, comp_heap);
114 | } else {
115 | size_t diff_heap = log->heap - prev->heap + sizeof(heap_log);
116 | ESP_LOGD("debug", "----------> heap %25s: %d \t (%d)", log->tag, comp_heap, diff_heap);
117 | }
118 | }
119 |
120 | heap_log* heap_log_take(heap_log* log, const char* msg) {
121 | heap_log* new_log = malloc(sizeof(heap_log));
122 | heap_log_count++;
123 | new_log->tag = strdup(msg);
124 | new_log->next = NULL;
125 |
126 | //find tail
127 | if (log != NULL) {
128 | while (log->next) {
129 | log = log->next;
130 | }
131 | log->next = new_log;
132 | }
133 |
134 | new_log->heap = xPortGetFreeHeapSize();
135 | //heap_log_print(new_log, log);
136 | return new_log;
137 | }
138 |
139 | void heap_log_free(heap_log* log) {
140 | if (log) {
141 | size_t initial_heap = log->heap;
142 |
143 | heap_log_list(log);
144 | heap_log* next;
145 | do {
146 | next = log->next;
147 | free(log->tag);
148 | free(log);
149 | heap_log_count--;
150 | log = next;
151 | } while (log);
152 |
153 |
154 | ESP_LOGD("debug", "----------> leaked : %d", xPortGetFreeHeapSize() - initial_heap);
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/components/oap-common/oap_version.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_version.c
3 | *
4 | * Created on: Sep 7, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "oap_version.h"
24 | #include
25 | #include
26 | #include "esp_err.h"
27 |
28 | static oap_version_t _oap_version = { .major = OAP_VER_MAJOR, .minor = OAP_VER_MINOR, .patch = OAP_VER_PATCH };
29 | static char* _oap_version_str = NULL;
30 |
31 | static const char* VER_FORMAT="%d.%d.%d";
32 |
33 | char* oap_version_format(oap_version_t ver) {
34 | char* str = malloc(snprintf( NULL, 0, VER_FORMAT, ver.major, ver.minor, ver.patch)+1);
35 | sprintf(str, VER_FORMAT, ver.major, ver.minor, ver.patch);
36 | return str;
37 | }
38 |
39 | oap_version_t oap_version() {
40 | return _oap_version;
41 | }
42 |
43 | char* oap_version_str() {
44 | if (!_oap_version_str) {
45 | _oap_version_str = oap_version_format(_oap_version);
46 | }
47 | return _oap_version_str;
48 | }
49 |
50 | unsigned long oap_version_num(oap_version_t ver) {
51 | return 10000 * ver.major + 100 * ver.minor + ver.patch;
52 | }
53 |
54 | esp_err_t oap_version_parse(char* str, oap_version_t* ver)
55 | {
56 | int i = 0;
57 | while (str[i] != 0 && str[i] != '.') i++;
58 | if (str[i] != '.') return ESP_FAIL;
59 | int major = atoi(str);
60 | i++;
61 | int minor = atoi(str+i);
62 | while (str[i] != 0 && str[i] != '.') i++;
63 | if (str[i] != '.') return ESP_FAIL;
64 | i++;
65 | int patch = atoi(str+i);
66 |
67 | ver->major = major;
68 | ver->minor = minor;
69 | ver->patch = patch;
70 |
71 | return ESP_OK;
72 | }
73 |
74 |
75 |
--------------------------------------------------------------------------------
/components/oap-common/test/.gitignore:
--------------------------------------------------------------------------------
1 | test_wifi.h
--------------------------------------------------------------------------------
/components/oap-common/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-common/test/include/oap_test.h:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_test.h
3 | *
4 | * Created on: Sep 11, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OAP_COMMON_TEST_INCLUDE_OAP_TEST_H_
24 | #define COMPONENTS_OAP_COMMON_TEST_INCLUDE_OAP_TEST_H_
25 |
26 | #include "unity.h"
27 | #include "esp_log.h"
28 | #include "freertos/FreeRTOS.h"
29 | #include "bootwifi.h"
30 |
31 | #define TEST "TEST"
32 |
33 | void test_reset_hw();
34 | /**
35 | * init wifi, do not wait for IP
36 | */
37 | void test_init_wifi();
38 |
39 | /**
40 | * init wifi and wait for IP
41 | */
42 | void test_require_wifi();
43 |
44 | void test_require_wifi_with(wifi_state_callback_f callback);
45 |
46 | void test_require_ap();
47 |
48 | void test_require_ap_with(wifi_state_callback_f callback);
49 |
50 | typedef struct {
51 | uint32_t started;
52 | uint32_t wait_for;
53 | } test_timer_t;
54 |
55 | int test_timeout(test_timer_t* t);
56 |
57 | void test_delay(uint32_t ms);
58 |
59 | #endif /* COMPONENTS_OAP_COMMON_TEST_INCLUDE_OAP_TEST_H_ */
60 |
--------------------------------------------------------------------------------
/components/oap-common/test/oap_test.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_test.c
3 | *
4 | * Created on: Sep 11, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "esp_log.h"
24 | #include "oap_test.h"
25 | #include "bootwifi.h"
26 | #include "test_wifi.h"
27 | #include "unity.h"
28 |
29 | #include "esp_attr.h"
30 | #include "esp_log.h"
31 | #include "esp_system.h"
32 | #include
33 |
34 | static const char* TAG = "test";
35 |
36 | extern oc_wifi_t oap_wifi_config;
37 |
38 | void test_require_wifi() {
39 | test_require_wifi_with(NULL);
40 | }
41 |
42 | void test_require_wifi_with(wifi_state_callback_f wifi_state_callback) {
43 | memset(&oap_wifi_config, 0, sizeof(oap_wifi_config));
44 | strcpy(oap_wifi_config.ssid, OAP_TEST_WIFI_SSID);
45 | strcpy(oap_wifi_config.password,OAP_TEST_WIFI_PASSWORD);
46 | oap_wifi_config.callback = wifi_state_callback;
47 | wifi_boot();
48 | TEST_ESP_OK(wifi_connected_wait_for(10000));
49 | ESP_LOGI(TAG, "connected sta");
50 | }
51 |
52 | void test_require_ap() {
53 | test_require_ap_with(NULL);
54 | }
55 |
56 | void test_require_ap_with(wifi_state_callback_f wifi_state_callback) {
57 | memset(&oap_wifi_config, 0, sizeof(oap_wifi_config));
58 | oap_wifi_config.ap_mode=1;
59 | oap_wifi_config.callback = wifi_state_callback;
60 | wifi_boot();
61 | TEST_ESP_OK(wifi_ap_started_wait_for(10000));
62 | ESP_LOGI(TAG, "connected ap");
63 | }
64 |
65 | static uint32_t IRAM_ATTR time_now()
66 | {
67 | return xTaskGetTickCount() * portTICK_PERIOD_MS;
68 | }
69 |
70 | int test_timeout(test_timer_t* t) {
71 | if (t->started <= 0) t->started = time_now();
72 | return time_now() - t->started > t->wait_for;
73 | }
74 |
75 | void test_delay(uint32_t ms)
76 | {
77 | vTaskDelay(ms / portTICK_PERIOD_MS);
78 | }
79 |
80 | static void configure_gpio(uint8_t gpio) {
81 | if (gpio > 0) {
82 | ESP_LOGD(TAG, "configure pin %d as output", gpio);
83 | gpio_pad_select_gpio(gpio);
84 | ESP_ERROR_CHECK(gpio_set_direction(gpio, GPIO_MODE_OUTPUT));
85 | ESP_ERROR_CHECK(gpio_set_pull_mode(gpio, GPIO_PULLDOWN_ONLY));
86 | }
87 | }
88 |
89 | void test_reset_hw() {
90 | ESP_LOGI(TAG,"reset peripherals");
91 | configure_gpio(GPIO_NUM_10); //disable pm1
92 | configure_gpio(GPIO_NUM_2); //disable pm2
93 | }
94 |
--------------------------------------------------------------------------------
/components/oap-common/test/sandbox.c:
--------------------------------------------------------------------------------
1 | /*
2 | * sandbox.c
3 | *
4 | * Created on: Sep 12, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "unity.h"
29 | #include "nvs.h"
30 | #include "nvs_flash.h"
31 | #include "esp_partition.h"
32 | #include "esp_log.h"
33 | #include
34 | #include "esp_system.h"
35 |
36 | /*
37 | typedef struct {
38 | uint8_t num;
39 | char* str;
40 | } sample_struct;
41 |
42 | static const char* TAG = "test";
43 |
44 | void* modify_struct_by_value(sample_struct ss) {
45 | ss.num++;
46 | ss.str = "modified!";
47 | //warning: function returns address of local variable [-Wreturn-local-addr]
48 | return &ss;
49 | }
50 |
51 | void modify_struct_by_ref(sample_struct* ss) {
52 | ss->num++;
53 | ss->str = "modified!"; //what happens with assigned string? tricky - if it was a const we cannot release it. prefer immutable structs!
54 | }
55 |
56 | TEST_CASE("structs","sandbox") {
57 | sample_struct ss = {
58 | .num = 1,
59 | .str = "hello"
60 | };
61 |
62 | void* ssp = modify_struct_by_value(ss);
63 |
64 | TEST_ASSERT_EQUAL_STRING("hello", ss.str);
65 | TEST_ASSERT_EQUAL_INT(1, ss.num);
66 | TEST_ASSERT_EQUAL_INT32(0, ssp);
67 |
68 | char* str = ss.str;
69 | modify_struct_by_ref(&ss);
70 | TEST_ASSERT_EQUAL_STRING("modified!", ss.str);
71 | TEST_ASSERT_EQUAL_INT(2, ss.num);
72 |
73 | ESP_LOGI(TAG, "old str:%s", str);
74 | //str[0] = '!'; //error (const allocation)
75 | //free(str); //error free() target pointer is outside heap areas
76 | }*/
77 |
78 | /*
79 | TEST_CASE("mac", "sandbox") {
80 | uint8_t mac[6];
81 | esp_efuse_mac_get_default(mac);
82 | ESP_LOGD("TST", "MAC= %02X:%02X:%02X:%02X:%02X:%02X",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
83 | }
84 | */
85 |
--------------------------------------------------------------------------------
/components/oap-common/test/test_oap_version.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_test.c
3 | *
4 | * Created on: Sep 11, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "unity.h"
29 | #include "nvs.h"
30 | #include "nvs_flash.h"
31 | #include "esp_partition.h"
32 | #include "esp_log.h"
33 | #include
34 | #include "oap_version.h"
35 |
36 | static void parse_format_verify(char* input, char* output) {
37 | oap_version_t ver;
38 | char* str;
39 |
40 | memset(&ver, 0, sizeof(ver));
41 | TEST_ESP_OK(oap_version_parse(input, &ver));
42 | str = oap_version_format(ver);
43 | TEST_ASSERT_EQUAL_STRING(output, str);
44 | free(str);
45 | }
46 |
47 | TEST_CASE("parse and format version","oap_version") {
48 | parse_format_verify("1.2.3","1.2.3");
49 | parse_format_verify("0.4.0","0.4.0");
50 | parse_format_verify("012.034.056","12.34.56");
51 | }
52 |
53 | TEST_CASE("version to num","oap_version") {
54 | oap_version_t v1 = {
55 | .major = 12,
56 | .minor = 34,
57 | .patch = 56,
58 |
59 | };
60 | TEST_ASSERT_EQUAL_UINT32(123456, oap_version_num(v1));
61 |
62 | oap_version_t v2 = {
63 | .major = 0,
64 | .minor = 4,
65 | .patch = 0,
66 |
67 | };
68 | TEST_ASSERT_EQUAL_UINT32(400, oap_version_num(v2));
69 | }
70 |
--------------------------------------------------------------------------------
/components/oap-http/README.md:
--------------------------------------------------------------------------------
1 | # Lightweight HTTP client for ESP32
2 | ## Example
3 |
4 | ```cpp
5 | int download_callback(request_t *req, char *data, int len)
6 | {
7 | req_list_t *found = req->response->header;
8 | while(found->next != NULL) {
9 | found = found->next;
10 | ESP_LOGI(TAG,"Response header %s:%s", (char*)found->key, (char*)found->value);
11 | }
12 | //or
13 | found = req_list_get_key(req->response->header, "Content-Length");
14 | if(found) {
15 | ESP_LOGI(TAG,"Get header %s:%s", (char*)found->key, (char*)found->value);
16 | }
17 | ESP_LOGI(TAG,"%s", data);
18 | return 0;
19 | }
20 | static void request_task(void *pvParameters)
21 | {
22 | request_t *req;
23 | int status;
24 | xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
25 | ESP_LOGI(TAG, "Connected to AP, freemem=%d",esp_get_free_heap_size());
26 | // vTaskDelay(1000/portTICK_RATE_MS);
27 | req = req_new("http://httpbin.org/post");
28 | //or
29 | //request *req = req_new("https://google.com"); //for SSL
30 | req_setopt(req, REQ_SET_METHOD, "POST");
31 | req_setopt(req, REQ_SET_POSTFIELDS, "test=data&test2=data2");
32 | req_setopt(req, REQ_FUNC_DOWNLOAD_CB, download_callback);
33 | status = req_perform(req);
34 | req_clean(req);
35 | vTaskDelete(NULL);
36 | }
37 |
38 | ```
39 |
40 | ## Usage
41 | - Create ESP-IDF application https://github.com/espressif/esp-idf-template
42 | - Clone `git submodule add https://github.com/tuanpmt/esp-request components/esp-request`
43 | - Example `esp-request` application: https://github.com/tuanpmt/esp-request-app
44 | - OTA application using `esp-request`: https://github.com/tuanpmt/esp32-fota
45 |
46 | ## API
47 |
48 | ### Function
49 | - `req_new`
50 | - `req_setopt`
51 | - `req_clean`
52 |
53 | ### Options for `req_setopt`
54 | - REQ_SET_METHOD - `req_setopt(req, REQ_SET_METHOD, "GET");//or POST/PUT/DELETE`
55 | - REQ_SET_HEADER - `req_setopt(req, REQ_SET_HEADER, "HeaderKey: HeaderValue");`
56 | - REQ_SET_HOST - `req_setopt(req, REQ_SET_HOST, "google.com"); //or 192.168.0.1`
57 | - REQ_SET_PORT - `req_setopt(req, REQ_SET_PORT, "80");//must be string`
58 | - REQ_SET_PATH - `req_setopt(req, REQ_SET_PATH, "/path");`
59 | - REQ_SET_SECURITY
60 | - REQ_SET_URI - `req_setopt(req, REQ_SET_URI, "http://uri.com"); //will replace host, port, path, security and Auth if present`
61 | - REQ_SET_DATAFIELDS
62 | - REQ_SET_UPLOAD_LEN - Not effect for now
63 | - REQ_FUNC_DOWNLOAD_CB - `req_setopt(req, REQ_FUNC_DOWNLOAD_CB, download_callback);`
64 | - REQ_FUNC_UPLOAD_CB
65 | - REQ_REDIRECT_FOLLOW - `req_setopt(req, REQ_REDIRECT_FOLLOW, "true"); //or "false"`
66 |
67 | ### URI format
68 | - Follow this: https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
69 |
70 | ## Todo
71 | - [x] Support URI parser
72 | - [x] Follow redirect
73 | - [x] Support SSL
74 | - [x] Support Set POST Fields (simple)
75 | - [ ] Support Basic Auth
76 | - [ ] Support Upload multipart
77 | - [ ] Support Cookie
78 |
79 | ## Known Issues
80 | - ~~Memory leak~~
81 | - Uri parse need more work
82 |
83 | ## Authors
84 | - [Tuan PM](https://twitter.com/tuanpmt)
85 |
--------------------------------------------------------------------------------
/components/oap-http/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # "main" pseudo-component makefile.
3 | #
4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
5 |
6 |
7 |
--------------------------------------------------------------------------------
/components/oap-http/include/esp_request.h:
--------------------------------------------------------------------------------
1 | #ifndef _ESP_REQUEST_H_
2 | #define _ESP_REQUEST_H_
3 | #include "req_list.h"
4 | #include "uri_parser.h"
5 | #include "lwip/sockets.h"
6 | #include "lwip/netdb.h"
7 |
8 | #include "mbedtls/ssl.h"
9 | #include "mbedtls/entropy.h"
10 | #include "mbedtls/ctr_drbg.h"
11 |
12 | #define HTTP_HEADER_CONTENT_TYPE_JSON "Content-Type: application/json"
13 | #define HTTP_HEADER_CONNECTION_CLOSE "Connection: close"
14 | #define HTTP_POST "POST"
15 | #define HTTP_GET "GET"
16 |
17 | typedef enum {
18 | REQ_SET_METHOD = 0x01,
19 | REQ_SET_HEADER,
20 | REQ_SET_HOST,
21 | REQ_SET_PORT,
22 | REQ_SET_PATH,
23 | REQ_SET_URI,
24 | REQ_SET_SECURITY,
25 | REQ_SET_POSTFIELDS,
26 | REQ_SET_DATAFIELDS,
27 | REQ_SET_UPLOAD_LEN,
28 | REQ_FUNC_DOWNLOAD_CB,
29 | REQ_FUNC_UPLOAD_CB,
30 | REQ_REDIRECT_FOLLOW
31 | } REQ_OPTS;
32 |
33 | typedef struct response_t {
34 | req_list_t *header;
35 | int status_code;
36 | int len;
37 | } response_t;
38 |
39 | typedef struct {
40 | size_t buffer_length;
41 | int bytes_read;
42 | int bytes_write;
43 | int bytes_total;
44 | char *data;
45 | int at_eof;
46 | } req_buffer_t;
47 |
48 |
49 | typedef struct {
50 | mbedtls_ssl_context ssl_ctx;
51 | mbedtls_ssl_config ssl_conf;
52 | mbedtls_ctr_drbg_context drbg_ctx;
53 | mbedtls_entropy_context entropy_ctx;
54 | } req_ssl;
55 |
56 | typedef struct request_t {
57 | req_list_t *opt;
58 | req_list_t *header;
59 |
60 | req_buffer_t *buffer;
61 | size_t buffer_size;
62 | void *context;
63 | int socket;
64 | int (*_connect)(struct request_t *req);
65 | int (*_read)(struct request_t *req, char *buffer, int len);
66 | int (*_write)(struct request_t *req, char *buffer, int len);
67 | int (*_close)(struct request_t *req);
68 | int (*upload_callback)(struct request_t *req, void *buffer, int len);
69 | int (*download_callback)(struct request_t *req, void *buffer, int len);
70 | response_t *response;
71 |
72 | //mbedtls
73 | req_ssl* ssl;
74 | mbedtls_x509_crt* ca_cert;
75 | mbedtls_x509_crt* client_cert;
76 | mbedtls_pk_context* client_key;
77 |
78 | //meta
79 | void* meta;
80 |
81 | } request_t;
82 |
83 | typedef int (*download_cb)(request_t *req, void *buffer, int len);
84 | typedef int (*upload_cb)(request_t *req, void *buffer, int len);
85 |
86 |
87 | request_t *req_new(const char *url);
88 | request_t *req_new_with_buf(const char *uri, size_t buffer_size);
89 | void req_setopt(request_t *req, REQ_OPTS opt, void* data);
90 | void req_clean(request_t *req);
91 | int req_perform(request_t *req);
92 |
93 | void req_free_x509_crt(mbedtls_x509_crt* crt);
94 | void req_free_pkey(mbedtls_pk_context* pkey);
95 | mbedtls_x509_crt* req_parse_x509_crt(unsigned char *buf, size_t buflen);
96 | mbedtls_pk_context* req_parse_pkey(unsigned char* buf, size_t buflen);
97 |
98 | #endif
99 |
--------------------------------------------------------------------------------
/components/oap-http/include/req_list.h:
--------------------------------------------------------------------------------
1 | #ifndef _LIST_H
2 | #define _LIST_H
3 |
4 | typedef struct req_list_t {
5 | void *key;
6 | void *value;
7 | struct req_list_t *next;
8 | struct req_list_t *prev;
9 | } req_list_t;
10 |
11 | void req_list_add(req_list_t *root, req_list_t *new_tree);
12 | req_list_t *req_list_get_last(req_list_t *root);
13 | req_list_t *req_list_get_first(req_list_t *root);
14 | void req_list_remove(req_list_t *tree);
15 | void req_list_clear(req_list_t *root);
16 | req_list_t *req_list_set_key(req_list_t *root, const char *key, const char *value);
17 | req_list_t *req_list_get_key(req_list_t *root, const char *key);
18 | int req_list_check_key(req_list_t *root, const char *key, const char *value);
19 | req_list_t *req_list_set_from_string(req_list_t *root, const char *data); //data = "key=value"
20 | #endif
21 |
--------------------------------------------------------------------------------
/components/oap-http/include/uri_parser.h:
--------------------------------------------------------------------------------
1 | #ifndef _uri_parser_
2 | #define _uri_parser_
3 | #ifdef __cplusplus
4 | extern "C" {
5 | #endif
6 | typedef struct {
7 | char *scheme; /* mandatory */
8 | char *host; /* mandatory */
9 | char *port; /* optional */
10 | char *path; /* optional */
11 | char *query; /* optional */
12 | char *fragment; /* optional */
13 | char *username; /* optional */
14 | char *password; /* optional */
15 | char *extension;
16 | char *host_ext;
17 | char *_uri; /* private */
18 | int _uri_len; /* private */
19 | } parsed_uri_t;
20 |
21 | parsed_uri_t *parse_uri(const char *);
22 | void free_parsed_uri(parsed_uri_t *);
23 | void parse_uri_info(parsed_uri_t *puri);
24 | #ifdef __cplusplus
25 | }
26 | #endif
27 |
28 | #endif /* _uri_parser_ */
29 |
--------------------------------------------------------------------------------
/components/oap-http/req_list.c:
--------------------------------------------------------------------------------
1 | /*
2 | * @2017
3 | * Tuan PM
4 | */
5 | #include
6 | #include
7 | #include
8 | #include "req_list.h"
9 | #include "esp_log.h"
10 | #define LIST_TAG "LIST"
11 | static char *trimwhitespace(char *str)
12 | {
13 | char *end;
14 |
15 | // Trim leading space
16 | while(isspace((unsigned char)*str)) str++;
17 |
18 | if(*str == 0) // All spaces?
19 | return str;
20 |
21 | // Trim trailing space
22 | end = str + strlen(str) - 1;
23 | while(end > str && isspace((unsigned char)*end)) end--;
24 |
25 | // Write new null terminator
26 | *(end+1) = 0;
27 |
28 | return str;
29 | }
30 | void req_list_add(req_list_t *root, req_list_t *new_tree)
31 | {
32 | req_list_t *last = req_list_get_last(root);
33 | if(last != NULL) {
34 | last->next = new_tree;
35 | new_tree->prev = last;
36 | }
37 | }
38 | req_list_t *req_list_get_last(req_list_t *root)
39 | {
40 | req_list_t *last;
41 | if(root == NULL)
42 | return NULL;
43 | last = root;
44 | while(last->next != NULL) {
45 | last = last->next;
46 | }
47 | return last;
48 | }
49 | req_list_t *req_list_get_first(req_list_t *root)
50 | {
51 | if(root == NULL)
52 | return NULL;
53 | if(root->next == NULL)
54 | return NULL;
55 | // ESP_LOGD(LIST_TAG, "root->next = %x", (int)root->next);
56 | return root->next;
57 | }
58 | void req_list_remove(req_list_t *tree)
59 | {
60 | req_list_t *found = tree;
61 | if (found != NULL) {
62 | if (found->next && found->prev) {
63 | // ESP_LOGD(LIST_TAG, "found->prev->next= %x, found->next->prev=%x", (int)found->prev->next, (int)found->next->prev);
64 | found->prev->next = found->next;
65 | found->next->prev = found->prev;
66 | } else if (found->next) {
67 | // ESP_LOGD(LIST_TAG, "found->next->prev= %x", (int)found->next->prev);
68 | found->next->prev = NULL;
69 | } else if (found->prev) {
70 | // ESP_LOGD(LIST_TAG, "found->prev->next =%x", (int)found->prev->next);
71 | found->prev->next = NULL;
72 | }
73 | free(found->key);
74 | free(found->value);
75 | free(found);
76 | }
77 | }
78 |
79 | void req_list_clear(req_list_t *root)
80 | {
81 | //FIXME: Need to test this function
82 | req_list_t *found;
83 | while((found = req_list_get_first(root)) != NULL) {
84 | // ESP_LOGD(LIST_TAG, "free key=%s, value=%s, found=%x", (char*)found->key, (char*)found->value, (int)found);
85 | req_list_remove(found);
86 | }
87 | }
88 |
89 | req_list_t *req_list_set_key(req_list_t *root, const char *key, const char *value)
90 | {
91 | req_list_t *found;
92 | if(root == NULL)
93 | return NULL;
94 | found = root;
95 | while(found->next != NULL) {
96 | found = found->next;
97 | if (strcasecmp(found->key, key) == 0) {
98 | if (found->value) {
99 | free(found->value);
100 | }
101 | found->value = calloc(1, strlen(value)+1);
102 | strcpy(found->value, value);
103 | return found;
104 | }
105 | }
106 | req_list_t *new_tree = calloc(1, sizeof(req_list_t));
107 | if (new_tree == NULL)
108 | return NULL;
109 | new_tree->key = calloc(1, strlen(key) + 1);
110 | strcpy(new_tree->key, key);
111 | new_tree->value = calloc(1, strlen(value)+1);
112 | strcpy(new_tree->value, value);
113 |
114 | req_list_add(root, new_tree);
115 | return new_tree;
116 | }
117 | req_list_t *req_list_get_key(req_list_t *root, const char *key)
118 | {
119 | req_list_t *found;
120 | if(root == NULL)
121 | return NULL;
122 | found = root;
123 | while(found->next != NULL) {
124 | found = found->next;
125 | if (strcasecmp(found->key, key) == 0) {
126 | return found;
127 | }
128 | }
129 | return NULL;
130 | }
131 | int req_list_check_key(req_list_t *root, const char *key, const char *value)
132 | {
133 | req_list_t *found = req_list_get_key(root, key);
134 | if(found && strcasecmp(found->value, value) == 0)
135 | return 1;
136 | return 0;
137 |
138 | }
139 | req_list_t *req_list_set_from_string(req_list_t *root, const char *data)
140 | {
141 | int len = strlen(data);
142 | char* eq_ch = strchr(data, ':');
143 | int key_len, value_len;
144 | req_list_t *ret = NULL;
145 |
146 | if (eq_ch == NULL)
147 | return NULL;
148 | key_len = eq_ch - data;
149 | value_len = len - key_len - 1;
150 |
151 | char *key = calloc(1, key_len + 1);
152 | char *value = calloc(1, value_len + 1);
153 | memcpy(key, data, key_len);
154 | memcpy(value, eq_ch + 1, value_len);
155 |
156 | ret = req_list_set_key(root, trimwhitespace(key), trimwhitespace(value));
157 | free(key);
158 | free(value);
159 | return ret;
160 | }
161 | req_list_t *req_list_clear_key(req_list_t *root, const char *key)
162 | {
163 | return NULL;
164 | }
165 |
--------------------------------------------------------------------------------
/components/oap-http/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-http/test/test_esp_request.c:
--------------------------------------------------------------------------------
1 | /*
2 | * test_esp_request.c
3 | *
4 | * Created on: Oct 6, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 | #include "esp_request.h"
25 | #include "oap_test.h"
26 | #include "oap_debug.h"
27 |
28 | extern const uint8_t _root_ca_pem_start[] asm("_binary_comodo_ca_pem_start");
29 | extern const uint8_t _root_ca_pem_end[] asm("_binary_comodo_ca_pem_end");
30 |
31 | #define URL(PROT,PATH) #PROT"://openairproject.com/ota-test"#PATH
32 |
33 | static int make_http_get() {
34 | request_t* req = req_new(URL(http,/index.txt));
35 | if (!req) return -1;
36 | req_setopt(req, REQ_REDIRECT_FOLLOW, "false");
37 | req_setopt(req, REQ_SET_HEADER, HTTP_HEADER_CONNECTION_CLOSE);
38 | int resp = req_perform(req);
39 | req_clean(req);
40 | return resp == 301 ? 0 : resp;
41 | }
42 |
43 | static int make_https_get(int big) {
44 | request_t* req = req_new(big ? URL(https,/random32k.bin) : URL(https,/index.txt));
45 | if (!req) return -1;
46 | req->ca_cert = req_parse_x509_crt((unsigned char*)_root_ca_pem_start, _root_ca_pem_end-_root_ca_pem_start);
47 | req_setopt(req, REQ_SET_HEADER, HTTP_HEADER_CONNECTION_CLOSE);
48 | int resp = req_perform(req);
49 | req_clean(req);
50 | return resp == 200 ? 0 : resp;
51 | }
52 |
53 | TEST_CASE("http request", "[esp-request]") {
54 | test_require_wifi();
55 | TEST_ESP_OK(make_http_get());
56 | }
57 |
58 | TEST_CASE("https request", "[esp-request]") {
59 | test_require_wifi();
60 | TEST_ESP_OK(make_https_get(0));
61 | }
62 |
63 | /*
64 | * there's a few problems with SSL stack on ESP32.
65 | * a single SSL request consumes a lot of stack and heap.
66 | *
67 | * so I've implemented a mutex to process them sequentially.
68 | * even with queuing them, they are still quite unreliable and timeout often.
69 | *
70 | * these tests are handy to look for memory leaks and stability in general.
71 | */
72 | static QueueHandle_t https_client_task_queue;
73 |
74 | static void https_client_task() {
75 | int resp = make_https_get(1);
76 | xQueueSend(https_client_task_queue, &resp, 100);
77 | log_task_stack("sslclient");
78 | vTaskDelete(NULL);
79 | }
80 |
81 | TEST_CASE("multiple ssl requests", "[esp-request]") {
82 | test_require_wifi();
83 | int count = 4;
84 | if (!https_client_task_queue) https_client_task_queue = xQueueCreate(count, sizeof(int));
85 | log_heap_size("before https requests");
86 | for (int i = 0; i < count; i++) {
87 | char t[20]; //should be malloc ?
88 | sprintf(t, "https_task_%i", i);
89 | //6KB is MINIMUM for making ssl!
90 | xTaskCreate(https_client_task, t, 1024*6, NULL, 10, NULL);
91 | }
92 | int resp;
93 | for (int i = 0; i < count; i++) {
94 | xQueueReceive(https_client_task_queue, &resp, 20000/portTICK_PERIOD_MS);
95 | }
96 | log_heap_size("after http requests");
97 | }
98 |
99 |
100 | static QueueHandle_t http_client_task_queue;
101 |
102 | static void http_client_task() {
103 | int resp = make_http_get();
104 | xQueueSend(http_client_task_queue, &resp, 100);
105 | log_task_stack("httpclient");
106 | vTaskDelete(NULL);
107 | }
108 |
109 | //no problems here, even if sometimes one or two fails
110 | TEST_CASE("multiple http requests", "[esp-request]") {
111 | test_require_wifi();
112 | int count = 10;
113 | if (!http_client_task_queue) http_client_task_queue = xQueueCreate(count, sizeof(int));
114 | log_heap_size("before http requests");
115 | for (int i = 0; i < count; i++) {
116 | char t[20];
117 | sprintf(t, "http_task_%i", i);
118 | xTaskCreate(http_client_task, t, 1024*5, NULL, 10, NULL);
119 | }
120 | int resp;
121 | for (int i = 0; i < count; i++) {
122 | xQueueReceive(http_client_task_queue, &resp, 20000/portTICK_PERIOD_MS);
123 | }
124 | log_heap_size("after http requests");
125 | }
126 |
127 |
128 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP BMx280 Sensor"
2 |
3 | config OAP_BMX280_ENABLED
4 | int "enable bmx280 sensor"
5 | default 1
6 | help
7 | todo
8 |
9 | config OAP_BMX280_ADDRESS
10 | hex "i2c address"
11 | default 0x76
12 | help
13 | Default address for bmx280 sensor is 0x76, it can be set to 0x77 by pulling up SDO pin.
14 | Adafruit bme280 board is configured for 0x77 as default.
15 |
16 | config OAP_BMX280_I2C_NUM
17 | int "i2c interface number"
18 | default 0
19 | help
20 | todo
21 |
22 | config OAP_BMX280_I2C_SDA_PIN
23 | int "gpio SDA pin"
24 | default 25
25 | help
26 | be careful with choosing gpio. i2c pins must be R/W.
27 |
28 |
29 | config OAP_BMX280_I2C_SCL_PIN
30 | int "SCL pin"
31 | default 26
32 | help
33 | see help for SDA pin
34 |
35 | config OAP_BMX280_ENABLED_AUX
36 | int "enable internal bmx280 sensor"
37 | default 0
38 | help
39 | todo
40 |
41 | config OAP_BMX280_ADDRESS_AUX
42 | hex "i2c address of internal sensor"
43 | default 0x77
44 | help
45 | If both external and internal sensor use the same i2c bus, they must be configured to use
46 | different addresses.
47 | Default address for bmx280 sensor is 0x76, it can be set to 0x77 by pulling up SDO pin.
48 | Adafruit bme280 board is configured for 0x77 as default.
49 |
50 | config OAP_BMX280_I2C_NUM_AUX
51 | int "i2c interface number for internal sensor"
52 | default 0
53 | help
54 | if both sensors use the same bus (default), sda/scl pins are ignored.
55 |
56 | config OAP_BMX280_I2C_SDA_PIN_AUX
57 | int "gpio SDA pin"
58 | default 25
59 | help
60 | be careful with choosing gpio. i2c pins must be R/W.
61 |
62 |
63 | config OAP_BMX280_I2C_SCL_PIN_AUX
64 | int "SCL pin"
65 | default 26
66 | help
67 | see help for SDA pin
68 |
69 | endmenu
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/bmx280.c:
--------------------------------------------------------------------------------
1 | /*
2 | * bmp280.c
3 | *
4 | * Created on: Feb 8, 2017
5 | * Author: kris
6 | *
7 | * based on https://github.com/LanderU/BMP280/blob/master/BMP280.c
8 | *
9 | * This file is part of OpenAirProject-ESP32.
10 | *
11 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
12 | * it under the terms of the GNU General Public License as published by
13 | * the Free Software Foundation, either version 3 of the License, or
14 | * (at your option) any later version.
15 | *
16 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU General Public License
22 | * along with OpenAirProject-ESP32. If not, see .
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include "sdkconfig.h"
30 | #include "oap_common.h"
31 | #include "oap_debug.h"
32 | #include "bmx280.h"
33 | #include "i2c_bme280.h"
34 |
35 | static char* TAG = "bmx280";
36 |
37 | esp_err_t bmx280_measurement_loop(bmx280_config_t* bmx280_config) {
38 | i2c_comm_t i2c_comm = {
39 | .i2c_num = bmx280_config->i2c_num,
40 | .device_addr = bmx280_config->device_addr
41 | };
42 |
43 | bme280_sensor_t bmx280_sensor = {
44 | .operation_mode = BME280_MODE_NORMAL,
45 | .i2c_comm = i2c_comm
46 | };
47 |
48 | env_data_t result = {
49 | .sensor_idx = bmx280_config->sensor_idx
50 | };
51 |
52 | // TODO strangely, if this is executed inside main task, LEDC fails to initialise properly PWM (and blinks in funny ways)... easy to reproduce.
53 | esp_err_t ret;
54 | if ((ret = BME280_init(&bmx280_sensor)) == ESP_OK) {
55 | while(1) {
56 | log_task_stack(TAG);
57 | if ((ret = BME280_read(&bmx280_sensor, &result)) == ESP_OK) {
58 | ESP_LOGD(TAG,"sensor (%d) => Temperature : %.2f C, Pressure: %.2f hPa, Humidity %.2f", result.sensor_idx, result.temp, result.pressure, result.humidity);
59 | if (bmx280_config->callback) {
60 | bmx280_config->callback(&result);
61 | }
62 | } else {
63 | ESP_LOGW(TAG, "Failed to read data");
64 | }
65 | if (bmx280_config->interval > 0) {
66 | delay(bmx280_config->interval);
67 | } else {
68 | break;
69 | }
70 | }
71 | } else {
72 | ESP_LOGE(TAG, "Failed to initialise");
73 | }
74 | return ret;
75 | }
76 |
77 | static void bmx280_task(bmx280_config_t* bmx280_config) {
78 | bmx280_measurement_loop(bmx280_config);
79 | vTaskDelete(NULL);
80 | }
81 |
82 | static uint8_t i2c_drivers[3] = {0};
83 |
84 | esp_err_t bmx280_i2c_setup(bmx280_config_t* config) {
85 | if (config->i2c_num > 2) {
86 | ESP_LOGE(TAG, "invalid I2C BUS NUMBER (%d)", config->i2c_num);
87 | return ESP_FAIL;
88 | }
89 | if (i2c_drivers[config->i2c_num]) return ESP_OK; //already installed
90 |
91 | i2c_config_t i2c_conf;
92 | i2c_conf.mode = I2C_MODE_MASTER;
93 | i2c_conf.sda_io_num = config->sda_pin;//CONFIG_OAP_BMX280_I2C_SDA_PIN;
94 | i2c_conf.scl_io_num = config->scl_pin;//CONFIG_OAP_BMX280_I2C_SCL_PIN;
95 | i2c_conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
96 | i2c_conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
97 | i2c_conf.master.clk_speed = 100000;
98 |
99 | esp_err_t res;
100 | if ((res = i2c_param_config(config->i2c_num, &i2c_conf)) != ESP_OK) return res;
101 |
102 | ESP_LOGD(TAG, "install I2C driver (bus %d)", config->i2c_num);
103 | res = i2c_driver_install(config->i2c_num, I2C_MODE_MASTER, 0, 0, 0);
104 | if (res == ESP_OK) {
105 | i2c_drivers[config->i2c_num] = 1;
106 | }
107 |
108 | return res;
109 | }
110 |
111 | esp_err_t bmx280_init(bmx280_config_t* bmx280_config) {
112 | esp_err_t res;
113 | if ((res = bmx280_i2c_setup(bmx280_config)) == ESP_OK) {
114 | //2kb => ~380bytes free
115 | xTaskCreate((TaskFunction_t)bmx280_task, "bmx280_task", 1024*3, bmx280_config, DEFAULT_TASK_PRIORITY, NULL);
116 | }
117 | return res;
118 | }
119 |
120 | esp_err_t bmx280_set_hardware_config(bmx280_config_t* bmx280_config, uint8_t sensor_idx) {
121 | switch (sensor_idx) {
122 | case 0:
123 | if (!OAP_BMX280_ENABLED) return ESP_FAIL;
124 | bmx280_config->sensor_idx = 0;
125 | bmx280_config->i2c_num = OAP_BMX280_I2C_NUM;
126 | bmx280_config->device_addr = OAP_BMX280_ADDRESS;
127 | bmx280_config->sda_pin = OAP_BMX280_I2C_SDA_PIN;
128 | bmx280_config->scl_pin = OAP_BMX280_I2C_SCL_PIN;
129 | return ESP_OK;
130 | case 1:
131 | if (!OAP_BMX280_ENABLED_AUX) return ESP_FAIL;
132 | bmx280_config->sensor_idx = 1;
133 | bmx280_config->i2c_num = OAP_BMX280_I2C_NUM_AUX;
134 | bmx280_config->device_addr = OAP_BMX280_ADDRESS_AUX;
135 | bmx280_config->sda_pin = OAP_BMX280_I2C_SDA_PIN_AUX;
136 | bmx280_config->scl_pin = OAP_BMX280_I2C_SCL_PIN_AUX;
137 | return ESP_OK;
138 | default:
139 | return ESP_FAIL;
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/i2c_bme280.h:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of OpenAirProject-ESP32.
3 | *
4 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU General Public License as published by
6 | * the Free Software Foundation, either version 3 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU General Public License
15 | * along with OpenAirProject-ESP32. If not, see .
16 |
17 | */
18 | #ifndef __I2C_BME280_H
19 | #define __I2C_BME280_H
20 |
21 | #include
22 | #include
23 | #include "oap_data_env.h"
24 |
25 | #define BME280_MODE_NORMAL 0x03 //reads sensors at set interval
26 | #define BME280_MODE_FORCED 0x01 //reads sensors once when you write this register
27 |
28 | #define CHIP_TYPE_BMP 1
29 | #define CHIP_TYPE_BME 2
30 |
31 | #define HUMIDITY_MEAS_UNSUPPORTED -1
32 |
33 | typedef struct bmx280_calib_t {
34 | uint16_t dig_T1;
35 | int16_t dig_T2;
36 | int16_t dig_T3;
37 | uint16_t dig_P1;
38 | int16_t dig_P2;
39 | int16_t dig_P3;
40 | int16_t dig_P4;
41 | int16_t dig_P5;
42 | int16_t dig_P6;
43 | int16_t dig_P7;
44 | int16_t dig_P8;
45 | int16_t dig_P9;
46 | int8_t dig_H1;
47 | int16_t dig_H2;
48 | int8_t dig_H3;
49 | int16_t dig_H4;
50 | int16_t dig_H5;
51 | int8_t dig_H6;
52 | } bmx280_calib_t;
53 |
54 | typedef struct i2c_comm_t {
55 | uint8_t i2c_num;
56 | uint8_t device_addr;
57 | } i2c_comm_t;
58 |
59 | typedef struct bme280_sensor_t {
60 | uint8_t operation_mode;
61 | i2c_comm_t i2c_comm;
62 | bmx280_calib_t calib;
63 | uint8_t chip_type;
64 | } bme280_sensor_t;
65 |
66 | esp_err_t BME280_verify_chip(bme280_sensor_t* bme280_sensor);
67 |
68 | esp_err_t BME280_init(bme280_sensor_t* bme280_sensor);
69 |
70 | esp_err_t BME280_read(bme280_sensor_t* bme280_sensor, env_data_t* result);
71 |
72 | #endif
73 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/include/bmx280.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bmp280.h
3 | *
4 | * Created on: Feb 8, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_BMP280_H_
24 | #define MAIN_BMP280_H_
25 |
26 | #include "oap_common.h"
27 | #include "oap_data_env.h"
28 |
29 | #define OAP_BMX280_ENABLED CONFIG_OAP_BMX280_ENABLED
30 | #define OAP_BMX280_I2C_NUM CONFIG_OAP_BMX280_I2C_NUM
31 | #define OAP_BMX280_ADDRESS CONFIG_OAP_BMX280_ADDRESS
32 | #define OAP_BMX280_I2C_SDA_PIN CONFIG_OAP_BMX280_I2C_SDA_PIN
33 | #define OAP_BMX280_I2C_SCL_PIN CONFIG_OAP_BMX280_I2C_SCL_PIN
34 |
35 | #define OAP_BMX280_ENABLED_AUX CONFIG_OAP_BMX280_ENABLED_AUX
36 | #define OAP_BMX280_I2C_NUM_AUX CONFIG_OAP_BMX280_I2C_NUM_AUX
37 | #define OAP_BMX280_ADDRESS_AUX CONFIG_OAP_BMX280_ADDRESS_AUX
38 | #define OAP_BMX280_I2C_SDA_PIN_AUX CONFIG_OAP_BMX280_I2C_SDA_PIN_AUX
39 | #define OAP_BMX280_I2C_SCL_PIN_AUX CONFIG_OAP_BMX280_I2C_SCL_PIN_AUX
40 |
41 | typedef void(*env_callback)(env_data_t*);
42 |
43 | typedef struct bmx280_config_t {
44 |
45 | uint8_t i2c_num;
46 | uint8_t device_addr;
47 | uint8_t sda_pin;
48 | uint8_t scl_pin;
49 | uint8_t sensor_idx; //sensor number (0 - 1)
50 | uint32_t interval;
51 | env_callback callback;
52 |
53 | } bmx280_config_t;
54 |
55 | esp_err_t bmx280_init(bmx280_config_t* config);
56 |
57 | esp_err_t bmx280_set_hardware_config(bmx280_config_t* bmx280_config, uint8_t sensor_idx);
58 |
59 | #endif /* MAIN_BMP280_H_ */
60 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-hw-bmx280/test/test_bmx280.c:
--------------------------------------------------------------------------------
1 | /*
2 | * test_bmx280.c
3 | *
4 | * Created on: Sep 21, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "bmx280.h"
24 | #include "unity.h"
25 |
26 | esp_err_t bmx280_i2c_setup(bmx280_config_t* config);
27 | esp_err_t bmx280_measurement_loop(bmx280_config_t* bmx280_config);
28 | static env_data_t last_result;
29 |
30 | static void collect_result(env_data_t* result) {
31 | memcpy(&last_result, result, sizeof(env_data_t));
32 | }
33 |
34 | static bmx280_config_t cfg = {
35 | .i2c_num = CONFIG_OAP_BMX280_I2C_NUM,
36 | .device_addr= CONFIG_OAP_BMX280_ADDRESS,
37 | .sda_pin= CONFIG_OAP_BMX280_I2C_SDA_PIN,
38 | .scl_pin= CONFIG_OAP_BMX280_I2C_SCL_PIN,
39 | .sensor_idx = 9,
40 | .interval = 0, //no repeat
41 | .callback = &collect_result
42 | };
43 |
44 | TEST_CASE("bmx280 measurement","[bmx280]") {
45 | bzero(&last_result, 0);
46 | TEST_ASSERT_TRUE(CONFIG_OAP_BMX280_ENABLED);
47 | TEST_ESP_OK(bmx280_i2c_setup(&cfg));
48 | TEST_ESP_OK(bmx280_measurement_loop(&cfg));
49 |
50 | TEST_ASSERT_EQUAL_UINT(9, last_result.sensor_idx);
51 | TEST_ASSERT_TRUE_MESSAGE(last_result.temp > 10 && last_result.temp < 50, "invalid temperature"); //let's assume we do it indoors ;)
52 | TEST_ASSERT_TRUE_MESSAGE(last_result.pressure>850 && last_result.pressure < 1050, "invalid pressure");
53 | if (last_result.humidity != -1) {
54 | TEST_ASSERT_TRUE_MESSAGE(last_result.humidity > 0 && last_result.humidity < 100, "invalid humidity"); //bme280 only
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/components/oap-hw-ext/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP Peripherals"
2 |
3 | config OAP_LED_R_PIN
4 | int "led Red pin"
5 | default 12
6 | help
7 | ESP32 R/W gpio
8 |
9 | config OAP_LED_G_PIN
10 | int "led Green pin"
11 | default 27
12 | help
13 | ESP32 R/W gpio
14 |
15 | config OAP_LED_B_PIN
16 | int "led Blue pin"
17 | default 14
18 | help
19 | ESP32 R/W gpio
20 |
21 | config OAP_BTN_0_PIN
22 | int "button pin"
23 | default 35
24 | help
25 | ESP32 gpio
26 |
27 | endmenu
--------------------------------------------------------------------------------
/components/oap-hw-ext/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
--------------------------------------------------------------------------------
/components/oap-hw-ext/ctrl_btn.c:
--------------------------------------------------------------------------------
1 | /*
2 | * btn.c
3 | *
4 | * Created on: Feb 4, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "freertos/FreeRTOS.h"
29 | #include "freertos/task.h"
30 | #include "oap_common.h"
31 | #include "ctrl_btn.h"
32 | #include "esp_log.h"
33 | #include "esp_err.h"
34 | #include "driver/gpio.h"
35 | #include "freertos/queue.h"
36 |
37 | #define ESP_INTR_FLAG_DEFAULT 0
38 | #define TAG "btn"
39 |
40 | typedef struct {
41 | uint8_t gpio_num;
42 | uint32_t timestamp;
43 | } gpio_event_t;
44 |
45 | static QueueHandle_t gpio_evt_queue;
46 | static uint32_t last_click = 0;
47 | static btn_callback_f _callback = NULL;
48 |
49 | static void IRAM_ATTR gpio_isr_handler(void* arg)
50 | {
51 | uint32_t t = millis();
52 | /*
53 | * TODO is there a way to programmatically eliminate flickering?
54 | */
55 | if (t - last_click < 80) return;
56 | last_click = t;
57 | gpio_event_t gpio_evt = {
58 | .gpio_num = (uint8_t)(uint32_t)arg,
59 | .timestamp = t
60 | };
61 | xQueueSendFromISR(gpio_evt_queue, &gpio_evt, NULL);
62 | }
63 |
64 | static void gpio_watchdog_task() {
65 | gpio_event_t gpio_evt;
66 | int count = 0;
67 | uint32_t first_click = 0;
68 |
69 | while(1) {
70 | if (xQueueReceive(gpio_evt_queue, &gpio_evt, 1000)) {
71 | _callback(SINGLE_CLICK);
72 | //20 sec to perform the action
73 | if (!first_click || gpio_evt.timestamp - first_click > 20000) {
74 | first_click = gpio_evt.timestamp;
75 | count = 0;
76 | }
77 | count++;
78 | ESP_LOGD(TAG, "click gpio[%d] [%d in sequence]",gpio_evt.gpio_num, count);
79 |
80 | //due to flickering we cannot precisely count all clicks anyway
81 | if (count == 10) {
82 | _callback(MANY_CLICKS);
83 | }
84 | if (count >= 20) {
85 | _callback(TOO_MANY_CLICKS);
86 | first_click=0;
87 | count=0;
88 | }
89 | }
90 | }
91 | }
92 |
93 | esp_err_t btn_configure(btn_callback_f callback) {
94 | _callback = callback;
95 | gpio_evt_queue = xQueueCreate(10, sizeof(gpio_event_t));
96 | gpio_pad_select_gpio(CONFIG_OAP_BTN_0_PIN);
97 | gpio_set_direction(CONFIG_OAP_BTN_0_PIN, GPIO_MODE_INPUT);
98 | gpio_set_pull_mode(CONFIG_OAP_BTN_0_PIN, GPIO_PULLDOWN_ONLY);
99 | gpio_set_intr_type(CONFIG_OAP_BTN_0_PIN, GPIO_INTR_POSEDGE);
100 | gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
101 | gpio_isr_handler_add(CONFIG_OAP_BTN_0_PIN, gpio_isr_handler, (void*) CONFIG_OAP_BTN_0_PIN);
102 | xTaskCreate((TaskFunction_t)gpio_watchdog_task, "gpio_watchdog_task", 1024*2, NULL, DEFAULT_TASK_PRIORITY+2, NULL);
103 | return ESP_OK; //TODO handle errors
104 | }
105 |
106 | bool is_ap_mode_pressed() {
107 | return gpio_get_level(CONFIG_OAP_BTN_0_PIN);
108 | }
109 |
110 |
--------------------------------------------------------------------------------
/components/oap-hw-ext/include/ctrl_btn.h:
--------------------------------------------------------------------------------
1 | /*
2 | * btn.h
3 | *
4 | * Created on: Feb 4, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_BTN_H_
24 | #define MAIN_BTN_H_
25 |
26 | typedef enum {
27 | SINGLE_CLICK,
28 | MANY_CLICKS,
29 | TOO_MANY_CLICKS
30 | } btn_action_t;
31 | typedef void(*btn_callback_f)(btn_action_t);
32 |
33 | bool is_ap_mode_pressed();
34 | esp_err_t btn_configure(btn_callback_f callback);
35 |
36 | #endif /* MAIN_BTN_H_ */
37 |
--------------------------------------------------------------------------------
/components/oap-hw-ext/include/rgb_led.h:
--------------------------------------------------------------------------------
1 | /*
2 | * led.h
3 | *
4 | * Created on: Feb 7, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_LED_H_
24 | #define MAIN_LED_H_
25 |
26 | #include "freertos/queue.h"
27 |
28 | typedef struct { float v[3]; } rgb_color_t;
29 |
30 | typedef enum {
31 | LED_SET = 0,
32 | LED_FADE_TO = 1,
33 | LED_BLINK = 2,
34 | LED_PULSE = 3
35 | } led_mode_t;
36 |
37 | typedef struct {
38 | led_mode_t mode;
39 | rgb_color_t color;
40 | uint32_t freq;
41 | } led_cmd_t;
42 |
43 | void led_init(int enabled, xQueueHandle cmd_queue);
44 |
45 | #endif /* MAIN_LED_H_ */
46 |
--------------------------------------------------------------------------------
/components/oap-hw-ext/rgb_led.c:
--------------------------------------------------------------------------------
1 | /*
2 | * led.c
3 | *
4 | * Created on: Feb 7, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 | #include
23 | #include
24 | #include "freertos/FreeRTOS.h"
25 | #include "freertos/task.h"
26 | #include "freertos/xtensa_api.h"
27 | #include "freertos/queue.h"
28 | #include "driver/ledc.h"
29 | #include "driver/rtc_io.h"
30 | #include "driver/gpio.h"
31 | #include "esp_attr.h"
32 | #include "esp_err.h"
33 | #include "esp_log.h"
34 | #include
35 | #include "rgb_led.h"
36 | #include "oap_common.h"
37 |
38 | static const char* TAG = "rgbled";
39 | static xQueueHandle cmd_queue;
40 | static gpio_num_t led_gpio[] = {CONFIG_OAP_LED_R_PIN,CONFIG_OAP_LED_G_PIN,CONFIG_OAP_LED_B_PIN};
41 |
42 | #define DEFAULT_FREQ 1000
43 |
44 | static ledc_mode_t speed_mode = LEDC_HIGH_SPEED_MODE;
45 |
46 | static ledc_timer_config_t ledc_timer = {
47 | //set timer counter bit number
48 | .bit_num = LEDC_TIMER_10_BIT,
49 | //set frequency of pwm
50 | .freq_hz = 5000,
51 | //timer mode,
52 | .speed_mode = LEDC_HIGH_SPEED_MODE,
53 | //timer index
54 | .timer_num = LEDC_TIMER_0
55 | };
56 |
57 | static int MAX_DUTY = 0;
58 | static rgb_color_t LED_OFF = {.v={0,0,0}};
59 |
60 | //brightness for each of R/G/B. LED Green tends to be the brightest
61 | //so if we use the same resistors we need to compensate for it to get proper orange.
62 | //this probably should be configureble since it depends on particular LED and resistors.
63 | static float brightness[] = {1.0f,0.3f,1.0f};
64 |
65 | static int calc_duty(rgb_color_t color, uint8_t c) {
66 | return lroundf(MAX_DUTY * fminf(color.v[c] * brightness[c], 1.0));
67 | }
68 |
69 | void set_color(rgb_color_t color) {
70 | esp_err_t res;
71 | int duty;
72 | for (int c = 0; c < 3; c++) {
73 | duty = calc_duty(color,c);
74 | if ((res = ledc_set_duty(speed_mode, c, duty)) != ESP_OK) {
75 | ESP_LOGW(TAG, "ledc_set_duty(%d,%d,%d) error %d", speed_mode, c, duty, res);
76 | }
77 | if ((res = ledc_update_duty(speed_mode, c)) != ESP_OK) {
78 | ESP_LOGW(TAG, "ledc_update_duty(%d,%d) error %d", speed_mode, c, res);
79 | }
80 | }
81 | }
82 |
83 | void fade_to_color(rgb_color_t color, int time) {
84 | esp_err_t res;
85 | int duty;
86 | for (int c = 0; c < 3; c++) {
87 | duty = calc_duty(color,c);
88 | if ((res = ledc_set_fade_with_time(speed_mode, c, duty,time)) != ESP_OK) {
89 | ESP_LOGW(TAG, "ledc_set_fade_with_time(%d,%d,%d,%d) error %d", speed_mode, c, duty, time, res);
90 | }
91 | if ((res = ledc_fade_start(speed_mode, c, LEDC_FADE_NO_WAIT)) != ESP_OK) {
92 | ESP_LOGW(TAG, "ledc_fade_start(%d,%d) error %d", c, LEDC_FADE_NO_WAIT, res);
93 | }
94 | }
95 | }
96 |
97 | static void setup_ledc() {
98 | MAX_DUTY = pow(2,ledc_timer.bit_num)-1;
99 | ledc_timer_config(&ledc_timer);
100 |
101 | ledc_channel_config_t ledc_channel = {
102 | .channel = -1,
103 | .duty = -1,
104 | .gpio_num = -1,
105 | //GPIO INTR TYPE, as an example, we enable fade_end interrupt here.
106 | .intr_type = LEDC_INTR_FADE_END,
107 | //set LEDC mode, from ledc_mode_t
108 | .speed_mode = speed_mode,
109 | //set LEDC timer source, if different channel use one timer,
110 | //the frequency and bit_num of these channels should be the same
111 | .timer_sel = LEDC_TIMER_0
112 | };
113 |
114 | for (int c = 0; c < 3; c++) {
115 | ledc_channel.channel = c; //LEDC_CHANNEL_0 to LEDC_CHANNEL_2
116 | ledc_channel.gpio_num = led_gpio[c];
117 | ledc_channel.duty = 0;
118 | gpio_intr_disable(led_gpio[c]);
119 | ledc_channel_config(&ledc_channel);
120 | }
121 | //initialize fade service.
122 | ledc_fade_func_install(0);
123 | }
124 |
125 | static void led_cycle() {
126 | rgb_color_t color = {.v={1,1,1}};
127 | led_cmd_t cmd = {
128 | .mode = LED_SET,
129 | .color = color
130 | };
131 | int level = 0;
132 | int freq;
133 | while (1) {
134 | level = !level;
135 | freq = cmd.freq > 0 ? cmd.freq : DEFAULT_FREQ;
136 | switch (cmd.mode) {
137 | case LED_BLINK :
138 | //ESP_LOGD(TAG, "->blink (%d)", level);
139 | set_color(level ? cmd.color : LED_OFF);
140 | break;
141 | case LED_PULSE :
142 | //ESP_LOGD(TAG, "->pulse (%d)", level);
143 | fade_to_color(level ? cmd.color : LED_OFF, freq);
144 | break;
145 | case LED_FADE_TO:
146 | //ESP_LOGD(TAG, "->fade_to");
147 | //this is causing some errors - cannot schedule fading when other is still ongoing?
148 | fade_to_color(cmd.color, freq);
149 | break;
150 | default:
151 | //ESP_LOGD(TAG, "->set");
152 | freq = DEFAULT_FREQ;
153 | set_color(cmd.color);
154 | break;
155 | }
156 | //wait for another command
157 | if (xQueueReceive(cmd_queue, &cmd, freq / portTICK_PERIOD_MS)) {
158 | ESP_LOGD(TAG, "->received command");
159 | //memcpy(&cmd, &received, sizeof(cmd));
160 | }
161 | }
162 | }
163 |
164 | void led_init(int enabled, xQueueHandle _cmd_queue)
165 | {
166 | if (enabled) {
167 | cmd_queue = _cmd_queue;
168 | setup_ledc(); //this often conflicts with other i/o operations? e.g. bme280 init.
169 | xTaskCreate(led_cycle, "led_cycle", 1024*2, NULL, DEFAULT_TASK_PRIORITY+1, NULL);
170 | } else {
171 | for (int c = 0; c < 3; c++) {
172 | if (led_gpio[c] > 0) gpio_set_pull_mode(led_gpio[c], GPIO_PULLDOWN_ONLY);
173 | }
174 | }
175 | }
176 |
177 |
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP PMSx003 Sensor"
2 |
3 | config OAP_PM_UART_NUM
4 | hex "uart num"
5 | default 1
6 | help
7 | todo
8 |
9 | config OAP_PM_SENSOR_CONTROL_PIN
10 | int "sensor set gpio"
11 | default 10
12 | help
13 | R/W GPIO pin connected to sensor SET line - it enables/disables sensor.
14 |
15 | config OAP_PM_UART_RXD_PIN
16 | int "RX gpio"
17 | default 13
18 | help
19 | GPIO pin connected to sensor RX line. This pin can be R/O (>=34).
20 |
21 | config OAP_PM_UART_TXD_PIN
22 | int "TX gpio"
23 | default 5
24 | help
25 | Any gpio pin (no need to connect this line)
26 |
27 | config OAP_PM_UART_RTS_PIN
28 | int "RTS gpio"
29 | default 18
30 | help
31 | Any gpio pin (no need to connect this line)
32 |
33 | config OAP_PM_UART_CTS_PIN
34 | int "CTS gpio"
35 | default 19
36 | help
37 | Any gpio pin (no need to connect this line)
38 |
39 | config OAP_PM_ENABLED_AUX
40 | int "enable secondary PM sensor"
41 | default 0
42 | help
43 | todo
44 |
45 | config OAP_PM_UART_NUM_AUX
46 | hex "AUX uart num"
47 | default 2
48 | help
49 | todo
50 |
51 | config OAP_PM_SENSOR_CONTROL_PIN_AUX
52 | int "AUX sensor set gpio"
53 | default 2
54 | help
55 | R/W GPIO pin connected to sensor SET line - it enables/disables sensor.
56 |
57 | config OAP_PM_UART_RXD_PIN_AUX
58 | int "AUX RX gpio"
59 | default 15
60 | help
61 | GPIO pin connected to sensor RX line. This pin can be R/O (>=34).
62 |
63 | config OAP_PM_UART_TXD_PIN_AUX
64 | int "AUX TX gpio"
65 | default 5
66 | help
67 | Any gpio pin (no need to connect this line)
68 |
69 | config OAP_PM_UART_RTS_PIN_AUX
70 | int "AUX RTS gpio"
71 | default 18
72 | help
73 | Any gpio pin (no need to connect this line)
74 |
75 | config OAP_PM_UART_CTS_PIN_AUX
76 | int "AUX CTS gpio"
77 | default 19
78 | help
79 | Any gpio pin (no need to connect this line)
80 |
81 | endmenu
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/include/pmsx003.h:
--------------------------------------------------------------------------------
1 | /*
2 | * pms.h
3 | *
4 | * Created on: Feb 3, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_PMS_H_
24 | #define MAIN_PMS_H_
25 |
26 | #include "oap_common.h"
27 | #include "oap_data_pm.h"
28 | #include "driver/uart.h"
29 |
30 | typedef struct {
31 | uint8_t indoor;
32 | uint8_t enabled; //internal, read-only
33 | uint8_t sensor_idx;
34 | pm_data_callback_f callback;
35 | uint8_t set_pin;
36 | uart_port_t uart_num;
37 | uint8_t uart_txd_pin;
38 | uint8_t uart_rxd_pin;
39 | uint8_t uart_rts_pin;
40 | uint8_t uart_cts_pin;
41 | } pmsx003_config_t;
42 |
43 | /**
44 | * pm samples data is send to the queue.
45 | */
46 | esp_err_t pmsx003_init(pmsx003_config_t* config);
47 |
48 | /**
49 | * enable/disable sensor.
50 | */
51 | esp_err_t pmsx003_enable(pmsx003_config_t* config, uint8_t enabled);
52 |
53 |
54 | /**
55 | * fill config based on hardware configuration
56 | */
57 | esp_err_t pmsx003_set_hardware_config(pmsx003_config_t* config, uint8_t sensor_idx);
58 |
59 | #endif /* MAIN_PMS_H_ */
60 |
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/pmsx003.c:
--------------------------------------------------------------------------------
1 | /*
2 | * pms.c
3 | *
4 | * Created on: Feb 3, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include
24 | #include
25 | #include
26 | #include
27 | #include "freertos/FreeRTOS.h"
28 | #include "driver/gpio.h"
29 | #include "driver/uart.h"
30 | #include "soc/uart_struct.h"
31 | #include "esp_log.h"
32 | #include "pmsx003.h"
33 | #include "oap_debug.h"
34 |
35 | /*
36 | * Driver for Plantower PMS3003 / PMS5003 / PMS7003 dust sensors.
37 | * PMSx003 sensors return two values for different environment of measurement.
38 | */
39 | #define OAP_PM_UART_BUF_SIZE (128)
40 |
41 | static const char* TAG = "pmsX003";
42 |
43 | esp_err_t pms_init_uart(pmsx003_config_t* config) {
44 | //configure UART
45 | uart_config_t uart_config = {
46 | .baud_rate = 9600,
47 | .data_bits = UART_DATA_8_BITS,
48 | .parity = UART_PARITY_DISABLE,
49 | .stop_bits = UART_STOP_BITS_1,
50 | .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
51 | .rx_flow_ctrl_thresh = 122,
52 | };
53 | esp_err_t ret;
54 | if ((ret = uart_param_config(config->uart_num, &uart_config)) != ESP_OK) {
55 | return ret;
56 | }
57 |
58 | if ((ret = uart_set_pin(config->uart_num, config->uart_txd_pin, config->uart_rxd_pin, config->uart_rts_pin, config->uart_cts_pin)) != ESP_OK) {
59 | return ret;
60 | }
61 | //Install UART driver( We don't need an event queue here)
62 |
63 | ret = uart_driver_install(config->uart_num, OAP_PM_UART_BUF_SIZE * 2, 0, 0, NULL,0);
64 | return ret;
65 | }
66 |
67 | static void configure_gpio(uint8_t gpio) {
68 | if (gpio > 0) {
69 | ESP_LOGD(TAG, "configure pin %d as output", gpio);
70 | gpio_pad_select_gpio(gpio);
71 | ESP_ERROR_CHECK(gpio_set_direction(gpio, GPIO_MODE_OUTPUT));
72 | ESP_ERROR_CHECK(gpio_set_pull_mode(gpio, GPIO_PULLDOWN_ONLY));
73 | }
74 | }
75 |
76 | static void set_gpio(uint8_t gpio, uint8_t enabled) {
77 | if (gpio > 0) {
78 | ESP_LOGD(TAG, "set pin %d => %d", gpio, enabled);
79 | gpio_set_level(gpio, enabled);
80 | }
81 | }
82 |
83 | void pms_init_gpio(pmsx003_config_t* config) {
84 | configure_gpio(config->set_pin);
85 | }
86 |
87 | static pm_data_t decodepm_data(uint8_t* data, uint8_t startByte) {
88 | pm_data_t pm = {
89 | .pm1_0 = ((data[startByte]<<8) + data[startByte+1]),
90 | .pm2_5 = ((data[startByte+2]<<8) + data[startByte+3]),
91 | .pm10 = ((data[startByte+4]<<8) + data[startByte+5])
92 | };
93 | return pm;
94 | }
95 |
96 | esp_err_t pms_uart_read(pmsx003_config_t* config, uint8_t data[32]) {
97 | int len = uart_read_bytes(config->uart_num, data, 32, 100 / portTICK_RATE_MS);
98 | if (config->enabled) {
99 | if (len >= 24 && data[0]==0x42 && data[1]==0x4d) {
100 | log_task_stack(TAG);
101 | //ESP_LOGI(TAG, "got frame of %d bytes", len);
102 | pm_data_t pm = decodepm_data(data, config->indoor ? 4 : 10); //atmospheric from 10th byte, standard from 4th
103 | pm.sensor_idx = config->sensor_idx;
104 | if (config->callback) {
105 | config->callback(&pm);
106 | }
107 | } else if (len > 0) {
108 | ESP_LOGW(TAG, "invalid frame of %d", len); //we often get an error after this :(
109 | return ESP_FAIL;
110 | }
111 | }
112 | return ESP_OK;
113 | }
114 |
115 | static void pms_task(pmsx003_config_t* config) {
116 | uint8_t data[32];
117 | while(1) {
118 | pms_uart_read(config, data);
119 | }
120 | vTaskDelete(NULL);
121 | }
122 |
123 | esp_err_t pmsx003_enable(pmsx003_config_t* config, uint8_t enabled) {
124 | ESP_LOGI(TAG,"enable(%d)",enabled);
125 | config->enabled = enabled;
126 | set_gpio(config->set_pin, enabled);
127 | //if (config->heater_enabled) set_gpio(config->heater_pin, enabled);
128 | //if (config->fan_enabled) set_gpio(config->fan_pin, enabled);
129 | return ESP_OK; //todo
130 | }
131 |
132 | esp_err_t pmsx003_init(pmsx003_config_t* config) {
133 | pms_init_gpio(config);
134 | pmsx003_enable(config, 0);
135 | pms_init_uart(config);
136 |
137 | char task_name[100];
138 | sprintf(task_name, "pms_sensor_%d", config->sensor_idx);
139 |
140 | //2kb leaves ~ 240 bytes free (depend on logs, printfs etc)
141 | xTaskCreate((TaskFunction_t)pms_task, task_name, 1024*3, config, DEFAULT_TASK_PRIORITY, NULL);
142 | return ESP_OK; //todo
143 | }
144 |
145 | esp_err_t pmsx003_set_hardware_config(pmsx003_config_t* config, uint8_t sensor_idx) {
146 | if (sensor_idx == 0) {
147 | config->sensor_idx = 0;
148 | config->set_pin = CONFIG_OAP_PM_SENSOR_CONTROL_PIN;
149 | config->uart_num = CONFIG_OAP_PM_UART_NUM;
150 | config->uart_txd_pin = CONFIG_OAP_PM_UART_TXD_PIN;
151 | config->uart_rxd_pin = CONFIG_OAP_PM_UART_RXD_PIN;
152 | config->uart_rts_pin = CONFIG_OAP_PM_UART_RTS_PIN;
153 | config->uart_cts_pin = CONFIG_OAP_PM_UART_CTS_PIN;
154 | return ESP_OK;
155 | } else if (sensor_idx == 1 && CONFIG_OAP_PM_ENABLED_AUX) {
156 | config->sensor_idx = 1;
157 | config->set_pin = CONFIG_OAP_PM_SENSOR_CONTROL_PIN_AUX;
158 | config->uart_num = CONFIG_OAP_PM_UART_NUM_AUX;
159 | config->uart_txd_pin = CONFIG_OAP_PM_UART_TXD_PIN_AUX;
160 | config->uart_rxd_pin = CONFIG_OAP_PM_UART_RXD_PIN_AUX;
161 | config->uart_rts_pin = CONFIG_OAP_PM_UART_RTS_PIN_AUX;
162 | config->uart_cts_pin = CONFIG_OAP_PM_UART_CTS_PIN_AUX;
163 | return ESP_OK;
164 | } else {
165 | return ESP_FAIL;
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-hw-pmsx003/test/test_pmsx003.c:
--------------------------------------------------------------------------------
1 | /*
2 | * test_pmsx003.c
3 | *
4 | * Created on: Sep 21, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 | #include "pmsx003.h"
25 | #include "oap_test.h"
26 |
27 | static pm_data_t last_result;
28 |
29 | static int got_result = 0;
30 | static void pms_test_callback(pm_data_t* result) {
31 | got_result = 1;
32 | memcpy(&last_result, result, sizeof(pm_data_t));
33 | }
34 |
35 | static pmsx003_config_t config = {
36 | .indoor = 1,
37 | .enabled = 1,
38 | .sensor_idx = 7,
39 | .callback = pms_test_callback,
40 | .set_pin = CONFIG_OAP_PM_SENSOR_CONTROL_PIN,
41 | .uart_num = CONFIG_OAP_PM_UART_NUM,
42 | .uart_txd_pin = CONFIG_OAP_PM_UART_TXD_PIN,
43 | .uart_rxd_pin = CONFIG_OAP_PM_UART_RXD_PIN,
44 | .uart_rts_pin = CONFIG_OAP_PM_UART_RTS_PIN,
45 | .uart_cts_pin = CONFIG_OAP_PM_UART_CTS_PIN
46 | };
47 |
48 | esp_err_t pms_init_uart(pmsx003_config_t* config);
49 | void pms_init_gpio(pmsx003_config_t* config);
50 | esp_err_t pms_uart_read(pmsx003_config_t* config, uint8_t data[32]);
51 |
52 | static int uart_installed = 0;
53 |
54 | void tearDown(void)
55 | {
56 | test_reset_hw();
57 | }
58 |
59 | TEST_CASE("pmsx003 measurement","pmsx003") {
60 | pms_init_gpio(&config);
61 | if (!uart_installed) {
62 | TEST_ESP_OK(pms_init_uart(&config));
63 | uart_installed = 1;
64 | }
65 | got_result = 0;
66 | uint8_t data[32];
67 |
68 | test_timer_t t = {
69 | .started = 0,
70 | .wait_for = 10000 //it takes a while to spin it up
71 | };
72 |
73 | TEST_ESP_OK(pmsx003_enable(&config, 1));
74 | while (!got_result && !test_timeout(&t)) {
75 | pms_uart_read(&config, data);
76 | }
77 | TEST_ESP_OK(pmsx003_enable(&config, 0));
78 | TEST_ASSERT_TRUE_MESSAGE(got_result, "timeout while waiting for measurement");
79 |
80 | TEST_ASSERT_EQUAL_INT(config.sensor_idx, last_result.sensor_idx);
81 | TEST_ASSERT_TRUE_MESSAGE(last_result.pm1_0 > 0, "no pm1.0");
82 | TEST_ASSERT_TRUE_MESSAGE(last_result.pm2_5 > 0, "no pm2.5");
83 | TEST_ASSERT_TRUE_MESSAGE(last_result.pm10 > 0, "no pm10");
84 | }
85 |
86 |
87 |
--------------------------------------------------------------------------------
/components/oap-meter/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP measurements"
2 |
3 | config OAP_PM_SAMPLE_BUF_SIZE
4 | int "PM sensor sample buffer size"
5 | default 120
6 | help
7 | Max number of samples that are stored during measurement period. PMSx003 sensor sends ~1 sample / sec.
8 | If more samples are collected during measurement, older samples get overriden.
9 |
10 | config OAP_HEATER_CONTROL_PIN
11 | int "external heater gpio"
12 | default 21
13 | help
14 | optional GPIO pin to control a heater. It mirrors state of SET gpio. (0 = none)
15 |
16 | config OAP_FAN_CONTROL_PIN
17 | int "external fan gpio"
18 | default 22
19 | help
20 | optional GPIO pin to control an additional fan. It mirrors state of SET gpio. (0 = none)
21 |
22 | endmenu
--------------------------------------------------------------------------------
/components/oap-meter/component.mk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/components/oap-meter/component.mk
--------------------------------------------------------------------------------
/components/oap-meter/include/meas_continuous.h:
--------------------------------------------------------------------------------
1 | /*
2 | * meas_continuous.h
3 | *
4 | * Created on: Mar 25, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_MEAS_CONTINUOUS_H_
24 | #define MAIN_MEAS_CONTINUOUS_H_
25 |
26 | typedef struct {
27 |
28 | } meas_continuous_params_t;
29 |
30 | #include "pm_meter.h"
31 |
32 | #endif /* MAIN_MEAS_CONTINUOUS_H_ */
33 |
--------------------------------------------------------------------------------
/components/oap-meter/include/meas_intervals.h:
--------------------------------------------------------------------------------
1 | /*
2 | * meas_intervals.h
3 | *
4 | * Created on: Mar 25, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_MEAS_INTERVALS_H_
24 | #define MAIN_MEAS_INTERVALS_H_
25 |
26 |
27 | #include "pm_meter.h"
28 |
29 | typedef struct {
30 | int warm_up_time;
31 | int meas_time;
32 | int meas_interval;
33 | } pm_meter_intervals_params_t;
34 |
35 |
36 | #endif /* MAIN_MEAS_INTERVALS_H_ */
37 |
--------------------------------------------------------------------------------
/components/oap-meter/include/pm_meter.h:
--------------------------------------------------------------------------------
1 | /*
2 | * meas.h
3 | *
4 | * Created on: Mar 25, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_MEAS_H_
24 | #define MAIN_MEAS_H_
25 |
26 | #include "oap_common.h"
27 | #include "oap_data.h"
28 |
29 | typedef struct {
30 | uint8_t heater_pin;
31 | uint8_t fan_pin;
32 | } pm_meter_aux_t;
33 |
34 | pm_meter_aux_t pm_meter_aux;
35 |
36 | typedef struct {
37 | uint8_t count;
38 | pm_data_t pm_data[2];
39 | } pm_data_pair_t;
40 |
41 | typedef enum {
42 | PM_METER_START,
43 | PM_METER_RESULT,
44 | PM_METER_ERROR
45 | } pm_meter_event_t;
46 |
47 | typedef void(*pm_meter_output_f)(pm_meter_event_t event, void* pm_data);
48 |
49 | typedef void(*pm_sensor_enable_handler_f)(uint8_t enable);
50 |
51 | typedef struct {
52 | uint8_t count;
53 | pm_sensor_enable_handler_f handler[2];
54 | } pm_sensor_enable_handler_pair_t;
55 |
56 | /**
57 | * @brief starts PM meter. it will now start collecting input samples until stop method is called
58 | *
59 | * params:
60 | * 1. handlers to enable/disable pm_sensors;
61 | * 2. pm_meter parameters
62 | * 3. output callback
63 | */
64 | typedef void(*pm_meter_start_f)(pm_sensor_enable_handler_pair_t*, void*, pm_meter_output_f);
65 |
66 | /**
67 | * @brief stops PM meter. depending on a meter, this may generate 'RESULT' event.
68 | */
69 | typedef void(*pm_meter_stop_f)();
70 |
71 | typedef struct {
72 | pm_data_callback_f input;
73 | pm_meter_start_f start;
74 | pm_meter_stop_f stop;
75 | } pm_meter_t;
76 |
77 |
78 |
79 | #endif /* MAIN_MEAS_H_ */
80 |
--------------------------------------------------------------------------------
/components/oap-meter/meas_continuous.c:
--------------------------------------------------------------------------------
1 | /*
2 | * meas_continuous.c
3 | *
4 | * Created on: Mar 25, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "meas_continuous.h"
24 |
25 | //static char* TAG = "meas_cont";
26 | //
27 | //typedef struct {
28 | // pmsx003_config_t config;
29 | // pm_data last;
30 | //} sensor_model_t;
31 | //
32 | //uint8_t sensor_count;
33 | //sensor_model_t* sensors;
34 | //
35 | //static void collect(pm_data* pm) {
36 | //
37 | //}
38 | //
39 | //static void start(pm_sensor_pair_config_t* pms_configs, meas_continuous_params_t* params, meas_strategy_callback callback) {
40 | // sensor_count = pms_configs->count;
41 | // sensors = malloc(sizeof(sensor_model_t)*sensor_count);
42 | // for (uint8_t c = 0; c < sensor_count; c++) {
43 | // sensor_model_t* sensor = sensors+c;
44 | // memset(sensor, 0, sizeof(sensor_model_t));
45 | // memcpy(&sensor->config, pms_configs->sensor[c], sizeof(pmsx003_config_t));
46 | // }
47 | //}
48 | //
49 | pm_meter_t pm_meter_continuous = {
50 | .input = NULL,
51 | .start = NULL,
52 | .stop = NULL
53 | };
54 |
--------------------------------------------------------------------------------
/components/oap-meter/meas_intervals.c:
--------------------------------------------------------------------------------
1 | /*
2 | * meas_intervals.c
3 | *
4 | * Created on: Mar 25, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "meas_intervals.h"
24 | #include "esp_log.h"
25 | #include "oap_common.h"
26 | #include "oap_debug.h"
27 | #include "esp_err.h"
28 | #include "freertos/task.h"
29 |
30 | static char* TAG = "meter_intv";
31 |
32 | typedef struct {
33 | pm_sensor_enable_handler_f handler;
34 | uint16_t sample_count;
35 | pm_data_t* samples;
36 | } sensor_model_t;
37 |
38 | static sensor_model_t* sensors;
39 | static uint8_t sensor_count;
40 | static pm_meter_output_f _callback;
41 | static pm_meter_intervals_params_t _params;
42 |
43 | static long startedAt;
44 |
45 | static void pm_data_print(char* str, uint8_t sensor, pm_data_t* pm) {
46 | ESP_LOGI(TAG, "%s[%d] pm1.0=%d pm2.5=%d pm10=%d", str, sensor, pm->pm1_0, pm->pm2_5, pm->pm10);
47 | }
48 |
49 | static void collect(pm_data_t* pm) {
50 | sensor_model_t* sensor = sensors+pm->sensor_idx;
51 |
52 | pm_data_t* buf = sensor->samples+(sensor->sample_count % CONFIG_OAP_PM_SAMPLE_BUF_SIZE);
53 | memcpy(buf, pm, sizeof(pm_data_t));
54 |
55 | if (millis() - startedAt > _params.warm_up_time * 1000) {
56 | sensor->sample_count++;
57 | pm_data_print("collect", pm->sensor_idx, buf);
58 | } else {
59 | pm_data_print("warming", pm->sensor_idx, buf);
60 | }
61 | }
62 |
63 | static void enable_sensors() {
64 | ESP_LOGI(TAG, "enable_sensors");
65 |
66 | for (uint8_t s = 0; s < sensor_count; s++) {
67 | sensors[s].sample_count = 0;
68 | sensors[s].handler(1);
69 | }
70 | }
71 |
72 | static esp_err_t pm_meter_sample(uint8_t s, pm_data_t* result, uint8_t disable_sensor) {
73 | sensor_model_t* sensor = sensors+s;
74 |
75 | if (disable_sensor) {
76 | sensor->handler(0);
77 | }
78 |
79 | uint16_t count = sensor->sample_count > CONFIG_OAP_PM_SAMPLE_BUF_SIZE ? CONFIG_OAP_PM_SAMPLE_BUF_SIZE : sensor->sample_count;
80 | if (count == 0) {
81 | ESP_LOGW(TAG, "no samples recorded for sensor %d", s);
82 | return ESP_FAIL;
83 | }
84 |
85 | memset(result, 0, sizeof(pm_data_t));
86 | pm_data_t* sample;
87 | for (uint16_t i = 0; i < count; i++) {
88 | sample = sensor->samples+i;
89 | result->pm1_0 += sample->pm1_0;
90 | result->pm2_5 += sample->pm2_5;
91 | result->pm10 += sample->pm10;
92 | }
93 |
94 | result->pm1_0 /= count;
95 | result->pm2_5 /= count;
96 | result->pm10 /= count;
97 | result->sensor_idx = s;
98 |
99 | ESP_LOGI(TAG, "stop measurement for sensor %d, recorded %d samples", s, count);
100 | pm_data_print("average", s, result);
101 |
102 | return ESP_OK;
103 | }
104 |
105 | static void task() {
106 | int delay_sec = (_params.meas_interval-_params.meas_time);
107 | while (1) {
108 | log_task_stack("pm_meter_trigger");
109 |
110 | _callback(PM_METER_START,NULL);
111 |
112 | startedAt = millis();
113 |
114 | enable_sensors();
115 |
116 | delay(_params.meas_time * 1000);
117 |
118 | pm_data_pair_t pm_data_pair = {
119 | .count = sensor_count
120 | };
121 |
122 | uint8_t ok = 1;
123 | for (uint8_t s = 0; ok && s < sensor_count; s++) {
124 | ESP_LOGI(TAG, "compute results for sensor %d", s);
125 | if (pm_meter_sample(s, pm_data_pair.pm_data+s, delay_sec>0) != ESP_OK) {
126 | _callback(PM_METER_ERROR, "cannot calculate result");
127 | ok = 0;
128 | }
129 | }
130 |
131 | if (ok) {
132 | _callback(PM_METER_RESULT,&pm_data_pair);
133 | }
134 |
135 | if (delay_sec > 0) {
136 | delay(delay_sec * 1000);
137 | } else {
138 | delay(10);
139 | }
140 | }
141 | }
142 |
143 | static TaskHandle_t task_handle = NULL;
144 | static void start(pm_sensor_enable_handler_pair_t* pm_sensor_handlers, pm_meter_intervals_params_t* params, pm_meter_output_f callback) {
145 | ESP_LOGI(TAG, "start");
146 | _callback = callback;
147 | memcpy(&_params, params, sizeof(pm_meter_intervals_params_t));
148 |
149 | sensor_count = pm_sensor_handlers->count;
150 | sensors = malloc(sizeof(sensor_model_t)*sensor_count);
151 | for (uint8_t c = 0; c < sensor_count; c++) {
152 | sensor_model_t* sensor = sensors+c;
153 | memset(sensor, 0, sizeof(sensor_model_t));
154 | sensor->handler = pm_sensor_handlers->handler[c];
155 | sensor->samples = malloc(sizeof(pm_data_t)*CONFIG_OAP_PM_SAMPLE_BUF_SIZE);
156 | }
157 | xTaskCreate(task, "pm_meter_intervals", 1024*4, NULL, DEFAULT_TASK_PRIORITY, &task_handle);
158 | }
159 |
160 | static void stop() {
161 | if (task_handle) {
162 | vTaskDelete(task_handle);
163 | task_handle = NULL;
164 | }
165 | }
166 |
167 | pm_meter_t pm_meter_intervals = {
168 | .input = &collect,
169 | .start = (pm_meter_start_f)&start,
170 | .stop = &stop
171 | };
172 |
--------------------------------------------------------------------------------
/components/oap-meter/pm_meter.c:
--------------------------------------------------------------------------------
1 | /*
2 | * meas.c
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "pm_meter.h"
24 |
25 | pm_meter_aux_t pm_meter_aux = {
26 | .heater_pin = CONFIG_OAP_HEATER_CONTROL_PIN,
27 | .fan_pin = CONFIG_OAP_FAN_CONTROL_PIN
28 | };
29 |
30 |
31 |
--------------------------------------------------------------------------------
/components/oap-meter/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-meter/test/test_pm_meter.c:
--------------------------------------------------------------------------------
1 | /*
2 | * test_meas.c
3 | *
4 | * Created on: Sep 24, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 |
24 | #include "pm_meter.h"
25 | #include "meas_intervals.h"
26 | #include "oap_test.h"
27 | #include "freertos/task.h"
28 |
29 | extern pm_meter_t pm_meter_intervals;
30 |
31 | static int fake_sensor0_enabled = 0;
32 | static int fake_sensor1_enabled = 0;
33 | static list_t* strategy_events = NULL;
34 |
35 | #define TAG "test"
36 |
37 | typedef struct {
38 | pm_meter_event_t event_type;
39 | char* error;
40 | pm_data_pair_t* result;
41 | } test_meas_record_t;
42 |
43 | static void strategy_callback(pm_meter_event_t event, void* data) {
44 | test_meas_record_t* record = malloc(sizeof(test_meas_record_t));
45 | memset(record, 0, sizeof(test_meas_record_t));
46 |
47 | record->event_type = event;
48 | switch (event) {
49 | case PM_METER_START:
50 | ESP_LOGI(TAG, "MEAS_START");
51 | break;
52 | case PM_METER_RESULT :
53 | ESP_LOGI(TAG, "MEAS_RESULT");
54 | record->result = malloc(sizeof(pm_data_pair_t));
55 | memcpy(record->result, data, sizeof(pm_data_pair_t));
56 | break;
57 | case PM_METER_ERROR:
58 | ESP_LOGI(TAG, "MEAS_ERROR: %s", (char*)data);
59 | record->error = strdup((char*)data);
60 | break;
61 | }
62 | list_insert(strategy_events, record);
63 | }
64 |
65 |
66 | static void sensor_handler0(uint8_t enable) {
67 | fake_sensor0_enabled = enable;
68 | }
69 | static void sensor_handler1(uint8_t enable) {
70 | fake_sensor1_enabled = enable;
71 | }
72 |
73 | static pm_sensor_enable_handler_pair_t pm_sensor_handler_pair;
74 | static pm_meter_intervals_params_t strategy_test_params;
75 |
76 | static TaskHandle_t fake_sensor_task_handle = NULL;
77 |
78 | static void fake_sensor() {
79 | pm_data_t sample0 = {
80 | .pm1_0 = 0,
81 | .pm2_5 = 0,
82 | .pm10 = 0,
83 | .sensor_idx = 0
84 | };
85 |
86 | pm_data_t sample1 = {
87 | .pm1_0 = 1,
88 | .pm2_5 = 2,
89 | .pm10 = 3,
90 | .sensor_idx = 1
91 | };
92 |
93 | while (1) {
94 | if (fake_sensor0_enabled) {
95 | pm_meter_intervals.input(&sample0);
96 | sample0.pm1_0++;
97 | sample0.pm2_5+=2;
98 | sample0.pm10+=4;
99 | }
100 | if (fake_sensor1_enabled) {
101 | pm_meter_intervals.input(&sample1);
102 | }
103 | delay(100);
104 | }
105 | }
106 |
107 | static int has_result(void* data) {
108 | return data && ((test_meas_record_t*)data)->event_type == PM_METER_RESULT;
109 | }
110 | static int free_record(test_meas_record_t* record) {
111 | if (record->error) free(record->error);
112 | if (record->result) free(record->result);
113 | free(record);
114 | return 0;
115 | }
116 |
117 | TEST_CASE("meas intervals","[meas]") {
118 |
119 | //configure
120 | pm_sensor_handler_pair.count = 2;
121 | pm_sensor_handler_pair.handler[0] = &sensor_handler0;
122 | pm_sensor_handler_pair.handler[1] = &sensor_handler1;
123 |
124 | strategy_test_params.warm_up_time = 1; //one sec warming
125 | strategy_test_params.meas_time = 3, //two sec collect
126 | strategy_test_params.meas_interval = 10;
127 |
128 | strategy_events = list_createList();
129 | xTaskCreate(fake_sensor, "fake_sensor", 2*1024, NULL, DEFAULT_TASK_PRIORITY, &fake_sensor_task_handle);
130 |
131 | pm_meter_intervals.start(&pm_sensor_handler_pair, &strategy_test_params, strategy_callback);
132 | list_t* result_record;
133 |
134 | //wait a bit longer for a result
135 | test_timer_t timer = {.started = 0, .wait_for = strategy_test_params.meas_time * 1000 + 1000};
136 | while ((result_record = list_find(strategy_events, &has_result)) == NULL && !test_timeout(&timer)) {
137 | delay(50);
138 | }
139 |
140 | //cleanup
141 | pm_meter_intervals.stop();
142 | vTaskDelete(fake_sensor_task_handle);
143 |
144 | //check
145 | if (!result_record) {
146 | list_deleteListAndValues(strategy_events, (node_value_predicate)&free_record);
147 | TEST_FAIL_MESSAGE("timeout while waiting for measurement result_record");
148 | } else {
149 | pm_data_pair_t* meas_data = ((test_meas_record_t*)(result_record->value))->result;
150 | //sensor 0
151 | TEST_ASSERT_EQUAL_INT8(0, meas_data->pm_data[0].sensor_idx);
152 | TEST_ASSERT_MESSAGE(meas_data->pm_data[0].pm1_0 >= 19 && meas_data->pm_data[0].pm1_0 <= 21, "invalid 0->pm1.0 avg");
153 | TEST_ASSERT_MESSAGE(meas_data->pm_data[0].pm2_5 >= 38 && meas_data->pm_data[0].pm2_5 <= 42, "invalid 0->pm2.5 avg");
154 | TEST_ASSERT_MESSAGE(meas_data->pm_data[0].pm10 >= 76 && meas_data->pm_data[0].pm10 <= 84, "invalid 0->pm10 avg");
155 | TEST_ASSERT_FALSE_MESSAGE(fake_sensor0_enabled, "sensor0 not disabled after measurement");
156 |
157 | //sensor 1
158 | TEST_ASSERT_EQUAL_INT8(1, meas_data->pm_data[1].sensor_idx);
159 | TEST_ASSERT_EQUAL_INT16(1, meas_data->pm_data[1].pm1_0);
160 | TEST_ASSERT_EQUAL_INT16(2, meas_data->pm_data[1].pm2_5);
161 | TEST_ASSERT_EQUAL_INT16(3, meas_data->pm_data[1].pm10);
162 | TEST_ASSERT_FALSE_MESSAGE(fake_sensor1_enabled, "sensor1 not disabled after measurement");
163 | list_deleteListAndValues(strategy_events, (node_value_predicate)&free_record);
164 | }
165 |
166 | }
167 |
--------------------------------------------------------------------------------
/components/oap-ota/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP OTA updates"
2 |
3 | config OAP_OTA_ENABLED
4 | int "enable OTA updates"
5 | default 1
6 | help
7 | enable automatic over-the-air updates
8 |
9 | config OAP_OTA_BIN_URI_PREFIX
10 | string "bin uri prefix"
11 | default "https://openairproject.com/ota/"
12 | help
13 | This prefix will be used to construct a full URI of a binary with OTA file.
14 | It is recommended to define as strictly as possible to increase security.
15 | Malicious index file won't be able to force update from different server / path.
16 |
17 | config OAP_OTA_INDEX_URI
18 | string "index uri"
19 | default "https://openairproject.com/ota/index.txt"
20 | help
21 | full URI to file with OTA definition
22 |
23 | endmenu
--------------------------------------------------------------------------------
/components/oap-ota/comodo_ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
3 | MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
4 | IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
5 | MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
6 | FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
7 | bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
8 | dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
9 | H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
10 | uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
11 | mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
12 | a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
13 | E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
14 | WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
15 | VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
16 | Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
17 | cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
18 | IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
19 | AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
20 | YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
21 | 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
22 | Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
23 | c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
24 | mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
25 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/components/oap-ota/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
10 | # GitHub (https://www.digicert.com/CACerts/DigiCertHighAssuranceEVRootCA.crt)
11 | #COMPONENT_EMBED_TXTFILES = digicert_ca.pem
12 |
13 | # openairproject.com (CloudFront)
14 | COMPONENT_EMBED_TXTFILES = comodo_ca.pem
15 |
--------------------------------------------------------------------------------
/components/oap-ota/digicert_ca.crt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/components/oap-ota/digicert_ca.crt
--------------------------------------------------------------------------------
/components/oap-ota/digicert_ca.pem:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
5 | ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
6 | MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
7 | LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
8 | RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
9 | +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
10 | PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
11 | xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
12 | Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
13 | hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
14 | EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
15 | MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
16 | FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
17 | nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
18 | eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
19 | hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
20 | Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
21 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
22 | +OkuE6N36B9K
23 | -----END CERTIFICATE-----
24 |
--------------------------------------------------------------------------------
/components/oap-ota/include/ota.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ota.h
3 | *
4 | * Created on: Sep 10, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OTA_INCLUDE_OTA_H_
24 | #define COMPONENTS_OTA_INCLUDE_OTA_H_
25 |
26 | #include "oap_common.h"
27 | #include "cJSON.h"
28 |
29 | #define OAP_OTA_ENABLED CONFIG_OAP_OTA_ENABLED
30 | #define OAP_OTA_BIN_URI_PREFIX CONFIG_OAP_OTA_BIN_URI_PREFIX
31 | #define OAP_OTA_INDEX_URI CONFIG_OAP_OTA_INDEX_URI
32 |
33 | void start_ota_task(cJSON* user_ota_config);
34 | void reset_to_factory_partition();
35 |
36 | #endif /* COMPONENTS_OTA_INCLUDE_OTA_H_ */
37 |
--------------------------------------------------------------------------------
/components/oap-ota/ota_int.h:
--------------------------------------------------------------------------------
1 | /*
2 | * ota_int.h
3 | *
4 | * Created on: Sep 14, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_OTA_OTA_INT_H_
24 | #define COMPONENTS_OTA_OTA_INT_H_
25 |
26 |
27 | #include "ota.h"
28 | #include "esp_err.h"
29 | #include "esp_ota_ops.h"
30 | #include "oap_version.h"
31 |
32 | #define OAP_OTA_ERR_REQUEST_FAILED 0x1001
33 | #define OAP_OTA_ERR_NO_UPDATES 0x1002
34 | #define OAP_OTA_ERR_EMPTY_RESPONSE 0x1003
35 | #define OAP_OTA_ERR_MALFORMED_INFO 0x1004
36 | #define OAP_OTA_ERR_SHA_MISMATCH 0x1005
37 |
38 | typedef struct {
39 | char* bin_uri_prefix;
40 | char* index_uri;
41 | unsigned int interval; // for <=0 it checks only once
42 | int commit_and_reboot;
43 | const esp_partition_t *update_partition;
44 | unsigned long min_version;
45 | } ota_config_t;
46 |
47 | typedef struct {
48 | char* sha;
49 | char* file;
50 | oap_version_t ver;
51 | } ota_info_t;
52 |
53 | /*
54 | * ota_info has to be freed with free_ota_info
55 | */
56 | esp_err_t is_ota_available(ota_config_t* ota_config, ota_info_t* ota_info);
57 |
58 | /*
59 | * ota_info has to be freed with free_ota_info
60 | */
61 | esp_err_t fetch_last_ota_info(ota_config_t* ota_config, ota_info_t* ota_info);
62 | void free_ota_info(ota_info_t* ota_info);
63 | esp_err_t parse_ota_info(ota_info_t* ota_info, char* line, int len);
64 | esp_err_t check_ota(ota_config_t* ota_config);
65 |
66 |
67 | #endif /* COMPONENTS_OTA_OTA_INT_H_ */
68 |
--------------------------------------------------------------------------------
/components/oap-ota/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-ota/test/files/hello-world.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/components/oap-ota/test/files/hello-world.bin
--------------------------------------------------------------------------------
/components/oap-ota/test/files/index-sha-mismatch.txt:
--------------------------------------------------------------------------------
1 | 1.2.3|hello-world.bin|99999999b5d1f4e98d810a36e361b84f62d8363de55fba487b81ebe0b3d4f676
2 |
--------------------------------------------------------------------------------
/components/oap-ota/test/files/index.txt:
--------------------------------------------------------------------------------
1 | 1.2.3|hello-world.bin|304717e6b5d1f4e98d810a36e361b84f62d8363de55fba487b81ebe0b3d4f676
2 |
--------------------------------------------------------------------------------
/components/oap-ota/test/test_ota.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include "unity.h"
7 | #include "nvs.h"
8 | #include "nvs_flash.h"
9 | #include "esp_partition.h"
10 | #include "esp_log.h"
11 | #include
12 | #include "ota.h"
13 | #include "bootwifi.h"
14 | #include "oap_test.h"
15 | #include "oap_common.h"
16 | #include "oap_version.h"
17 | #include "mbedtls/sha256.h"
18 |
19 | #include "../ota_int.h"
20 |
21 | static const char* TAG = "test_ota";
22 |
23 | static ota_config_t ota_test_config = {
24 | .index_uri = "https://openairproject.com/ota/test/index.txt",
25 | .bin_uri_prefix = "https://openairproject.com/ota/test/",
26 | .commit_and_reboot = 0,
27 | .update_partition = NULL,
28 | .interval = 0
29 | };
30 |
31 | static ota_info_t hello_world_info = {
32 | .file = "hello-world.bin",
33 | .sha = "304717e6b5d1f4e98d810a36e361b84f62d8363de55fba487b81ebe0b3d4f676",
34 | .ver = {
35 | .major = 1,
36 | .minor = 2,
37 | .patch = 3
38 | }
39 | };
40 |
41 | void sha_to_hexstr(unsigned char hash[32], unsigned char hex[64]);
42 |
43 | static void TEST_ASSERT_EQUAL_VER(uint8_t expected_major, uint8_t expected_minor, uint8_t expected_patch, oap_version_t* version) {
44 | TEST_ASSERT_EQUAL_INT(expected_major, version->major);
45 | TEST_ASSERT_EQUAL_INT(expected_minor, version->minor);
46 | TEST_ASSERT_EQUAL_INT(expected_patch, version->patch);
47 | }
48 |
49 | TEST_CASE("sha","[ota]")
50 | {
51 | char* input = "hello world";
52 | char* output = "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9";
53 |
54 | unsigned char hash[32];
55 | unsigned char hex[65];
56 | hex[64] = 0;
57 |
58 | //single value
59 | mbedtls_sha256((unsigned char*)input, strlen(input), hash, 0);
60 | sha_to_hexstr(hash, hex);
61 | TEST_ASSERT_EQUAL_STRING(output, hex);
62 |
63 | //in parts
64 | mbedtls_sha256_context sha_context;
65 | mbedtls_sha256_init(&sha_context);
66 | mbedtls_sha256_starts(&sha_context,0);
67 | for (int i = 0; i < strlen(input); i++) {
68 | mbedtls_sha256_update(&sha_context, (unsigned char *)input+i, 1);
69 | }
70 | mbedtls_sha256_finish(&sha_context, hash);
71 | mbedtls_sha256_free(&sha_context);
72 | sha_to_hexstr(hash, hex);
73 | TEST_ASSERT_EQUAL_STRING(output, hex);
74 | }
75 |
76 |
77 | TEST_CASE("fetch_last_ota_info", "[ota]")
78 | {
79 | test_require_wifi();
80 | ota_info_t info;
81 | /*
82 | * heap consumption goes to 0 after ~5 requests
83 | */
84 | size_t curr_heap = 0;
85 | size_t prev_heap = 0;
86 | for (int i = 0; i < 1; i++) {
87 | curr_heap = xPortGetFreeHeapSize();
88 | ESP_LOGW(TAG, "REQUEST %d (heap %u, %d bytes)", i, curr_heap, curr_heap-prev_heap);
89 | prev_heap = curr_heap;
90 | TEST_ESP_OK(fetch_last_ota_info(&ota_test_config, &info));
91 | TEST_ASSERT_EQUAL_STRING(hello_world_info.file, info.file);
92 | TEST_ASSERT_EQUAL_VER(hello_world_info.ver.major,hello_world_info.ver.minor,hello_world_info.ver.patch,&info.ver);
93 | TEST_ASSERT_EQUAL_STRING(hello_world_info.sha, info.sha);
94 | if (i) delay(1000);
95 | }
96 | }
97 |
98 | //TEST_CASE("fetch_last_ota_info - LL", "[ota]")
99 | //{
100 | // test_require_wifi();
101 | // ota_info_t info = {
102 | // .sha = NULL,
103 | // .file = NULL
104 | // };
105 | // /*
106 | // * heap consumption goes to 0 after ~5 requests
107 | // */
108 | // size_t curr_heap = 0;
109 | // size_t prev_heap = 0;
110 | // for (int i = 0; i < 1000; i++) {
111 | // curr_heap = xPortGetFreeHeapSize();
112 | // ESP_LOGW(TAG, "REQUEST %d (heap %u, %d bytes)", i, curr_heap, curr_heap-prev_heap);
113 | // prev_heap = curr_heap;
114 | // fetch_last_ota_info(&ota_test_config, &info);
115 | // free_ota_info(&info);
116 | // if (i) delay(1000);
117 | // }
118 | //}
119 |
120 | TEST_CASE("parse_ota_info","[ota]")
121 | {
122 | ota_info_t info;
123 | char* data = "1.2.3|hello-world.bin|929fd82b12f4e67cfa08a14e763232a95820b7f2b2edcce744e1c1711c7c9e04\r\n";
124 | parse_ota_info(&info, data, strlen(data));
125 |
126 | TEST_ASSERT_EQUAL_STRING("hello-world.bin", info.file);
127 | TEST_ASSERT_EQUAL_VER(1,2,3,&info.ver);
128 | TEST_ASSERT_EQUAL_STRING("929fd82b12f4e67cfa08a14e763232a95820b7f2b2edcce744e1c1711c7c9e04", info.sha);
129 | }
130 |
131 | //TEST_CASE("download_ota_binary", "[ota]")
132 | //{
133 | // test_require_wifi();
134 | // TEST_ESP_OK(download_ota_binary(&ota_test_config, &hello_world_info, NULL));
135 | //}
136 |
137 | TEST_CASE("full ota", "[ota]")
138 | {
139 | test_require_wifi();
140 | ota_config_t ota_config;
141 | memcpy(&ota_config, &ota_test_config, sizeof(ota_config_t));
142 | ota_config.min_version=oap_version_num(hello_world_info.ver) - 1; //one patch earlier
143 |
144 | int ret = check_ota(&ota_config);
145 |
146 | //if OTA partition is too small, you'll get 'segment invalid length error'
147 | TEST_ESP_OK(ret);
148 | TEST_ASSERT_NOT_NULL(ota_config.update_partition);
149 | }
150 |
151 | TEST_CASE("skip ota if up-to-date", "[ota]")
152 | {
153 | test_require_wifi();
154 | ota_config_t ota_config;
155 | memcpy(&ota_config, &ota_test_config, sizeof(ota_config_t));
156 | ota_config.min_version=oap_version_num(hello_world_info.ver); //the same version
157 |
158 | int ret = check_ota(&ota_config);
159 | TEST_ASSERT_EQUAL_UINT16(OAP_OTA_ERR_NO_UPDATES, ret);
160 | }
161 |
162 | TEST_CASE("fail ota for sha mismatch", "[ota]")
163 | {
164 | test_require_wifi();
165 | ota_config_t ota_config;
166 | memcpy(&ota_config, &ota_test_config, sizeof(ota_config_t));
167 | ota_config.index_uri = "https://openairproject.com/ota/test/index-sha-mismatch.txt",
168 | ota_config.min_version=oap_version_num(hello_world_info.ver) - 1; //one patch earlier
169 |
170 | int ret = check_ota(&ota_config);
171 | TEST_ASSERT_EQUAL_UINT16(OAP_OTA_ERR_SHA_MISMATCH, ret);
172 | }
173 |
174 | TEST_CASE("fail ota for invalid cert", "[ota]")
175 | {
176 | test_require_wifi();
177 | //git uses digicert CA, cloud front - comodo CA
178 | ota_config_t ota_config = {
179 | .index_uri = "https://raw.githubusercontent.com/openairproject/sensor-esp32/master/components/ota/test/files/index.txt",
180 | .bin_uri_prefix = "https://raw.githubusercontent.com/openairproject/sensor-esp32/master/components/ota/test/files/"
181 | };
182 |
183 | ota_config.min_version=oap_version_num(hello_world_info.ver) - 1; //one patch earlier
184 |
185 | int ret = check_ota(&ota_config);
186 | TEST_ASSERT_EQUAL_UINT16(OAP_OTA_ERR_REQUEST_FAILED, ret);
187 | }
188 |
--------------------------------------------------------------------------------
/components/oap-thingspk/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
--------------------------------------------------------------------------------
/components/oap-thingspk/include/thing_speak.h:
--------------------------------------------------------------------------------
1 | /*
2 | * http.h
3 | *
4 | * Created on: Feb 6, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_THING_SPEAK_H_
24 | #define COMPONENTS_THING_SPEAK_H_
25 |
26 | #include "esp_err.h"
27 | #include "oap_publisher.h"
28 |
29 |
30 | oap_publisher_t thingspeak_publisher;
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/components/oap-thingspk/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-thingspk/test/test_thing_speak.c:
--------------------------------------------------------------------------------
1 | /*
2 | * test_thing_speak.c
3 | *
4 | * Created on: Oct 1, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "thing_speak.h"
24 | #include "oap_test.h"
25 |
26 | #define TEST_API_KEY "QMN6JJM996QXBORX"
27 |
28 | TEST_CASE("publish to thingspeak", "[tspk]") {
29 | test_require_wifi();
30 |
31 | cJSON* cfg = cJSON_CreateObject();
32 | cJSON_AddNumberToObject(cfg, "enabled", 1);
33 | cJSON_AddStringToObject(cfg, "apikey", TEST_API_KEY);
34 |
35 | TEST_ESP_OK(thingspeak_publisher.configure(cfg));
36 | cJSON_Delete(cfg);
37 |
38 | pm_data_t pm = {
39 | .pm1_0 = 10,
40 | .pm2_5 = 25,
41 | .pm10 = 50,
42 | .sensor_idx = 0
43 | };
44 |
45 | pm_data_t pm_aux = {
46 | .pm1_0 = 11,
47 | .pm2_5 = 26,
48 | .pm10 = 51,
49 | .sensor_idx = 1
50 | };
51 |
52 | env_data_t env = {
53 | .temp = 15.5,
54 | .pressure = 999.9,
55 | .humidity = 79.11,
56 | .sensor_idx = 0
57 | };
58 |
59 | env_data_t env_int = {
60 | .temp = 22.1,
61 | .pressure = 997.9,
62 | .humidity = 43.89,
63 | .sensor_idx = 1
64 | };
65 |
66 | oap_measurement_t meas = {
67 | .pm = &pm,
68 | .pm_aux = &pm_aux,
69 | .env = &env,
70 | .env_int = &env_int,
71 | .local_time = 1505156826
72 | };
73 |
74 | oap_sensor_config_t sensor_config = {
75 | .0
76 | };
77 |
78 | size_t curr_heap = 0;
79 | size_t prev_heap = 0;
80 |
81 | /*
82 | * heap consumption goes to 0 after ~10 requests
83 | * warning - thingspeak cuts off abusive devices after a while
84 | */
85 | for (int i = 0; i < 1; i++) {
86 | curr_heap = xPortGetFreeHeapSize();
87 | ESP_LOGW("test", "REQUEST %d (heap %u, %d bytes)", i, curr_heap, curr_heap-prev_heap);
88 | prev_heap = curr_heap;
89 | TEST_ESP_OK(thingspeak_publisher.publish(&meas, &sensor_config));
90 | if (i) test_delay(1000);
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/components/oap-thingspk/thing_speak.c:
--------------------------------------------------------------------------------
1 | /*
2 | * http.c
3 | *
4 | * Created on: Feb 6, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "thing_speak.h"
24 |
25 | #include "oap_common.h"
26 | #include "oap_storage.h"
27 | #include "oap_debug.h"
28 | #include "esp_request.h"
29 | #include "bootwifi.h"
30 |
31 | //to use https we'd need to install CA cert first.
32 | #define OAP_THING_SPEAK_URI "http://api.thingspeak.com/update"
33 |
34 | static const char *TAG = "thingspk";
35 |
36 | static char* apikey = NULL;
37 | static int _configured = 0;
38 |
39 | static void set_config_str_field(char** field, char* value) {
40 | if (*field) {
41 | free(*field);
42 | }
43 | *field = str_dup(value);
44 | }
45 |
46 | static char* prepare_thingspeak_payload(oap_measurement_t* meas) {
47 | char* payload = malloc(512);
48 | if (!payload) return NULL;
49 | sprintf(payload, "api_key=%s", apikey);
50 |
51 | if (meas->pm) {
52 | sprintf(payload, "%s&field1=%d&field2=%d&field3=%d", payload,
53 | meas->pm->pm1_0,
54 | meas->pm->pm2_5,
55 | meas->pm->pm10);
56 | }
57 |
58 | if (meas->env) {
59 | sprintf(payload, "%s&field4=%.2f&field5=%.2f&field6=%.2f", payload,
60 | meas->env->temp,
61 | meas->env->pressure,
62 | meas->env->humidity);
63 | }
64 |
65 | //memory metrics
66 | sprintf(payload, "%s&field7=%d&field8=%d", payload,
67 | avg_free_heap_size(),
68 | xPortGetMinimumEverFreeHeapSize());
69 |
70 | return payload;
71 | }
72 |
73 | static esp_err_t rest_post(char* uri, char* payload) {
74 | request_t* req = req_new(uri);
75 | if (!req) {
76 | return ESP_FAIL;
77 | }
78 | ESP_LOGD(TAG, "request payload: %s", payload);
79 |
80 | req_setopt(req, REQ_SET_POSTFIELDS, payload);
81 | req_setopt(req, REQ_SET_HEADER, HTTP_HEADER_CONNECTION_CLOSE);
82 |
83 | int response_code = req_perform(req);
84 | req_clean(req);
85 | if (response_code == 200) {
86 | ESP_LOGI(TAG, "update succeeded");
87 | return ESP_OK;
88 | } else {
89 | ESP_LOGW(TAG, "update failed (response code: %d)", response_code);
90 | return ESP_FAIL;
91 | }
92 |
93 | }
94 |
95 | static esp_err_t thing_speak_configure(cJSON* thingspeak) {
96 | _configured = 0;
97 | if (!thingspeak) {
98 | ESP_LOGI(TAG, "config not found");
99 | return ESP_FAIL;
100 | }
101 |
102 | cJSON* field;
103 | if (!(field = cJSON_GetObjectItem(thingspeak, "enabled")) || !field->valueint) {
104 | ESP_LOGI(TAG, "client disabled");
105 | return ESP_FAIL;
106 | }
107 |
108 | if ((field = cJSON_GetObjectItem(thingspeak, "apikey")) && field->valuestring) {
109 | set_config_str_field(&apikey, field->valuestring);
110 | } else {
111 | ESP_LOGW(TAG, "apikey not configured");
112 | return ESP_FAIL;
113 | }
114 |
115 | _configured = 1;
116 | return ESP_OK;
117 | }
118 |
119 | static esp_err_t thing_speak_send(oap_measurement_t* meas, oap_sensor_config_t* oap_sensor_config) {
120 | if (!_configured) {
121 | ESP_LOGE(TAG, "thingspeak not configured");
122 | return ESP_FAIL;
123 | }
124 | esp_err_t ret;
125 | if ((ret = wifi_connected_wait_for(5000)) != ESP_OK) {
126 | ESP_LOGW(TAG, "no connectivity, skip");
127 | return ret;
128 | }
129 |
130 | char* payload = prepare_thingspeak_payload(meas);
131 | if (payload) {
132 | esp_err_t ret = rest_post(OAP_THING_SPEAK_URI, payload);
133 | free(payload);
134 | return ret;
135 | } else {
136 | return ESP_FAIL;
137 | }
138 | }
139 |
140 | oap_publisher_t thingspeak_publisher = {
141 | .name = "ThingSpeak",
142 | .configure = thing_speak_configure,
143 | .publish = &thing_speak_send
144 | };
145 |
--------------------------------------------------------------------------------
/components/oap-wifi/Kconfig:
--------------------------------------------------------------------------------
1 | menu "OAP WIFI"
2 |
3 | config OAP_AP_PASSWORD
4 | string "AccessPoint password"
5 | default "cleanair"
6 | help
7 | Password to authenticate to WiFi Access Point when sensor runs in this mode.
8 | Minimum 8 characters.
9 |
10 | endmenu
--------------------------------------------------------------------------------
/components/oap-wifi/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 | COMPONENT_EMBED_TXTFILES := index.html
--------------------------------------------------------------------------------
/components/oap-wifi/cpanel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * cpanel.c
3 | *
4 | * Created on: Oct 5, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "oap_common.h"
24 | #include "mongoose.h"
25 | #include "cJSON.h"
26 | #include "oap_storage.h"
27 |
28 | #define tag "cpanel"
29 |
30 | extern const uint8_t index_html_start[] asm("_binary_index_html_start");
31 | extern const uint8_t index_html_end[] asm("_binary_index_html_end");
32 |
33 | static char *mgStrToStr(struct mg_str mgStr) {
34 | char *retStr = (char *) malloc(mgStr.len + 1);
35 | memcpy(retStr, mgStr.p, mgStr.len);
36 | retStr[mgStr.len] = 0;
37 | return retStr;
38 | } // mgStrToStr
39 |
40 | static void handler_index(struct mg_connection *nc) {
41 | size_t resp_size = index_html_end-index_html_start;
42 | mg_send_head(nc, 200, resp_size, "Content-Type: text/html");
43 | mg_send(nc, index_html_start, resp_size);
44 | ESP_LOGD(tag, "served %d bytes", resp_size);
45 | }
46 |
47 | static void handler_get_config(struct mg_connection *nc, struct http_message *message) {
48 | ESP_LOGD(tag, "handler_get_config");
49 | cJSON* config = storage_get_config_to_update();
50 | char* json = cJSON_Print(config);
51 | char* headers = malloc(200);
52 | sprintf(headers, "Content-Type: application/json\r\nX-Version: %s", oap_version_str());
53 | mg_send_head(nc, 200, strlen(json), headers);
54 | mg_send(nc, json, strlen(json));
55 | free(headers);
56 | free(json);
57 | }
58 |
59 | static void handler_reboot(struct mg_connection *nc) {
60 | mg_send_head(nc, 200, 0, "Content-Type: text/plain");
61 | oap_reboot("requested by user");
62 | }
63 |
64 | static void handler_set_config(struct mg_connection *nc, struct http_message *message) {
65 | ESP_LOGD(tag, "handler_set_config");
66 | char *body = mgStrToStr(message->body);
67 | cJSON* config = cJSON_Parse(body);
68 | free(body);
69 | if (config) {
70 | storage_update_config(config);
71 | handler_get_config(nc, message);
72 | } else {
73 | mg_http_send_error(nc, 500, "invalid config");
74 | }
75 | cJSON_Delete(config);
76 | }
77 |
78 | /**
79 | * Handle mongoose events. These are mostly requests to process incoming
80 | * browser requests. The ones we handle are:
81 | * GET / - Send the enter details page.
82 | * GET /set - Set the connection info (REST request).
83 | * POST /ssidSelected - Set the connection info (HTML FORM).
84 | */
85 | void cpanel_event_handler(struct mg_connection *nc, int ev, void *evData) {
86 | ESP_LOGV(tag, "- Event: %d", ev);
87 | uint8_t handled = 0;
88 | switch (ev) {
89 | case MG_EV_HTTP_REQUEST: {
90 | struct http_message *message = (struct http_message *) evData;
91 |
92 | //mg_str is not terminated with '\0'
93 | char *uri = mgStrToStr(message->uri);
94 | char *method = mgStrToStr(message->method);
95 |
96 | ESP_LOGD(tag, "%s %s", method, uri);
97 |
98 | if (strcmp(uri, "/") == 0) {
99 | handler_index(nc);
100 | handled = 1;
101 | }
102 | if (strcmp(uri, "/reboot") == 0) {
103 | handler_reboot(nc);
104 | handled = 1;
105 | }
106 | if(strcmp(uri, "/config") == 0) {
107 | if (strcmp(method, "GET") == 0) {
108 | handler_get_config(nc, message);
109 | handled = 1;
110 | } else if (strcmp(method, "POST") == 0) {
111 | handler_set_config(nc, message);
112 | handled = 1;
113 | }
114 | }
115 |
116 | if (!handled) {
117 | mg_send_head(nc, 404, 0, "Content-Type: text/plain");
118 | }
119 | nc->flags |= MG_F_SEND_AND_CLOSE;
120 | free(uri);
121 | free(method);
122 | break;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/components/oap-wifi/cpanel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * cpanel.h
3 | *
4 | * Created on: Oct 5, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_BOOTWIFI_CPANEL_H_
24 | #define COMPONENTS_BOOTWIFI_CPANEL_H_
25 |
26 |
27 | #include "mongoose.h"
28 |
29 | void cpanel_event_handler(struct mg_connection *nc, int ev, void *evData);
30 |
31 |
32 | #endif /* COMPONENTS_BOOTWIFI_CPANEL_H_ */
33 |
--------------------------------------------------------------------------------
/components/oap-wifi/include/bootwifi.h:
--------------------------------------------------------------------------------
1 | /*
2 | * bootwifi.h
3 | *
4 | * Created on: Nov 25, 2016
5 | * Author: kolban
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_BOOTWIFI_H_
24 | #define MAIN_BOOTWIFI_H_
25 |
26 | #include
27 | #include "cJSON.h"
28 |
29 | #define SSID_SIZE (32) // Maximum SSID size
30 | #define PASSWORD_SIZE (64) // Maximum password size
31 |
32 | typedef void(*wifi_state_callback_f)(bool connected, bool ap_mode);
33 |
34 | typedef struct {
35 | char ssid[SSID_SIZE];
36 | char password[PASSWORD_SIZE];
37 | tcpip_adapter_ip_info_t ipInfo; // Optional static IP information
38 | int ap_mode;
39 | int control_panel;
40 | wifi_state_callback_f callback;
41 | } oc_wifi_t;
42 |
43 |
44 |
45 | esp_err_t wifi_configure(cJSON* wifi, wifi_state_callback_f wifi_state_callback);
46 | void wifi_boot();
47 | esp_err_t wifi_connected_wait_for(uint32_t ms);
48 | esp_err_t wifi_ap_started_wait_for(uint32_t ms);
49 | esp_err_t wifi_disconnected_wait_for(uint32_t ms);
50 |
51 |
52 |
53 | #endif /* MAIN_BOOTWIFI_H_ */
54 |
--------------------------------------------------------------------------------
/components/oap-wifi/include/server_cpanel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * server_cpanel.h
3 | *
4 | * Created on: Oct 5, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_BOOTWIFI_INCLUDE_SERVER_CPANEL_H_
24 | #define COMPONENTS_BOOTWIFI_INCLUDE_SERVER_CPANEL_H_
25 |
26 | #include
27 |
28 | void cpanel_wifi_handler(bool connected, bool ap_mode);
29 |
30 |
31 | #endif /* COMPONENTS_BOOTWIFI_INCLUDE_SERVER_CPANEL_H_ */
32 |
--------------------------------------------------------------------------------
/components/oap-wifi/server.c:
--------------------------------------------------------------------------------
1 | /*
2 | * server.c
3 | *
4 | * Created on: Oct 4, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "server.h"
24 | #include
25 | #include
26 | #include
27 | #include
28 | #include "esp_err.h"
29 | #include "oap_common.h"
30 |
31 | #define tag "serv"
32 |
33 | typedef enum {
34 | NOT_RUN = 0,
35 | IDLE,
36 | RUNNING,
37 | RESTARTING
38 | } server_mode_t;
39 |
40 | extern int mg_invalid_socket;
41 |
42 | static server_mode_t mode = NOT_RUN;
43 |
44 | /*
45 | char *mongoose_eventToString(int ev) {
46 | static char temp[100];
47 | switch (ev) {
48 | case MG_EV_CONNECT:
49 | return "MG_EV_CONNECT";
50 | case MG_EV_ACCEPT:
51 | return "MG_EV_ACCEPT";
52 | case MG_EV_CLOSE:
53 | return "MG_EV_CLOSE";
54 | case MG_EV_SEND:
55 | return "MG_EV_SEND";
56 | case MG_EV_RECV:
57 | return "MG_EV_RECV";
58 | case MG_EV_HTTP_REQUEST:
59 | return "MG_EV_HTTP_REQUEST";
60 | case MG_EV_MQTT_CONNACK:
61 | return "MG_EV_MQTT_CONNACK";
62 | case MG_EV_MQTT_CONNACK_ACCEPTED:
63 | return "MG_EV_MQTT_CONNACK";
64 | case MG_EV_MQTT_CONNECT:
65 | return "MG_EV_MQTT_CONNECT";
66 | case MG_EV_MQTT_DISCONNECT:
67 | return "MG_EV_MQTT_DISCONNECT";
68 | case MG_EV_MQTT_PINGREQ:
69 | return "MG_EV_MQTT_PINGREQ";
70 | case MG_EV_MQTT_PINGRESP:
71 | return "MG_EV_MQTT_PINGRESP";
72 | case MG_EV_MQTT_PUBACK:
73 | return "MG_EV_MQTT_PUBACK";
74 | case MG_EV_MQTT_PUBCOMP:
75 | return "MG_EV_MQTT_PUBCOMP";
76 | case MG_EV_MQTT_PUBLISH:
77 | return "MG_EV_MQTT_PUBLISH";
78 | case MG_EV_MQTT_PUBREC:
79 | return "MG_EV_MQTT_PUBREC";
80 | case MG_EV_MQTT_PUBREL:
81 | return "MG_EV_MQTT_PUBREL";
82 | case MG_EV_MQTT_SUBACK:
83 | return "MG_EV_MQTT_SUBACK";
84 | case MG_EV_MQTT_SUBSCRIBE:
85 | return "MG_EV_MQTT_SUBSCRIBE";
86 | case MG_EV_MQTT_UNSUBACK:
87 | return "MG_EV_MQTT_UNSUBACK";
88 | case MG_EV_MQTT_UNSUBSCRIBE:
89 | return "MG_EV_MQTT_UNSUBSCRIBE";
90 | case MG_EV_WEBSOCKET_HANDSHAKE_REQUEST:
91 | return "MG_EV_WEBSOCKET_HANDSHAKE_REQUEST";
92 | case MG_EV_WEBSOCKET_HANDSHAKE_DONE:
93 | return "MG_EV_WEBSOCKET_HANDSHAKE_DONE";
94 | case MG_EV_WEBSOCKET_FRAME:
95 | return "MG_EV_WEBSOCKET_FRAME";
96 | }
97 | sprintf(temp, "Unknown event: %d", ev);
98 | return temp;
99 | }*/
100 |
101 |
102 | static esp_err_t main_loop(void *mongoose_event_handler) {
103 | struct mg_mgr mgr;
104 | struct mg_connection *connection;
105 |
106 | ESP_LOGD(tag, ">> main_loop");
107 | mg_mgr_init(&mgr, NULL);
108 |
109 | connection = mg_bind(&mgr, ":80", mongoose_event_handler);
110 |
111 | if (connection == NULL) {
112 | //when this happens usually it won't recover until it gets a new IP
113 | //maybe we should reboot?
114 | ESP_LOGW(tag, "No connection from the mg_bind().");
115 | mg_mgr_free(&mgr);
116 | return ESP_FAIL;
117 | }
118 | //use http
119 | mg_set_protocol_http_websocket(connection);
120 |
121 | mg_invalid_socket=0; //hack for corrupted mongoose sockets (AP mode + http request triggers it)
122 | while (mode == RUNNING && !mg_invalid_socket) {
123 | mg_mgr_poll(&mgr, 1000);
124 | }
125 |
126 | mg_mgr_free(&mgr);
127 | ESP_LOGD(tag, "<< main_loop");
128 | return ESP_OK;
129 | }
130 |
131 | static void server_task(void *mongoose_event_handler) {
132 | ESP_LOGD(tag, "start");
133 | while (1) {
134 | switch (mode) {
135 | case RUNNING:
136 | if (main_loop(mongoose_event_handler) != ESP_OK) {
137 | vTaskDelay(1000 / portTICK_PERIOD_MS);
138 | }
139 | break;
140 | case IDLE:
141 | vTaskDelay(1000 / portTICK_PERIOD_MS);
142 | break;
143 | default: //{RESTARTING,NOT_RUN} => RUNNING
144 | mode = RUNNING;
145 | }
146 | }
147 | vTaskDelete(NULL);
148 | }
149 |
150 | void server_restart() {
151 | ESP_LOGD(tag, "restart");
152 | mode = RESTARTING;
153 | }
154 |
155 | void server_stop() {
156 | ESP_LOGD(tag, "idle");
157 | mode = IDLE;
158 | }
159 |
160 | void server_start(void *event_handler) {
161 | if (mode == NOT_RUN) {
162 | mode = RUNNING;
163 | xTaskCreatePinnedToCore(&server_task, "mongoose_task", 10000, event_handler, DEFAULT_TASK_PRIORITY+1, NULL, 0);
164 | } else {
165 | server_restart();
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/components/oap-wifi/server.h:
--------------------------------------------------------------------------------
1 | /*
2 | * server.h
3 | *
4 | * Created on: Oct 4, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef COMPONENTS_BOOTWIFI_SERVER_H_
24 | #define COMPONENTS_BOOTWIFI_SERVER_H_
25 |
26 | #include "mongoose.h"
27 |
28 | void server_restart();
29 | void server_stop();
30 | void server_start(void *event_handler);
31 |
32 |
33 |
34 | #endif /* COMPONENTS_BOOTWIFI_SERVER_H_ */
35 |
--------------------------------------------------------------------------------
/components/oap-wifi/server_cpanel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * server_cpanel.c
3 | *
4 | * Created on: Oct 5, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "server_cpanel.h"
24 | #include "server.h"
25 | #include "cpanel.h"
26 |
27 | void cpanel_wifi_handler(bool connected, bool ap_mode) {
28 | if (connected) {
29 | server_start(cpanel_event_handler);
30 | } else {
31 | server_restart();
32 | }
33 | }
34 |
35 |
36 |
--------------------------------------------------------------------------------
/components/oap-wifi/test/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | #Component Makefile
3 | #
4 |
5 | COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive
6 |
--------------------------------------------------------------------------------
/components/oap-wifi/test/test_bootwifi.c:
--------------------------------------------------------------------------------
1 | /*
2 | * oap_test.c
3 | *
4 | * Created on: Sep 11, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #include "oap_test.h"
24 | #include "bootwifi.h"
25 | #include "oap_storage.h"
26 | #include "esp_wifi.h"
27 | #include "server_cpanel.h"
28 | #include "esp_request.h"
29 |
30 |
31 | TEST_CASE("test wifi STA","[wifi]") {
32 | test_require_wifi();
33 | }
34 |
35 | /*
36 | * this test is problematic because esp32 encounters issues after switching back from AP to STA.
37 | * sometimes after this transition, a few ssl requests fail and then it recovers (cache?)
38 | * run it as a second to last one, and as last - do 'reconnect wifi'
39 | */
40 | TEST_CASE("test wifi AP","[wifi]") {
41 | //TEST_IGNORE();
42 | test_require_ap();
43 | }
44 |
45 | //TEST_CASE("test cpanel in AP","[wifi]") {
46 | // test_require_ap_with(cpanel_wifi_handler);
47 | //
48 | // test_delay(1000);
49 | // request_t* r = req_new("http://www.google.com"); //this breaks mongoose socket
50 | // req_perform(r);
51 | // req_clean(r);
52 | //
53 | // test_delay(10000);
54 | //}
55 |
56 | // this test is unstable - sometimes it reconnects before we're able to detect disconnect
57 | //
58 | //TEST_CASE("reconnect wifi","[wifi]") {
59 | // test_require_wifi();
60 | // esp_wifi_stop();
61 | // TEST_ESP_OK(wifi_disconnected_wait_for(5000));
62 | // TEST_ESP_OK(wifi_connected_wait_for(10000));
63 | //}
64 |
--------------------------------------------------------------------------------
/doc/BST-BME280_DS001-10.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/BST-BME280_DS001-10.pdf
--------------------------------------------------------------------------------
/doc/BST-BMP280-DS001-11.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/BST-BMP280-DS001-11.pdf
--------------------------------------------------------------------------------
/doc/api/README.md:
--------------------------------------------------------------------------------
1 | ## Architecture
2 |
3 | OAP is built on the top of AWS Iot.
4 |
5 | Each sensor is identified by a unique name.
6 |
7 | Senors can connect with OAP via REST or MQTT.
8 | Connections are secured and authentication is performed based on certificate issued by OAP when new sensor gets registered.
9 |
10 | Once connected, sensor can update its **state** (represented as a JSON tree) in the OAP cloud by sending json **state-reported** message.
11 | It can also receive **state-desired** requests from OAP, this feature however is fully optional and can be used to remotely change current configuration of connected sensors.
12 |
13 | ## Sensor API
14 |
15 | State itself has no particular schema and no validation is performed - it can be any value you want to persist in OAP cloud.
16 | However, to create a record in OAP result tables (and therefore - publish the results), state-reported message has to meet some conditions and contain at least 'result.uid' field.
17 |
18 | {
19 | "state" : {
20 | "reported" : {
21 | /**
22 | * All parameters below ARE OPTIONAL.
23 | * Thing shadow will get updated with any values posted here (there's no validation),
24 | * however system will record a measurement only when some specifics conditions are met. See below.
25 | */
26 |
27 | /**
28 | * local time of measurement in epoch seconds.
29 | * if this value is present, it is different than previously recorded and it falls into valid range, server will accept
30 | * this as a time of measurement. Otherwise server time will be used.
31 | * This field enables you to report historical measurements (for example taken when sensor is offline) - but only
32 | * if your sensor is equipped with Real-Time Clock.
33 | */
34 | "localTime" : 0,
35 |
36 | "results" : {
37 | /**
38 | * this parameter is required for server to accept incoming data as a measurement.
39 | * if this value is missing (or null, undefined, 0 or empty string) or equal to previously sent uid,
40 | * thing shadow will get updated but result tables will not.
41 | */
42 | "uid" : 1,
43 | /**
44 | * pollution results. all parameters are optional but when present, types must match.
45 | * if particular parameter is missing, but was reported previously - the old value will be taken.
46 | */
47 | "pm" : {
48 | "pm1_0" : 0,
49 | "pm2_5" : 0,
50 | "pm10" : 0,
51 |
52 | /*
53 | * this parameter determines sensor used for measurement. used by meters with multiple PM sensors.
54 | */
55 | "sensor" : 0
56 | },
57 | /**
58 | * measured atmospheric conditions. parameters are optional but types are validated.
59 | */
60 | "weather" : {
61 | "temp" : 0.0,
62 | "pressure" : 0.0,
63 | "humidity" : 0.0,
64 | "sensor" : 0
65 | }
66 | },
67 | /**
68 | * current configuration of the sensor.
69 | */
70 | "config" : {
71 | /**
72 | * sent it when sensor changed its location from outdoor to indoor or vice-versa.
73 | */
74 | "indoor" : false,
75 | /**
76 | * any value other than 0 means that sensor is running in test mode and results should be ignored from main metrics.
77 | */
78 | "test" : 0,
79 | /**
80 | * optional location data for mobile sensors
81 | */
82 | "location" : {
83 | "lat" : 0.0,
84 | "lng" : 0.0
85 | }
86 | }
87 | }
88 | }
89 | }
90 |
91 | ## Data API
92 |
93 | Results are currently stored in three DynamoDB tables:
94 |
95 | 1. OAP_ALL (all recorded measurements)
96 | 2. OAP_HOUR (one measurement per hour)
97 | 3. OAP_LAST (last recorded measurement)
98 |
99 | All registered sensors are listed in OAP_THINGS table.
100 | Anonymous users have read-only access to these tables and can use them via DynamoDB AWS-SDK api.
101 |
102 |
--------------------------------------------------------------------------------
/doc/api/state.json:
--------------------------------------------------------------------------------
1 | {
2 | "state" : {
3 | "reported" : {
4 | /**
5 | * All parameters below ARE OPTIONAL.
6 | * Thing shadow will get updated with any values posted here (there's no validation),
7 | * however system will record a measurement only when some specifics conditions are met. See below.
8 | */
9 |
10 | /**
11 | * local time of measurement in epoch seconds.
12 | * if this value is present, it is different than previously recorded and it falls into valid range, server will accept
13 | * this as a time of measurement. Otherwise server time will be used.
14 | * This field enables you to report historical measurements (for example taken when sensor is offline) - but only
15 | * if your sensor is equipped with Real-Time Clock.
16 | */
17 | "localTime" : 0,
18 |
19 | "results" : {
20 | /**
21 | * this parameter is required for server to accept incoming data as a measurement.
22 | * if this value is missing (or null, undefined, 0 or empty string) or equal to previously sent uid,
23 | * thing shadow will get updated but result tables will not.
24 | */
25 | "uid" : 1,
26 | /**
27 | * pollution results. all parameters are optional but when present, types must match.
28 | * if particular parameter is missing, but was reported previously - the old value will be taken.
29 | */
30 | "pm" : {
31 | "pm1_0" : 0,
32 | "pm2_5" : 0,
33 | "pm10" : 0,
34 |
35 | /*
36 | * this parameter determines sensor used for measurement. used by meters with multiple PM sensors.
37 | */
38 | "sensor" : 0
39 | },
40 |
41 | /**
42 | * optional results for the second sensor, if both were used to perform measurement at the same time
43 | */
44 | "pmAux": {
45 | "pm1_0" : 0,
46 | "pm2_5" : 0,
47 | "pm10" : 0,
48 | "sensor": 1
49 | },
50 |
51 | /**
52 | * measured atmospheric conditions. parameters are optional but types are validated.
53 | */
54 | "weather" : {
55 | "temp" : 0.0,
56 | "pressure" : 0.0,
57 | "humidity" : 0.0,
58 | "sensor" : 0
59 | },
60 |
61 | /**
62 | * measured internal atmospheric conditions (optional)
63 | */
64 | "weather" : {
65 | "temp" : 0.0,
66 | "pressure" : 0.0,
67 | "humidity" : 0.0,
68 | "sensor" : 0
69 | }
70 | },
71 | /**
72 | * current configuration of the sensor.
73 | */
74 | "config" : {
75 | /**
76 | * sent it when sensor changed its location from outdoor to indoor or vice-versa.
77 | */
78 | "indoor" : false,
79 | /**
80 | * any value other than 0 means that sensor is running in test mode and results should be ignored from main metrics.
81 | */
82 | "test" : 0,
83 | /**
84 | * optional location data for mobile sensors
85 | */
86 | "location" : {
87 | "lat" : 0.0,
88 | "lng" : 0.0
89 | }
90 | }
91 | }
92 | }
93 | }
--------------------------------------------------------------------------------
/doc/images/ESP32-DevBoard.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/images/ESP32-DevBoard.jpg
--------------------------------------------------------------------------------
/doc/images/prototype.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/images/prototype.jpg
--------------------------------------------------------------------------------
/doc/images/schema.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/images/schema.jpg
--------------------------------------------------------------------------------
/doc/images/sensor_settings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/images/sensor_settings.png
--------------------------------------------------------------------------------
/doc/plantower-pms5003-manual_v2-3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openairproject/sensor-esp32/374e28ed91679678e267c937e63ae3dcc64d7818/doc/plantower-pms5003-manual_v2-3.pdf
--------------------------------------------------------------------------------
/main/Kconfig.projbuild:
--------------------------------------------------------------------------------
1 | menu "OpenAirProject"
2 |
3 | config OAP_CONTROL_PANEL
4 | int "enable control panel"
5 | default 1
6 | help
7 | Enable web-based control panel where you can configure various parameters of the sensor,
8 | including wifi and data publishing settings
9 |
10 | endmenu
--------------------------------------------------------------------------------
/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
10 | # TODO split into proper components
11 | #COMPONENT_PRIV_INCLUDEDIRS := .
12 | #COMPONENT_SRCDIRS := . bootwifi mongoose hardware net
13 |
14 | CFLAGS += -DCS_PLATFORM=CS_P_ESP32 \
15 | -DMG_DISABLE_DIRECTORY_LISTING=1 \
16 | -DMG_DISABLE_DAV=1 \
17 | -DMG_DISABLE_CGI=1 \
18 | -DMG_DISABLE_FILESYSTEM=1 \
19 | -DMG_LWIP=1 \
20 | -DMG_ENABLE_BROADCAST \
21 | -DMBEDTLS_DEBUG_C=1
22 |
--------------------------------------------------------------------------------
/main/oap_config.txt:
--------------------------------------------------------------------------------
1 | /*
2 | * config.h
3 | *
4 | * Created on: Feb 9, 2017
5 | * Author: kris
6 | *
7 | * This file is part of OpenAirProject-ESP32.
8 | *
9 | * OpenAirProject-ESP32 is free software: you can redistribute it and/or modify
10 | * it under the terms of the GNU General Public License as published by
11 | * the Free Software Foundation, either version 3 of the License, or
12 | * (at your option) any later version.
13 | *
14 | * OpenAirProject-ESP32 is distributed in the hope that it will be useful,
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 | * GNU General Public License for more details.
18 | *
19 | * You should have received a copy of the GNU General Public License
20 | * along with OpenAirProject-ESP32. If not, see .
21 | */
22 |
23 | #ifndef MAIN_CONFIG_H_
24 | #define MAIN_CONFIG_H_
25 |
26 | /*
27 | * the hardware configuration was tested on official ESP32 DevKit (with WROOM32 module).
28 | * For other boards pin assignments may require changes.
29 | */
30 |
31 |
32 | /* -------------------------------------------------------
33 | * PM SENSOR
34 | */
35 |
36 | /*
37 | * UART configuration. Do not use UART0
38 | */
39 | //#define OAP_PM_UART_NUM UART_NUM_1
40 | //
41 | //#define OAP_PM_UART_RXD_PIN (34) //this pin can be R/O (>=34) . we care only about RX
42 | //#define OAP_PM_UART_TXD_PIN (4) //any free 'safe' pin
43 | //#define OAP_PM_UART_RTS_PIN (18) //any free 'safe' pin
44 | //#define OAP_PM_UART_CTS_PIN (19) //any free 'safe' pin
45 |
46 | /*
47 | * pmsX003 sensor need to know whether it is outdoor or indoor
48 | * to compensate values
49 | */
50 | //#define OAP_PM_SENSOR_OUTDOOR 0
51 |
52 | /*
53 | * output GPIO pin to enable/disable PM sensor.
54 | * same pins that work with LEDC are ok.
55 | */
56 | //#define OAP_PM_SENSOR_CONTROL_PIN (10)
57 |
58 | /*
59 | * max number of samples to compute average from during measurement
60 | * sampling interval is ~1sec, so for measurement times > 2min you might want to increase this number
61 | * (otherwise earlier samples will be overridden)
62 | */
63 | //#define OAP_PM_SAMPLE_BUF_SIZE 120
64 |
65 |
66 |
67 |
68 | /* -------------------------------------------------------
69 | * BMx280 SENSOR
70 | */
71 |
72 | /*
73 | * be careful with choosing gpio. i2c pin must be R/W (<34)
74 | *
75 | * so far I've tested:
76 | * safe pins: 25,26,27,14,10
77 | * problems :
78 | * 12 =>Warning: Could not auto-detect Flash size (FlashID=0xffffff, SizeID=0xff), defaulting to 4MB \nFlash params set to 0x0220
79 | * 32,33 => (i2c err)
80 | * 13,11 => (i2c err)
81 | * 9 => (rebooting) Guru Meditation Error of type IllegalInstruction occurred on core 0. Exception was unhandled
82 | */
83 |
84 |
85 |
86 | /* -------------------------------------------------------
87 | * CONTROL BUTTON(S)
88 | */
89 |
90 | /*
91 | * we're good with most pins here, even those that do not work with LEDC/IC2 (32, 33)
92 | */
93 | //#define OAP_BTN_0_PIN (35)
94 | //#define OAP_BTN_1_PIN (33)
95 |
96 |
97 | /* -------------------------------------------------------
98 | * RGB LED
99 | */
100 |
101 | /*
102 | * careful with choosing gpio...
103 | * safe: 12,14,27
104 | * problems: 9,11 - reboots
105 | */
106 | //#define OAP_LED_PINS 12,27,14
107 |
108 |
109 | /* -------------------------------------------------------
110 | * THING SPEAK CLIENT
111 | */
112 | //#define OAP_THING_SPEAK_API_KEY ""
113 |
114 | //#define OAP_RESULT_BUFFER_SIZE 100
115 |
116 | #endif /* MAIN_CONFIG_H_ */
117 |
118 |
--------------------------------------------------------------------------------
/partitions.csv:
--------------------------------------------------------------------------------
1 | # Name, Type, SubType, Offset, Size
2 | # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
3 | nvs, data, nvs, 0x9000, 0x13000
4 | otadata, data, ota, 0x1c000, 0x2000
5 | phy_init, data, phy, 0x1e000, 0x1000
6 | factory, 0, 0, 0x30000, 0x140000
7 | coredump, data, coredump,, 0x10000
8 | ota_0, 0, ota_0, , 0x140000
9 | ota_1, 0, ota_1, , 0x140000
--------------------------------------------------------------------------------
/unit-test-app/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | sdkconfig
3 | sdkconfig.old
4 | .DS_Store
5 | main/*.bak
6 | core.dat
7 |
--------------------------------------------------------------------------------
/unit-test-app/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := unit-test-app
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
10 | print_flash_cmd:
11 | echo $(ESPTOOL_WRITE_FLASH_OPTIONS) $(ESPTOOL_ALL_FLASH_ARGS) | sed -e 's:'$(PWD)/build/'::g'
12 |
--------------------------------------------------------------------------------
/unit-test-app/README.md:
--------------------------------------------------------------------------------
1 | # Unit Test App
2 |
3 | ESP-IDF unit tests are run using Unit Test App. The app can be built with the unit tests for a specific component. Unit tests are in `test` subdirectories of respective components.
4 |
5 | # Building Unit Test App
6 |
7 | * Follow the setup instructions in the top-level esp-idf README.
8 | * Set IDF_PATH environment variable to point to the path to the esp-idf top-level directory.
9 | * Change into `tools/unit-test-app` directory
10 | * `make menuconfig` to configure the Unit Test App.
11 | * `make TEST_COMPONENTS=` with `TEST_COMPONENTS` set to names of the components to be included in the test app. Or `make TESTS_ALL=1` to build the test app with all the tests for components having `test` subdirectory.
12 | * Follow the printed instructions to flash, or run `make flash`.
13 |
14 | # Running Unit Tests
15 |
16 | The unit test loader will prompt by showing a menu of available tests to run:
17 |
18 | * Type a number to run a single test.
19 | * `*` to run all tests.
20 | * `[tagname]` to run tests with "tag"
21 | * `![tagname]` to run tests without "tag" (`![ignore]` is very useful as it runs all CI-enabled tests.)
22 | * `"test name here"` to run test with given name
23 |
--------------------------------------------------------------------------------
/unit-test-app/components/unity/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Component Makefile
3 | #
4 |
--------------------------------------------------------------------------------
/unit-test-app/components/unity/include/test_utils.h:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | #pragma once
15 |
16 | // Utilities for esp-idf unit tests
17 |
18 | #include
19 | #include
20 |
21 | /* Return the 'flash_test' custom data partition (type 0x55)
22 | defined in the custom partition table.
23 | */
24 | const esp_partition_t *get_test_data_partition();
25 |
26 | /**
27 | * @brief Initialize reference clock
28 | *
29 | * Reference clock provides timestamps at constant 1 MHz frequency, even when
30 | * the APB frequency is changing.
31 | */
32 | void ref_clock_init();
33 |
34 | /**
35 | * @brief Deinitialize reference clock
36 | */
37 | void ref_clock_deinit();
38 |
39 | /**
40 | * @brief Get reference clock timestamp
41 | * @return number of microseconds since the reference clock was initialized
42 | */
43 | uint64_t ref_clock_get();
44 |
--------------------------------------------------------------------------------
/unit-test-app/components/unity/include/unity_config.h:
--------------------------------------------------------------------------------
1 | #ifndef UNITY_CONFIG_H
2 | #define UNITY_CONFIG_H
3 |
4 | // This file gets included from unity.h via unity_internals.h
5 | // It is inside #ifdef __cplusplus / extern "C" block, so we can
6 | // only use C features here
7 |
8 | // Adapt Unity to our environment, disable FP support
9 |
10 | #include
11 |
12 | /* Some definitions applicable to Unity running in FreeRTOS */
13 | #define UNITY_FREERTOS_PRIORITY 5
14 | #define UNITY_FREERTOS_CPU 0
15 |
16 | #define UNITY_EXCLUDE_FLOAT
17 | #define UNITY_EXCLUDE_DOUBLE
18 |
19 | #define UNITY_OUTPUT_CHAR unity_putc
20 | #define UNITY_OUTPUT_FLUSH unity_flush
21 |
22 | // Define helpers to register test cases from multiple files
23 |
24 | #define UNITY_EXPAND2(a, b) a ## b
25 | #define UNITY_EXPAND(a, b) UNITY_EXPAND2(a, b)
26 | #define UNITY_TEST_UID(what) UNITY_EXPAND(what, __LINE__)
27 |
28 | #define UNITY_TEST_REG_HELPER reg_helper ## UNITY_TEST_UID
29 | #define UNITY_TEST_DESC_UID desc ## UNITY_TEST_UID
30 | struct test_desc_t
31 | {
32 | const char* name;
33 | const char* desc;
34 | void (*fn)(void);
35 | const char* file;
36 | int line;
37 | struct test_desc_t* next;
38 | };
39 |
40 | void unity_testcase_register(struct test_desc_t* desc);
41 |
42 | void unity_run_menu();
43 |
44 | void unity_run_tests_with_filter(const char* filter);
45 |
46 | void unity_run_all_tests();
47 |
48 | /* Test case macro, a-la CATCH framework.
49 | First argument is a free-form description,
50 | second argument is (by convention) a list of identifiers, each one in square brackets.
51 | Identifiers are used to group related tests, or tests with specific properties.
52 | Use like:
53 |
54 | TEST_CASE("Frobnicator forbnicates", "[frobnicator][rom]")
55 | {
56 | // test goes here
57 | }
58 | */
59 | #define TEST_CASE(name_, desc_) \
60 | static void UNITY_TEST_UID(test_func_) (void); \
61 | static void __attribute__((constructor)) UNITY_TEST_UID(test_reg_helper_) () \
62 | { \
63 | static struct test_desc_t UNITY_TEST_UID(test_desc_) = { \
64 | .name = name_, \
65 | .desc = desc_, \
66 | .fn = &UNITY_TEST_UID(test_func_), \
67 | .file = __FILE__, \
68 | .line = __LINE__, \
69 | .next = NULL \
70 | }; \
71 | unity_testcase_register( & UNITY_TEST_UID(test_desc_) ); \
72 | }\
73 | static void UNITY_TEST_UID(test_func_) (void)
74 | /**
75 | * Note: initialization of test_desc_t fields above has to be done exactly
76 | * in the same order as the fields are declared in the structure.
77 | * Otherwise the initializer will not be valid in C++ (which doesn't
78 | * support designated initializers). G++ can parse the syntax, but
79 | * field names are treated as annotations and don't affect initialization
80 | * order. Also make sure all the fields are initialized.
81 | */
82 |
83 | // shorthand to check esp_err_t return code
84 | #define TEST_ESP_OK(rc) TEST_ASSERT_EQUAL_HEX32(ESP_OK, rc)
85 | #define TEST_ESP_ERR(err, rc) TEST_ASSERT_EQUAL_HEX32(err, rc)
86 |
87 |
88 | #endif //UNITY_CONFIG_H
89 |
--------------------------------------------------------------------------------
/unit-test-app/components/unity/license.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2007-14 Mike Karlesky, Mark VanderVoord, Greg Williams
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/unit-test-app/components/unity/test_utils.c:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "unity.h"
16 | #include "test_utils.h"
17 |
18 | const esp_partition_t *get_test_data_partition()
19 | {
20 | /* This finds "flash_test" partition defined in partition_table_unit_test_app.csv */
21 | const esp_partition_t *result = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
22 | ESP_PARTITION_SUBTYPE_ANY, "flash_test");
23 | TEST_ASSERT_NOT_NULL(result); /* means partition table set wrong */
24 | return result;
25 | }
26 |
--------------------------------------------------------------------------------
/unit-test-app/main/app_main.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include "freertos/FreeRTOS.h"
3 | #include "freertos/task.h"
4 | #include "unity.h"
5 | #include "unity_config.h"
6 | #include "oap_test.h"
7 |
8 | void unityTask(void *pvParameters)
9 | {
10 | vTaskDelay(1000 / portTICK_PERIOD_MS);
11 | unity_run_menu();
12 | while(1);
13 | }
14 |
15 | void app_main()
16 | {
17 | test_reset_hw();
18 | // Note: if unpinning this task, change the way run times are calculated in
19 | // unity_platform
20 | xTaskCreatePinnedToCore(unityTask, "unityTask", 8192, NULL,
21 | UNITY_FREERTOS_PRIORITY, NULL, UNITY_FREERTOS_CPU);
22 | }
23 |
--------------------------------------------------------------------------------
/unit-test-app/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # "main" pseudo-component makefile.
3 | #
4 | # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
5 |
--------------------------------------------------------------------------------
/unit-test-app/partition_table_unit_test_app.csv:
--------------------------------------------------------------------------------
1 | # Let's keep it the same as for app
2 | # Name, Type, SubType, Offset, Size
3 | # Note: if you change the phy_init or app partition offset, make sure to change the offset in Kconfig.projbuild
4 | nvs, data, nvs, 0x9000, 0x13000
5 | otadata, data, ota, 0x1c000, 0x2000
6 | phy_init, data, phy, 0x1e000, 0x1000
7 | factory, 0, 0, 0x30000, 0x140000
8 | coredump, data, coredump,, 0x10000
9 | ota_0, 0, ota_0, , 0x140000
10 | ota_1, 0, ota_1, , 0x140000
--------------------------------------------------------------------------------