Skip to content

Commit cfa5611

Browse files
committed
option to reset to factory firmware, fix #40
1 parent 66e90c8 commit cfa5611

File tree

7 files changed

+114
-101
lines changed

7 files changed

+114
-101
lines changed

bin/deploy_ota.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ DEST_FOLDER=s3://openairproject.com/ota
99

1010
printf "$1|$1/sensor-esp32.bin|" > $INDEX_FILE
1111

12-
cat build/sensor-esp32.bin | openssl dgst -sha256 >> $INDEX_FILE
12+
cat build/sensor-esp32.bin | openssl dgst -sha256 -binary | xxd -p -c 100 >> $INDEX_FILE
13+
cat $INDEX_FILE
1314

1415
aws s3 cp build/sensor-esp32.bin $DEST_FOLDER/$1/sensor-esp32.bin --profile oap
1516
aws s3 cp $INDEX_FILE $DEST_FOLDER/index.txt --profile oap

components/oap-hw-ext/ctrl_btn.c

Lines changed: 62 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -30,93 +30,80 @@
3030
#include "oap_common.h"
3131
#include "ctrl_btn.h"
3232
#include "esp_log.h"
33+
#include "esp_err.h"
34+
#include "driver/gpio.h"
35+
#include "freertos/queue.h"
3336

3437
#define ESP_INTR_FLAG_DEFAULT 0
38+
#define TAG "btn"
3539

36-
static QueueHandle_t gpio_evt_queue = NULL;
37-
static QueueHandle_t btn_events = NULL;
40+
typedef struct {
41+
uint8_t gpio_num;
42+
uint32_t timestamp;
43+
} gpio_event_t;
3844

45+
static QueueHandle_t gpio_evt_queue;
46+
static uint32_t last_click = 0;
47+
static btn_callback_f _callback = NULL;
3948

4049
static void IRAM_ATTR gpio_isr_handler(void* arg)
4150
{
42-
uint32_t gpio_num = (uint32_t) arg;
43-
xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
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);
4462
}
4563

46-
static long int now() {
47-
struct timeval tv;
48-
gettimeofday(&tv, NULL);
49-
return tv.tv_sec * 1000 + tv.tv_usec / 1000;
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+
}
5091
}
5192

52-
static uint8_t gpio_to_index[40] = {-1};
53-
54-
static void btn_task()
55-
{
56-
uint32_t io_num;
57-
uint8_t level[40] = {0};
58-
long int time = now();
59-
long int _time;
60-
61-
62-
for(;;) {
63-
if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
64-
65-
//debounce
66-
_time = now();
67-
if (_time - time > 50 || io_num >= 40) {
68-
btn_event event = {
69-
.index = gpio_to_index[io_num],
70-
.gpio = io_num,
71-
.level= gpio_get_level(io_num)
72-
};
73-
74-
if (level[event.gpio] == event.level) continue;
75-
76-
time = _time;
77-
level[event.gpio] = event.level;
78-
xQueueSend(btn_events, &event, 500);
79-
}
80-
}
81-
}
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
82104
}
83105

84-
85-
QueueHandle_t btn_init(gpio_num_t *btn_gpio, uint8_t num_of_btns)
86-
{
87-
btn_events = xQueueCreate(1, sizeof(btn_event));
88-
gpio_config_t io_conf;
89-
90-
//interrupt of ...
91-
io_conf.intr_type = GPIO_INTR_ANYEDGE;
92-
//bit mask of the pins,
93-
io_conf.pin_bit_mask = 0;
94-
//set as input mode
95-
io_conf.mode = GPIO_MODE_INPUT;
96-
//set pull-up mode
97-
io_conf.pull_up_en = 0;
98-
io_conf.pull_down_en = 1;
99-
100-
for (int n = 0; n < num_of_btns; n++) {
101-
io_conf.pin_bit_mask |= (uint64_t)(((uint64_t)1)<<((uint64_t)(btn_gpio[n])));
102-
}
103-
104-
gpio_config(&io_conf);
105-
106-
//create a queue to handle gpio event from isr
107-
gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
108-
//start gpio task
109-
xTaskCreate(btn_task, "btn_task", 2048, NULL, DEFAULT_TASK_PRIORITY, NULL);
110-
111-
//install gpio isr service
112-
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
113-
//hook isr handler for specific gpio pin
114-
for (int n = 0; n < num_of_btns; n++) {
115-
gpio_to_index[btn_gpio[n]] = n;
116-
gpio_isr_handler_add(btn_gpio[n], gpio_isr_handler, (void*) btn_gpio[n]);
117-
}
118-
119-
return btn_events;
106+
bool is_ap_mode_pressed() {
107+
return gpio_get_level(CONFIG_OAP_BTN_0_PIN);
120108
}
121109

122-

components/oap-hw-ext/include/ctrl_btn.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,14 @@
2323
#ifndef MAIN_BTN_H_
2424
#define MAIN_BTN_H_
2525

26-
#include "freertos/queue.h"
27-
#include "driver/gpio.h"
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);
2832

29-
typedef struct {
30-
uint8_t index;
31-
gpio_num_t gpio;
32-
uint8_t level;
33-
} btn_event;
34-
35-
xQueueHandle btn_init(gpio_num_t* btns_gpio, uint8_t num_of_btns);
33+
bool is_ap_mode_pressed();
34+
esp_err_t btn_configure(btn_callback_f callback);
3635

3736
#endif /* MAIN_BTN_H_ */

components/oap-hw-ext/rgb_led.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static const char* TAG = "rgbled";
3939
static xQueueHandle cmd_queue;
4040
static gpio_num_t led_gpio[] = {CONFIG_OAP_LED_R_PIN,CONFIG_OAP_LED_G_PIN,CONFIG_OAP_LED_B_PIN};
4141

42-
#define DEFAULT_FREQ 1500
42+
#define DEFAULT_FREQ 1000
4343

4444
static ledc_mode_t speed_mode = LEDC_HIGH_SPEED_MODE;
4545

components/oap-ota/include/ota.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131
#define OAP_OTA_INDEX_URI CONFIG_OAP_OTA_INDEX_URI
3232

3333
void start_ota_task(cJSON* user_ota_config);
34+
void reset_to_factory_partition();
3435

3536
#endif /* COMPONENTS_OTA_INCLUDE_OTA_H_ */

components/oap-ota/ota.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ static int is_white_char(int ch) {
7171
return ch == '\n' || ch == '\r' || ch == '\t';
7272
}
7373

74+
void reset_to_factory_partition() {
75+
ESP_LOGW(TAG, "RESET TO FACTORY");
76+
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
77+
if (factory) {
78+
esp_ota_set_boot_partition(factory);
79+
oap_reboot();
80+
} else {
81+
ESP_LOGE(TAG, "no factory partition?");
82+
}
83+
}
84+
7485
esp_err_t parse_ota_info(ota_info_t* ota_info, char* line, int len) {
7586
if (len <= 0) return OAP_OTA_ERR_EMPTY_RESPONSE;
7687
char* ver = NULL; char* file = NULL; char* sha = NULL;

main/main.c

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@
5050
#include "oap_data.h"
5151
#include "server_cpanel.h"
5252

53+
#define ESP_INTR_FLAG_DEFAULT 0
54+
5355
static const char *TAG = "app";
5456

5557

@@ -69,26 +71,24 @@ static led_cmd_t ledc_state = {
6971
.color = {.v = {0,0,1}} //initial color (when no samples collected)
7072
};
7173

72-
static void ledc_set() {
74+
static void ledc_update() {
7375
xQueueSend(ledc_queue, &ledc_state, 100);
7476
}
7577

7678
static void ledc_set_mode(led_mode_t mode) {
7779
ledc_state.mode = mode;
78-
ledc_set();
7980
}
8081

81-
static void ledc_set_color(led_mode_t mode, float r, float g, float b) {
82+
static void ledc_set_color(float r, float g, float b) {
8283
ledc_state.color.v[0] = r;
8384
ledc_state.color.v[1] = g;
8485
ledc_state.color.v[2] = b;
85-
ledc_set_mode(mode);
8686
}
8787

8888
static void ledc_init() {
8989
ledc_queue = xQueueCreate(10, sizeof(led_cmd_t));
9090
led_init(oap_sensor_config.led, ledc_queue);
91-
ledc_set();
91+
ledc_update();
9292
}
9393

9494

@@ -121,6 +121,7 @@ static void pm_meter_output_handler(pm_meter_event_t event, void* data) {
121121
case PM_METER_START:
122122
ESP_LOGI(TAG, "start measurement");
123123
ledc_set_mode(LED_PULSE);
124+
ledc_update();
124125
break;
125126
case PM_METER_RESULT:
126127
ESP_LOGI(TAG, "finished measurement");
@@ -302,7 +303,9 @@ static void publish_loop() {
302303
log_task_stack(TAG);
303304
float aqi = fminf(pm_data_pair.pm_data[0].pm2_5 / 100.0, 1.0);
304305
//ESP_LOGI(TAG, "AQI=%f",aqi);
305-
ledc_set_color(LED_SET, aqi,(1-aqi), 0);
306+
ledc_set_color(aqi,(1-aqi), 0);
307+
ledc_set_mode(LED_SET);
308+
ledc_update();
306309

307310
oap_measurement_t meas = {
308311
.pm = &pm_data_pair.pm_data[0],
@@ -343,29 +346,40 @@ void publishers_init() {
343346
}
344347
}
345348

346-
static void configure_ap_mode_btn() {
347-
gpio_pad_select_gpio(CONFIG_OAP_BTN_0_PIN);
348-
gpio_set_direction(CONFIG_OAP_BTN_0_PIN, GPIO_MODE_INPUT);
349-
gpio_set_pull_mode(CONFIG_OAP_BTN_0_PIN, GPIO_PULLDOWN_ONLY);
350-
}
351349

352-
static int is_ap_mode_pressed() {
353-
return gpio_get_level(CONFIG_OAP_BTN_0_PIN);
350+
static void btn_handler(btn_action_t action) {
351+
switch (action) {
352+
case MANY_CLICKS :
353+
ESP_LOGW(TAG, "about to perform factory reset!");
354+
ledc_set_mode(LED_BLINK);
355+
ledc_update();
356+
break;
357+
case TOO_MANY_CLICKS :
358+
reset_to_factory_partition();
359+
break;
360+
default:
361+
break;
362+
}
354363
}
355364

356365
void app_main() {
366+
//silence annoying logs
367+
esp_log_level_set("ledc", ESP_LOG_INFO);
368+
esp_log_level_set("nvs", ESP_LOG_INFO);
369+
esp_log_level_set("tcpip_adapter", ESP_LOG_INFO);
370+
371+
//a sec to start flashing
357372
delay(1000);
358373
ESP_LOGI(TAG,"starting app... firmware %s", oap_version_str());
359374

360375
//130kb is a nice cap to test against alloc fails
361376
//reduce_heap_size_to(130000);
362377
storage_init();
363378

364-
ESP_LOGD(TAG, "retrieve sensor config");
365379
oap_sensor_config = sensor_config_from_json(cJSON_GetObjectItem(storage_get_config("sensor"), "config"));
366380

367381
//wifi/mongoose requires plenty of mem, start it here
368-
configure_ap_mode_btn();
382+
btn_configure(&btn_handler);
369383
wifi_configure(is_ap_mode_pressed() ? NULL : storage_get_config("wifi"), CONFIG_OAP_CONTROL_PANEL ? cpanel_wifi_handler : NULL);
370384
wifi_boot();
371385
start_ota_task(storage_get_config("ota"));

0 commit comments

Comments
 (0)