flipperzero-firmware/applications/subghz/views/subghz_transmitter.c
Skorpionm e17336498d
[FL-1756, FL-1769, FL-1776, FL-1759] Gui: input events complementary V3, refactoring. SubGhz: read/emulate fixes. Cleanup. (#684)
* Gui: move rotation logic to ViewPort, replace delayed View switch in ViewDispatcher with event filtering and redirection to previous view.
* SubGhz: add function description
* Gui, Input: add event id to input events.
* SubGhz: fix "crashing on ?"
* SubGhz: add icon scanning
* SubGhz: updated interface read scene,  updated interface config scene
* Assets: update subghz assets
* SubGhz:  replaced the picture in the read scene, changed the paths to additional files
* SubGhz: fix deadlock in timer callback
* SubGhz: fix icon read scene
* SubGhz: fix icon read scene
* SubGhz: fix duble text transmitter scene
* SubGhz: correct spelling. Gui: bigger queue for ViewDispatcher.
* SubGhz: fix creation and transmission of dynamic code without the presence of a manufactory key
* SubGhz: fix keelog, setting a name in the absence of a manufactory key
* SubGhz: fix load bad keelog key
* Format sources
* Furi: remove garbage from core. GpioTester: fix memory leak and cleanup
* Accessor: remove obsolete notification code
* MusicPlayer: remove input event injection
* Input: rename id to sequence

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2021-09-02 00:05:00 +03:00

219 lines
7.5 KiB
C

#include "subghz_transmitter.h"
#include "../subghz_i.h"
#include <math.h>
#include <furi.h>
#include <furi-hal.h>
#include <input/input.h>
#include <gui/elements.h>
#include <notification/notification-messages.h>
#include <lib/subghz/protocols/subghz_protocol_keeloq.h>
struct SubghzTransmitter {
View* view;
SubghzTransmitterCallback callback;
void* context;
};
typedef struct {
string_t text;
uint16_t scene;
uint32_t real_frequency;
FuriHalSubGhzPreset preset;
SubGhzProtocolCommon* protocol;
} SubghzTransmitterModel;
void subghz_transmitter_set_callback(
SubghzTransmitter* subghz_transmitter,
SubghzTransmitterCallback callback,
void* context) {
furi_assert(subghz_transmitter);
subghz_transmitter->callback = callback;
subghz_transmitter->context = context;
}
void subghz_transmitter_set_protocol(
SubghzTransmitter* subghz_transmitter,
SubGhzProtocolCommon* protocol) {
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
model->protocol = protocol;
return true;
});
}
void subghz_transmitter_set_frequency_preset(
SubghzTransmitter* subghz_transmitter,
uint32_t frequency,
FuriHalSubGhzPreset preset) {
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
model->real_frequency = frequency;
model->preset = preset;
return true;
});
}
static void subghz_transmitter_button_right(Canvas* canvas, const char* str) {
const uint8_t button_height = 13;
const uint8_t vertical_offset = 3;
const uint8_t horizontal_offset = 1;
const uint8_t string_width = canvas_string_width(canvas, str);
const Icon* icon = &I_ButtonCenter_7x7;
const uint8_t icon_offset = 3;
const uint8_t icon_width_with_offset = icon_get_width(icon) + icon_offset;
const uint8_t button_width = string_width + horizontal_offset * 2 + icon_width_with_offset;
const uint8_t x = (canvas_width(canvas) - button_width) / 2 + 40;
const uint8_t y = canvas_height(canvas);
canvas_draw_box(canvas, x, y - button_height, button_width, button_height);
canvas_draw_line(canvas, x - 1, y, x - 1, y - button_height + 0);
canvas_draw_line(canvas, x - 2, y, x - 2, y - button_height + 1);
canvas_draw_line(canvas, x - 3, y, x - 3, y - button_height + 2);
canvas_draw_line(canvas, x + button_width + 0, y, x + button_width + 0, y - button_height + 0);
canvas_draw_line(canvas, x + button_width + 1, y, x + button_width + 1, y - button_height + 1);
canvas_draw_line(canvas, x + button_width + 2, y, x + button_width + 2, y - button_height + 2);
canvas_invert_color(canvas);
canvas_draw_icon(
canvas, x + horizontal_offset, y - button_height + vertical_offset, &I_ButtonCenter_7x7);
canvas_draw_str(
canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str);
canvas_invert_color(canvas);
}
void subghz_transmitter_draw(Canvas* canvas, SubghzTransmitterModel* model) {
char buffer[64];
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
canvas_set_font(canvas, FontSecondary);
elements_multiline_text(canvas, 0, 8, string_get_cstr(model->text));
snprintf(
buffer,
sizeof(buffer),
"%03ld.%03ld",
model->real_frequency / 1000000 % 1000,
model->real_frequency / 1000 % 1000);
canvas_draw_str(canvas, 90, 8, buffer);
if(model->protocol && model->protocol->get_upload_protocol) {
if((!strcmp(model->protocol->name, "KeeLoq")) &&
(!strcmp(subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
return;
}
subghz_transmitter_button_right(canvas, "Send");
}
}
bool subghz_transmitter_input(InputEvent* event, void* context) {
furi_assert(context);
SubghzTransmitter* subghz_transmitter = context;
bool can_be_sent = false;
if(event->key == InputKeyBack) {
return false;
}
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
if(model->protocol && model->protocol->get_upload_protocol) {
if((!strcmp(model->protocol->name, "KeeLoq")) &&
(!strcmp(
subghz_protocol_keeloq_get_manufacture_name(model->protocol), "Unknown"))) {
return false;
}
can_be_sent = true;
}
//can_be_sent = (model->protocol && model->protocol->get_upload_protocol);
string_clean(model->text);
model->protocol->to_string(model->protocol, model->text);
return true;
});
//if(event->type != InputTypeShort) return false;
if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) {
subghz_transmitter->callback(SubghzTransmitterEventSendStart, subghz_transmitter->context);
return true;
} else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) {
subghz_transmitter->callback(SubghzTransmitterEventSendStop, subghz_transmitter->context);
return true;
}
return true;
}
void subghz_transmitter_text_callback(string_t text, void* context) {
furi_assert(context);
SubghzTransmitter* subghz_transmitter = context;
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_set(model->text, text);
model->scene = 0;
return true;
});
}
void subghz_transmitter_enter(void* context) {
furi_assert(context);
SubghzTransmitter* subghz_transmitter = context;
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_clean(model->text);
model->protocol->to_string(model->protocol, model->text);
return true;
});
}
void subghz_transmitter_exit(void* context) {
furi_assert(context);
SubghzTransmitter* subghz_transmitter = context;
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_clean(model->text);
return true;
});
}
SubghzTransmitter* subghz_transmitter_alloc() {
SubghzTransmitter* subghz_transmitter = furi_alloc(sizeof(SubghzTransmitter));
// View allocation and configuration
subghz_transmitter->view = view_alloc();
view_allocate_model(
subghz_transmitter->view, ViewModelTypeLocking, sizeof(SubghzTransmitterModel));
view_set_context(subghz_transmitter->view, subghz_transmitter);
view_set_draw_callback(subghz_transmitter->view, (ViewDrawCallback)subghz_transmitter_draw);
view_set_input_callback(subghz_transmitter->view, subghz_transmitter_input);
view_set_enter_callback(subghz_transmitter->view, subghz_transmitter_enter);
view_set_exit_callback(subghz_transmitter->view, subghz_transmitter_exit);
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_init(model->text);
return true;
});
return subghz_transmitter;
}
void subghz_transmitter_free(SubghzTransmitter* subghz_transmitter) {
furi_assert(subghz_transmitter);
with_view_model(
subghz_transmitter->view, (SubghzTransmitterModel * model) {
string_clear(model->text);
return true;
});
view_free(subghz_transmitter->view);
free(subghz_transmitter);
}
View* subghz_transmitter_get_view(SubghzTransmitter* subghz_transmitter) {
furi_assert(subghz_transmitter);
return subghz_transmitter->view;
}