From fe212228e2a7b4649de73be940156ad3d4945111 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 12 May 2023 16:47:39 +0300 Subject: [PATCH 01/23] New SubGhz Remote GUI --- .../subghz_remote_new/application.fam | 15 + .../helpers/subrem_custom_event.h | 67 ++++ .../subghz_remote_new/helpers/subrem_types.h | 39 +++ .../icons/ButtonDown_7x4.png | Bin 0 -> 102 bytes .../icons/ButtonLeft_4x7.png | Bin 0 -> 1415 bytes .../icons/ButtonRight_4x7.png | Bin 0 -> 1839 bytes .../subghz_remote_new/icons/ButtonUp_7x4.png | Bin 0 -> 102 bytes .../subghz_remote_new/icons/Ok_btn_9x9.png | Bin 0 -> 3605 bytes .../icons/Pin_arrow_up_7x9.png | Bin 0 -> 3603 bytes .../icons/Pin_cell_13x13.png | Bin 0 -> 3593 bytes .../subghz_remote_new/icons/Pin_star_7x7.png | Bin 0 -> 3600 bytes .../subghz_remote_new/icons/back_10px.png | Bin 0 -> 154 bytes .../subghz_remote_new/icons/sub1_10px.png | Bin 0 -> 299 bytes .../subghz_remote_new/scenes/subrem_scene.c | 30 ++ .../subghz_remote_new/scenes/subrem_scene.h | 29 ++ .../scenes/subrem_scene_config.h | 3 + .../scenes/subrem_scene_openmapfile.c | 26 ++ .../scenes/subrem_scene_remote.c | 135 ++++++++ .../scenes/subrem_scene_start.c | 93 +++++ .../subghz_remote_new/subghz_remote_app.c | 181 ++++++++++ .../subghz_remote_new/subghz_remote_app_i.c | 28 ++ .../subghz_remote_new/subghz_remote_app_i.h | 53 +++ .../subghz_remote_new/views/transmitter.c | 277 +++++++++++++++ .../subghz_remote_new/views/transmitter.h | 27 ++ .../views/transmitter_old.txt | 317 ++++++++++++++++++ 25 files changed, 1320 insertions(+) create mode 100644 applications/external/subghz_remote_new/application.fam create mode 100644 applications/external/subghz_remote_new/helpers/subrem_custom_event.h create mode 100644 applications/external/subghz_remote_new/helpers/subrem_types.h create mode 100644 applications/external/subghz_remote_new/icons/ButtonDown_7x4.png create mode 100644 applications/external/subghz_remote_new/icons/ButtonLeft_4x7.png create mode 100644 applications/external/subghz_remote_new/icons/ButtonRight_4x7.png create mode 100644 applications/external/subghz_remote_new/icons/ButtonUp_7x4.png create mode 100644 applications/external/subghz_remote_new/icons/Ok_btn_9x9.png create mode 100644 applications/external/subghz_remote_new/icons/Pin_arrow_up_7x9.png create mode 100644 applications/external/subghz_remote_new/icons/Pin_cell_13x13.png create mode 100644 applications/external/subghz_remote_new/icons/Pin_star_7x7.png create mode 100644 applications/external/subghz_remote_new/icons/back_10px.png create mode 100644 applications/external/subghz_remote_new/icons/sub1_10px.png create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene.h create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_config.h create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_remote.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_start.c create mode 100644 applications/external/subghz_remote_new/subghz_remote_app.c create mode 100644 applications/external/subghz_remote_new/subghz_remote_app_i.c create mode 100644 applications/external/subghz_remote_new/subghz_remote_app_i.h create mode 100644 applications/external/subghz_remote_new/views/transmitter.c create mode 100644 applications/external/subghz_remote_new/views/transmitter.h create mode 100644 applications/external/subghz_remote_new/views/transmitter_old.txt diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam new file mode 100644 index 0000000000..4f633b9610 --- /dev/null +++ b/applications/external/subghz_remote_new/application.fam @@ -0,0 +1,15 @@ +App( + appid="subghz_remote_new", + name="SubRem new", + apptype=FlipperAppType.EXTERNAL, + entry_point="subghz_remote_app", + requires=[ + "gui", + "dialogs", + ], + icon="A_SubGHzRemote_14", + stack_size=4 * 1024, + order=12, + fap_category="Debug", + fap_icon_assets="icons", +) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h new file mode 100644 index 0000000000..d1559a7960 --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -0,0 +1,67 @@ +#pragma once + +typedef enum { + // SubRemCustomEventManagerNoSet = 0, + // SubRemCustomEventManagerSet, + // SubRemCustomEventManagerSetRAW, + + //SubmenuIndex + SubmenuIndexOpenMapFile, + SubmenuIndexOpenView, // TODO: temp debug + + //SubRemCustomEvent + SubRemCustomEventViewRemoteBack = 100, + // SubRemCustomEventSceneDeleteSuccess = 100, + // SubRemCustomEventSceneDelete, + // SubRemCustomEventSceneDeleteRAW, + // SubRemCustomEventSceneDeleteRAWBack, + + // SubRemCustomEventSceneReceiverInfoTxStart, + // SubRemCustomEventSceneReceiverInfoTxStop, + // SubRemCustomEventSceneReceiverInfoSave, + // SubRemCustomEventSceneSaveName, + // SubRemCustomEventSceneSaveSuccess, + // SubRemCustomEventSceneShowErrorBack, + // SubRemCustomEventSceneShowErrorOk, + // SubRemCustomEventSceneShowErrorSub, + // SubRemCustomEventSceneShowOnlyRX, + // SubRemCustomEventSceneAnalyzerLock, + // SubRemCustomEventSceneAnalyzerUnlock, + // SubRemCustomEventSceneSettingLock, + + // SubRemCustomEventSceneExit, + // SubRemCustomEventSceneStay, + + // SubRemCustomEventSceneRpcLoad, + // SubRemCustomEventSceneRpcButtonPress, + // SubRemCustomEventSceneRpcButtonRelease, + // SubRemCustomEventSceneRpcSessionClose, + + // SubRemCustomEventViewReceiverOK, + // SubRemCustomEventViewReceiverConfig, + // SubRemCustomEventViewReceiverBack, + // SubRemCustomEventViewReceiverOffDisplay, + // SubRemCustomEventViewReceiverUnlock, + // SubRemCustomEventViewReceiverDeleteItem, + + // SubRemCustomEventViewReadRAWBack, + // SubRemCustomEventViewReadRAWIDLE, + // SubRemCustomEventViewReadRAWREC, + // SubRemCustomEventViewReadRAWConfig, + // SubRemCustomEventViewReadRAWErase, + // SubRemCustomEventViewReadRAWSendStart, + // SubRemCustomEventViewReadRAWSendStop, + // SubRemCustomEventViewReadRAWSave, + // SubRemCustomEventViewReadRAWTXRXStop, + // SubRemCustomEventViewReadRAWMore, + + // SubRemCustomEventViewTransmitterBack, + // SubRemCustomEventViewTransmitterSendStart, + // SubRemCustomEventViewTransmitterSendStop, + // SubRemCustomEventViewTransmitterError, + + // SubRemCustomEventViewFreqAnalOkShort, + // SubRemCustomEventViewFreqAnalOkLong, + + // SubRemCustomEventByteInputDone, +} SubRemCustomEvent; diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h new file mode 100644 index 0000000000..ffb2f8044e --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +/* +#define AVR_ISP_VERSION_APP "0.1" +#define AVR_ISP_DEVELOPED "SkorP" +#define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" + +#define AVR_ISP_APP_FILE_VERSION 1 +#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR" +#define AVR_ISP_APP_EXTENSION ".avr" +*/ + +// TODO: rename Filepath +//#define SUBREMOTEMAP_FOLDER "/ext/subghz_remote" +#define SUBGHZ_REMOTE_APP_EXTENSION ".txt" +#define SUBGHZ_REMOTE_APP_PATH_PREFIX "/ext/subghz_remote" + +typedef enum { + //SubRemViewVariableItemList, + SubRemViewSubmenu, + //SubRemViewProgrammer, + //SubRemViewReader, + //SubRemViewWriter, + SubRemViewWidget, + SubRemViewPopup, + SubRemViewTextInput, + SubRemViewIDRemote, + //SubRemViewChipDetect, +} SubRemViewID; +/* +typedef enum { + SubRemErrorNoError, + SubRemErrorReading, + SubRemErrorWriting, + SubRemErrorVerification, + SubRemErrorWritingFuse, +} SubRemError;*/ \ No newline at end of file diff --git a/applications/external/subghz_remote_new/icons/ButtonDown_7x4.png b/applications/external/subghz_remote_new/icons/ButtonDown_7x4.png new file mode 100644 index 0000000000000000000000000000000000000000..2954bb6a67d1c23c0bb5d765e8d2aa04b9b5adec GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)I!3HFqj;YoHDIHH2#}J9|(o>FH3<^BV2haYO z-y5_sM4;GPjq%Ck6>60csmUj6EiNa>ORduPH4*)h!w|e3sE@(Z)z4*}Q$iC10Gods AV*mgE literal 0 HcmV?d00001 diff --git a/applications/external/subghz_remote_new/icons/ButtonLeft_4x7.png b/applications/external/subghz_remote_new/icons/ButtonLeft_4x7.png new file mode 100644 index 0000000000000000000000000000000000000000..0b4655d43247083aa705620e9836ac415b42ca46 GIT binary patch literal 1415 zcmbVM+iKK67*5rq)>aU2M7$VM1Vxif;vTv~W2u`S7ED{V3s&&L*<`XiG|9wd+THd> z5CnY!sdyuJtrvQyAo>KpiLcV|{Tkc)riAbluXfwSZCApL`ztB&p zx6LGKvks4K_4~)qD&oGa-YdJlW)hAKMNJd7<=t?6c^RI1>c$ifyjaM>^|&8!ey zB4!nh9u>5uen6Ve@<H5rru6h<2Ef#GQdQ*CmZOlQi~N!?9H`Rp;C% zU}CB21#?;r`&0|6C0}b-=jODa5|nEJ#ntxQ&{~jpgtwDta4hftr~G=#p@V36e4Zjh zq%J~{y26Jjn=1Nw-l*3%QW5YFE*v4z3gt0$&(*xf2en34c?JpH8+FYldo+Alvg8af-pG4(=!fyUi-Wsg z`g#n9VUcf(DFr{poMSNzw-lz>w+HV+n1ELr&SLA#LHUb0p(xWQ(1*vJ-i+1!`swxZ Z!O7;c$;lT_->m1Ovaz)0yuI`A$q$F8u*d)a literal 0 HcmV?d00001 diff --git a/applications/external/subghz_remote_new/icons/ButtonRight_4x7.png b/applications/external/subghz_remote_new/icons/ButtonRight_4x7.png new file mode 100644 index 0000000000000000000000000000000000000000..8e1c74c1c0038ea55172f19ac875003fc80c2d06 GIT binary patch literal 1839 zcmcIlO>f*p7#Yw)M6zw!O+@VZ{?d|D~WYi~8rHRY?X-&T}Yen`g$^+EJ;z+|RV zE@PoDvZ9%#+_}3bC_5Cj8jDGq541mi{7F+&KF}W65sr$Xn5H|YrMQ2(J7%Yc%;(zO z57ax000=TsQ+1Ke@+w#iw3au3cGGQWY740k2ijH>P(6tD)S)be>gX6Tj7`<`b>di- zgWp$8Y+?i31~CzF0&E4uRlA=C(Mp~K`{74jEchB|)4DDK!ZVhSwdFyw0YIZ1cDh0S{OvfO-U_~ zvmRF*m9sWDXNH)GOyqS1Skhxbr6}s*7t&@~kFM(NW5}qh?Lu@lJ}HE;FDiLdGO>LO z5pS*%E2grR)l^;|?O5b_?u0me&c1U}%jrk8*%=Wk%i)8yp2P|kuxmKg<=(u_`oQRI_0 zS`-DNysBx=#3&qSkgA@hJP>~D+ZM(s5jI6Owp`?yE=3e`YGUqkVOp#Cp=3wR3O4hX zX6BLsN3UBzV(vI5;|SZHgOb=HD0VFjpTyfFW}GnQuh>2*Q`k>*cAmA#iUT7EXSpo# zkPm5~#I-o^cpgfe#P$=4-Pi*SpT!-@nJgp8L347xe>5EKl`=_ZFc8XGy+_j=_R_7! z@vZZMowS1GJ?Zw)eetks%~G{BTR>T}9|jt0j3Btyb*C3-`C?fwY3EY`q*oYZ39DpM z&uJ;PCZPLs4QO1Jd_|A1PF)azZJ)RZ`^-VMWr6e#XUOA%3eLG_Ch@BDOHzMk*MF0G zCo7xMd?Mg*HMIXw%nNz?%60fZiZPlqb?GqUpXO`F&Yi!okZl(n>P@r1P2i)yk3DgRwbHeNn6e|;J^SK4TM LH~i+q&mR8;k>NTA literal 0 HcmV?d00001 diff --git a/applications/external/subghz_remote_new/icons/ButtonUp_7x4.png b/applications/external/subghz_remote_new/icons/ButtonUp_7x4.png new file mode 100644 index 0000000000000000000000000000000000000000..1be79328b40a93297a5609756328406565c437c0 GIT binary patch literal 102 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)I!3HFqj;YoHDIHH2#}J8d-yTOk1_O>mFaFD) zeWb+ZHz{mGZZ1QpXe09^4tcYT#4oe=UbmGC^A-KE*|F&zP#=S*tDnm{r-UX30HgpM AM*si- literal 0 HcmV?d00001 diff --git a/applications/external/subghz_remote_new/icons/Ok_btn_9x9.png b/applications/external/subghz_remote_new/icons/Ok_btn_9x9.png new file mode 100644 index 0000000000000000000000000000000000000000..9a1539da2049f12f7b25f96b11a9c40cd8227302 GIT binary patch literal 3605 zcmaJ@c{r5q+kR|?vSeS9G2*Q(Gqz$f_GQ#q8r!JE7=ytqjlqnNNGaK}Wlbolp-q`& zs|bxHiiEP0&{#s&zVZIv-rx7f*Y_O9^W67+-RF5;*L_{ra~$^-2RmyaK{-JH0EBE1 z7AVdru>JD$aK0bym%#uaXpT2Gcd#)x2azcxAABGV0BC)Aj-lw(6)B^^6`Y8RS?}DV z%)ko(See1!Eb3M$dL6)A6csaRjExg?k&xVzi*Rm;?iNJk#f=mkVEUR~jXN3dd|Lmz z;y}sMh%ol-?E1&`>dD;6jdps6NYoxN)s%@sf4~40YY6LAOtMEbwA4g#OCpANL823^ zSH66W05Hcxr$tg98gFntAOYL}xm$C;Skv&Ym?{TVR{)d(41vWacX1`7fM!jnW(lBK z26*WB#9I(Z1Ast!xEUC@Cj`v=urcBTdP`FWq=DYTy`}s>0vC{VzHdNRvxNFy}ir1|g=xDsrFP&l1P<-Sv zXLqYVYz{b^ZIV@1Ulg->7DEgvM*Min&Y8{8QW! z$_pA434?^wCTq$4%^>Zo8&|8XwbCv;KEd;WJJ{s;T}8R8Zwi7ssk$QWQ5l5+opKfX z;8D*COFEB#4W^*FIrRU%PDSc?B(}+9ZV?N9(yH>0uSnM?xg!>+>;e z{{7tXQQ|ZFXD*7q3XD!pwnih-=66+Qlqtl9;N-D|PHoI&B5d8>^V#i{mE>V0gQgu3+(DG%B z|8W!pl$lbQERt-0eZA%NSfvE4F>VAYP`DpeoF;Zm4`)2id;6xgSysWl6K$pWANcRZ z!ETRXKIU9G=@9lEB?<{ivj7!8FE9WN;qoo2Lr0#c@DmcF=JzU<73PmM3 zbe!-gs`c26Uc(AKz7%U!a0yZ5gsprdo1i51MjJPeHtV6d@Jy=*+_3dJ^>}p#8N#kPK_4t?hltq>u=?m+t z?em(Y%u3Bp_pyV?c_w-4c}p+?Y$aHr>TuPGs@SUj;Er!b@3GVLDS@T8OTts1JFS-p zKZ=&5zp;DRor*`Gy8MTeWdpVJv2(4-*slRM@XXG+i^F&Ku>7i08vKenZHoS4s(!!h zJE}*MHu7PR_IfdNzu*P}3^87K?f&A1;>NMsgKcR6**;aB74NC7tR(NB?{dHT-9QhXa*KoG!kGU1}$l2D>ypo)fSBuG$ zkTW4?+|I1m?6ZH8tD4^fB{cUpoEoZOo%4hl!EtNtQ#?j*jJR)x-Mn0TrxrX2uT_rh ziOh=Jxsktqbd9x{^s{c5z92Pk$LGoQl53o+=7QXXCp-Z>io998w|DCCCGfr20oiRN zX|`KH$W4)wN~)J$kYB~>4EU;NcS^qH&yzeUzXokpMegg_lX$6ve^4}%bY~Sg)%uJ- zZpb$p4x^GS5d{XJP=STbfpHV`58UBH& zKFg&BgS6bV+#-|^KBGeIBee2B zrM-`uTB^_(eS+{-KK1h3l`-Yjpv8X4z*uBwQ3a~pL0Ae2xvNGyC3A|#MARToe$W~8 z+4{DsyenENye9df1M}gNUM9_Leh6G=`9exL-cdSKQ_CGyEdZ3W5uoR!Lb^D)9!bd=7h@R=M%=|JqX9XP;Z6# zFD15Bw7qTP(ZlG?o@#x@=wG;XxM(>n@4P$9WwY#lW$h=`zMi_zq30HbV-zHheqpE0 zR6kXtxdzl&Ml2D#zDIvflJkb*e zIAI?GMjp?JBK76WW`{l{pFAY|%5?nYUxRnT&y6~Kz19AD;C0(z*7?dM{%HhVtqWEc z%+M$z6u@uQu)kg_%2PO_U|n1JE0V1>iVbekOLEOG$U6X^Umc519WC)L$t%`#Di0$ zY1|5H*440_`onhmXeayq`8EIg?x2r9KWe()q}QayqCMEC?c4meb4}#i`HHPaxO&3SPtSVKj@ND?Y+-@R`CDnf-d`T>vTn8RR<=@3 zNXk=Gloyh#S@3R89WHrXBHr;f(&ZO@I_Uo7;O5Bs@ecGx@7%7{_>Q`Adg&sCeZTYp ztVy{^vAUfOpTDzF*4`h%X0odWn`#uZ4s4igIV^UrVVg?c*{>K)hHq^^RxU2CM;WN> z;oK@^sg`J}BguyvilN{DQ*V+N4rD{X_~KAFj5qyk3(gP#cvSIDXe!zk3B!^InwV{j zCXGPmumQl(m`28618`K37tR+?goD{H>cAkpHyrG$XA89@o8$cOh%gGyG0e^h8y0{y z@CF+jfedLdjsO8i#eispKw=P#1_%GG3**eU%@8o?ZwNI24*pM2Xj=!6If;S;9nsX% zz(S!=&=CVoZ;TfP>*b{m(uQhlL7=)2EnN*L6sBVU)71t2^ME<-DBeCWl!etl&NwSL z*pEsj!yu5*&``}#9ZeF&7oufgU;u$?L$tLuI0%g(I+2Q@X%K^ye=Atvg0K`knTjV7 zLEDNLFH$fS4(5dVpED51|H=}B{>c+3V-OmK4AIhrZlCEl(AM_T0=zuK- zizjYd4*pHCwT0ObgQyrH7H4At2XjO;@px~TsgAA%R9|05PuEIcOUu&SOwUTs^00xK zshI`T;)sF%Z>|Li8%)3vslU12|K;lbk-Oav1Tx371&)Fb!FgLzNCeQ|r-tGG9E;W; z_5R^{|2Y=zKXM_QU?AJI{a>~IZQ?Z0_VnM@jcrt7jKN@*#$ZMzB}>VcEo(xFhBigA zRfKF&B$OpfLSqS8d&l#8dVcR8Z}0is_kGT}&h`CX>-l`{D|W}MM1o0W+qqCz&a@8xmO|M3uh;cln|6OUI z@X7fQ&dki(hqbDStcmq@R)<*FE(x{7@jPF^02^V5=v9ihMb|f1hw)0IhxkF_<1H_} z1sVWgmXE~@Wjrum=ebV>cmZ0s_CATm;a}mEc52Q5C=nO}OHAzGNx%Y4+73-pK+|sE zf&F7oVIUa*{8{JBz(BDGF#W^YNC4<9N*a&_dh_-a2?DV^K)SlsK3W zOCXnR0@miQE9D7uc?!4U4XYLag5q!qVkYiDSh|^JD*)2x1yFk>+xS2jzFcTm?NE^$ zEusR=1Jt#ow51*G(vhl2c`F}0KRYy{Jo3{2p&4FwzqpssC^#!EQ$-Rz!G~$z2>|jd zoi8@^jT0uuM~BC~Cj2=+8uB*%W~pE!<+;Jls%yObfcUWvPM_P@SPvhqk>^2RtzXee zpw9{L8C-GI=@-g9A^bLEC5ENHZn8J$mR*yf;vV50J7!cpZdF6S#2Ee38Kw@!gf4MU zH~T|ofioE<=_Pgf;Tvc0l%P^<+(Zk%8H}<#p|aT+abY8Ff9Htq!&92lSLbk7D(t{E zjjU(bM04fllo5%^3-CFm)D5AeU=e^FXGmfr{&k_>d3a+)aa}=xN$7&sHTfNh zfVj6VoV5%9Nwq8SCK^0ITUx;v0I2%9`_$cJSLF_4$)r9^g5d7-;)ha7k^2JBT`QGyenmoI!B!BgFZa^nPSIjjmHP5e8zHBct z>}g(M=h3f$4B-6LI6_z_Ow{YzNBpU4Q5No3aPn%6GK4Xlo>ROYK@oQ-NLryT2hS1Q z#~TwSIW2hlviM8?O9=^9I1CPTS9MyYOrlcISt$H6?B!qJq`S6dsv#09^-K@M!vvfq zTkX5@UgaFs(|?Idx+S6ai8fy!JtnNIngF-nVeN7Z`Pkld>>sQwike&!d8m z!q}j+#PS5O1l#Lt&96qwr4S9#BN(B)eb|Czi6eSM<1zl*H{oXKxy8rZigMly7Dpp) zp0Fn82H8REqlzST12a_HGG$OL1zP#tZ!<{Vq-7t-B%@O3Q}|wsw6|$peqXmwPE3aX z2;M0YDH7g@_E4AelRGO{xVu~ql8(6}@GdRA$pQKSu8{71L+l3C5qDtez&Yu}Hxem` z6sMHXl!;;o#{fs;ZdUOQhkK4<_f9*Vzhmk6*zQY_(0iGC-9?Iy&x;P0wqt{_@pc`@ z-STVPHZH9aL>@&(Sms8e^BoA~ujOKuWnROHb2zgex)a}&rr!-4kCTs9rZGVRYYIV- zvlx3+K(QCwE72=^{7f5<=%`? zl>Nr(;dCk;g6aw$Opx=3=@VvK69`}ZZjdTEXD<)m-PPh#nON_W-)WuySB2X5DDN+N zOj#o@Hg%5&TlX_@z|RoxL4x-e)E6|2*6eRf_RH|9>@0i7Xl-rM9ANjdo2TOpy0iRp z@HHQ+`qyJ4Zd+tE9Emv?)0oNb81R+irnMuZ>Qj# zxib@y+4A&mNoGlXP$qd$YD6l2f7kv+drBW{dVN}WI%9gX}>;*m9J4X{*B+`P?WbMg?R|_dOLt0YC zJHiM_Ty3A^GkR^rdo$!_RLz|l@F22ACA23r zJ#_ne&f4MCmW}wIwZp7=nYm*E?mRDe#(1hP%3plU=f|hSpU!`KyPiO-!1Ha8okr4T zJB37Cl;}y+I@x)J6@t!yw`NAC^c%r!=@Sa8&{j3f-kx1?ksX4A;-S<#E11dFr-IQ# zR{qfyN+h{-*_HEB`wzg2wZ9!NvuB)PENk|#M_tyutK;V4i>^I8-0%C89^}pT^~d@X zrZX$TDvB#EGNXQ4%%w>%B=-r;Tp6wJtw&z@62Lp*pP`dAn&FVjAe4>`?UC_VILOQnvfFm7kYb}KIe$4b!q%cDFE;P^!}5wFhS$flol=(c zKOH`gTJ?#vwG4c%BV>!!U?s|3f2Oiv<7D3Rncea6%ttMQ=SEEn7*BSKM z{I;U9VyY&6%QWwRxn-WhQPHJ&t+6%>}7+sVXoLpPbO)$>wJq(%cIl{yAd4L zao(3TFdv5v@49^(rE$qwH>D`KxrI{ti`zebVW|0ofEcHjRC^^ydT1 zit!QWV{YB&7Fp!JzRyR>-^@&*rwXPh>}8kQ`$wvMO}pPl&We;M%*Bo=xRH;1X50$# zU5slhYkSkir-#>@IobM@-9LZpVE$4__664#r;U<(Fif+aek4~_5ISPczF+n%G&YJPZd_dwhcM)XK$a~zGT6f@?}u{2kzI_J`y5h z5613ABWPopVbs3NnT+5kv=awJUz(1+_-pXaxwBvFzTRqoHSnr!F#SULqTm#orO}0` z4PcuJ1W{iBF zKEPVWtf%|A9(S$wMs?&E%QC)W%H5Wm7d}tKyUte8et?%f`c=!1mLN-!R-v?wVf6iz z)G6X}%Z#&ODdUID)ZtFfy9=wnb=?6Uetyt)y~(QPyq;Dlr>K3}Q=wY9_%mo}MmAXZ zJ7&N&B%XPHy{2#D+xAtlZx_lo9}?@xLqFZ?+&f;mh;c-PqH;Eqf4z$u?y_pN>Q=E- ziH*-zQc@6+ub%g8PZ}Rf89BiysN>^Vu*|b~eTqQIXzO`L8nmD()4q3juuoh;Z zx{Lc)DaWwDG3=>cj9@&S2$*_OJ%}J{GTxhrCE`61Z>_G%gwd42_vIJi(910C^C-NfacQ^Sl-eB6%Xg&U!Xb8ybq}LqdnpiS{AK90(zP z1Ord7u@T6SiQp2Di3~i5N%p4%Aecz--@FL!dP@uegZ@@w_#wgnaSCT+2SQQlM9?8^ zm=*yFg@O(lXcIm0a1R|XJV6r#hr(eH8234(1v`X*>mXnTpnnFKYmn~gg}|Cy{$q~2 zLxO!63>pFg2@Vd{4%X48(!C)t0|NsH6b^yIwYVBu0W1mw&(xv>sQhLyCk7DcBpQQ6 zrGT~=@gCGb1`^D5_CHaOY5&qv0{+PqH)jwgo(6$wL${*(t!QKO|ErS8|7r&?u*CoR z`+pJ#IIw6$2$mQ?4WtvewewQhGDSn6=tMk&N_U`A{eLIY&WFmN2KZ2EAh?b;45V&@ zCy*#xlKp=}Y-|wLlmG^vLLge3Bf(q}Z4${7VPJ`Z>caJO59#RW!C)3BeO)*VWoc## zg<9yK4D<|sW6i0AKr)fS_>J}aFIMl5*sX>j)3}z+iF8sB(bJMnC4>Hs8bSKAFYrI| z{e$)VvoAV-#6q~vK(=c8ziRzk#BHFh<-g6#-Td4BL<+a(>D=bN76lY@FUB@IjDy9m z(5*YN-4s*8oj}&+rVh+L4|neH1o$j1E!71)pl~xe=$Un0lQ15DzW@MRrx z!J?<(q3pT2^$+V+Q`u7+9n4PA$lc;2p&F8~jx^B8sR zx>rCR%LJ^+TUW{z>G}+2%^g|I2L#7s6GcrtfXECp^)>*c&kdOGlW6Awp?LDNx@(7v z-Ko(PNG_nRHMKqcShu!hMe19*kj44oQKivW0gudZG6%)H1;)YI=~>DW$SEFFhY$eB zt#!TJ(l<_=nj9aQ^qvY}e{aa&@}H-Gjg%IKwyLgi^8#Xao$P-1iHTkwY7^JPpj!Xp zlR&>S;5)SDrad5#cS7)O=vpjOf5T*7?k#k)p~7ClUAyK~Ja1KNjl~-M(jK7<$40Dh zzHSYK&I4yMO)^UA3Zgd8;K;$HnE0tyUNb0pbxL`wDf--I{K2kKokyqCrLHbuuT-GH zwoT0Em?R6Omef)4>2t6J#k5U<Kzn-O7ywj#*>mb{iVUie9{?=!&L4Vcx>M+-B&$v&`=vrv zoeVc_hlPpI{yIZ3vmN7+dj)UpNi&sotb_OQK7Gg|m$y4}M6B#3R9|>%Sp3xa8LG?< zk3G4s_EcRG;5BXLm%u5(V|IJS_klb3WisMb#kh|E-FUbw5 zyr@BwG>AK8@-uOu83en!aka`CnsWZ}ah~_wK_<`dD#~4L%nR(I>xjBVrsey0$(8Lx zL_W(e>N@r%hz^8bjmJlJK}Ec;eZ-x*cG=S73RX_FNg6+a)pbtL#VcSB2TRG<<>J`< z`?+HyC1&|gUle;4a3L|#8jHf3-&L7aE)%chcM*uX2z~VjIQg!9nM$bmT0O%P{wNV^ z#ZvvIv`;Bl<@6sS67I>!{UR;b$L$1_R1#q}yKMZC14xZRheD%nF=94KbtaM2@_C&9 zaU=_ro>ZPFnrMH0z2)_Ixg@+HW)vlmzaLYWB7RhtU_8Nl`zFjRBk$hv_Tt?4{P$wu zH&57*@`BM2hs(thIzgE#?OD?1t%Vu|J#RCKKEzdD$TYoD;8WB-%k;PD-Tq&8PESoo zeGd^5z9bygg!DWh>o0p&wrEeeEF=SUhwoi_Mzf>V2bg?@&kfNV6esMVl|x}tNpHkc z;i=B45vf!69GwE4jC+{(b~)a661{)gIsA^5(-ZVqvA}!j`#r@9PA`h}N;@zim;`j^ zarc56_st7G@xqTUMO)=vLKZmU%Nu3ml%yMBgaxcwFU^@}M&190t>?+dYqO|ezIFLv z$XS$wdEh;7mUohO&g7YPE|JDZ!}A6ovyXNtbqIHy)!@-E)_BzGSK?g~QF6FHw7;g` zbB;DAJvYm|wtK=twSZHf3V{x^sfUGo=5?(S~&txT%-E$Ff-_@hGg+hw0I zU51R2H;b~@lcn>SFz9cH^CZFs3hN6S#%m6?r}$@jS9X=Xqqns+s}HjJSS_>h20hvS zxwx8-RRbGw(YGzL8;-{6#Wtn&r-ilhrP-#fvTisVIWwJ?oj*D(2*V8UO@;O6;BUNmvJB!T`eNt3~f!F zko#8I{q)^(LDq|`!IF=p_n+Dj4dM6KZ8fvxTijkF*rwm-SFxjK+QxE!oV zwhoA?P$bG`$gG7+9y|oQr}_1GnFIX{eO0}eHSW6ZQyssMP<-wAkpaJFv|t~WUjQZm zKbut%S#hu8Jmc~Y%Y}4ty2O5gxhv!Kef5YdV}aaL0h!v_-oUDw1g{pcIw>5q*kqCjS7$R7KNBC@T5#Nx%QXnV_={J8w%kIE~K8eX5waZX*) z|8ykW{HO0Fd#j*EZ2^0X8Z$}u`g7$aTW5>j&#camXFh5eq-3XL7hr^mX=Q33w8{^Z z+k302B@2%;CrNMQlP|wn9amlpTpExHh(>i4lwnHIBGM?xT{XtZJtr9z$ZF(?_u50= zTVL0dcU_PUt4@4~u6X#QuY%#aFbuA>d?BqI>mU=N33bC%dNGLe-Qlgit&h_-(W6+5 z)1n`9a4{Ye)qVT6x!MI6oz&u#mR54<_Y=?YQn*wvC$?XD&q?QVhh$RSSya~D(jO14 zDkeu=?A&|8mYJmf{?A9t-^|S*X9{P?tX0?A2S=;@Oncs5ninpSUx=HKcPAbFOurTC zw;bPI*8ZlQM;E6%ce3pnYhdw~UcpLe&N;VM=gpG)B&9!VE;HmQ^~52OSEds${}{Rxc6JQ?81X)1 zkhzN5$nbYN?pEz%-kEDGL;r>k0huQ(;>hkkyMz>yZX3 zyE%WAvUE!<-GSmw55dt0fT1NJfC!FKWRcq89?}qHC*VOEo9>5|N=afxKLY%hDXc9TWKN+GK!-J< z8h9-&Ezn^DO@bE==Be$C!>fZ}S}-UC%DE3~Ko7%V+Hj}==hG=V2Xg(0Afq?-;3kHF~G&l&2Kqi@vV`z{Am47Q(5CZWuB9%_0 zkU`suI8RCt9RcQ;{c9E^>OZpNz`s|Dvt|$mjtYTlYHiQzH_+Dh|A&%D|DXfu7{Y)3 z{;P1HBa=#iUSh0fZq#=_NCA%fxZ+f2&SzG1s$-( z;fdt!$iY7;wzhB^av&W?#uIET5MYjoCXwg`*VTsV=^4Ou4x5@;LZO!CW~Mq82B!L! zmXcl{>#<7uV}wy!_2I{hwS2#|&h9Z~xC;{|<2qXuJDQ@p163R|OV+mP%$Mbu7e(xV|@A;f_?)$#(@ArFM*L_{*^EuaSt<44aW%vOA5U@a* zpxNW@orjl;{a(6JI069tNCFaRYk@?9C{(g1!4D4r^!{wSAWYJ#g#OSfUdYk7Z~k$b zUjzVFWb!r(JLd`C1hAKdMGPCGqWK-g#P?;P92ze5@T0P$M{^HVdKq1hJ{{w5R_D9? zVByoyVAkB+#>b87sjR8Z4o0U?_&yQk#K}A#Ko=dQ2k(=Qw?Q?u)P!@2qlURb!jrA9 zym%S`V4jOX52HOY*yMOf1~>sqkNQE8rjcKfRkq4b04Na{28&GX;YdIO&Fc2eVnDML z@W}3o2S1Pu0Dg=RV=z!G0L=cd(B}dAijoE;fxf)`MZ7>P2atZq{2-^{3&71G0q|Mpou9$XIm2ssfWSCRf{>vb5T0(V+6I7hI057V(RMD7C0DLScinK2 zD?A8>kOnE00v^YOJsxbP>@3Apf^02Tc-#9ocEmKhxHN|Dwu@?Yj z*1BG9>lh?VO^%ODdQSPVel+H7`_7ZW`U(p}+toKXxdCD8PFBC`#6&L_rHSKFK%H;V z8KB=0@E%%o(H!8*J5H%h`P41Gq#yx+dBvvQ`q}QMt$y`k-#IvA1To!#fMM8@+6|dK ziGZ+|7L2h907-Rg@rEiKKzmxj7ywj%l{$MrS<>~E)&DO2kZ5OjdzWQ@8`cGm1-nyUk~r&e)@<@CU;-Ph;aE!sE)wYu*lhn8H(gC zH>sRgQq@=ZxQ&{5MX?I-=zZ>Sec%pW$@DmGFczhCGrRya9W8bW+}KPl;4CusNpwLe zE~-(*bYssNt|tsMgJ9P;uUDHxlOxJbaed$nFnoSrUgr9nT>mbbmXJ$$YMyVGO!)ys z__Msiu9IH_Xh7)oI9zxaRM7LrC+yi9S54inVPuq>BybZLZO3?RoE+v@ptx*(4wl7x zkTWJ+be8wrW#LzTml6`pF_swQeWh8&a*--tC%(wb&{uzflkVG;D+PY9W)DA;my+?roODFJ4&$HEsifKn^4E70#2CS+ME&m<6AzKrvh zg)>2Ei4_S#2{t!3T3(M=h`}49M=kmC4x$T^MNVkr4JNqn-i8^c=N6x8FUtAATO19) zecFPU8)yr$yILfw6_BCSo+*KBEl|tvd6z-(BCL8trfF4tpCb>LroBt+_WinhdTKiI zN6=n@D*};CDEC9szS0+@3#BTgA?cR)c;2U_H`{A`gvq9R-4eP*cEB82IT9kC_*NtZ zp5mAimNHdr@8IuX(8DO+WB<4uOsfYFugtYL9z;N<2%#N{;mh_t*Bj z&r##I1#=Yz*lv&>Qq%!)j&Y!H~sgx8OAi<^4n#>>Cau}%fuh~ z%aY$%y{sVeJJsJo_FjVEG`#x$k&r-rohq*|q}GH*HRJ2D)X9X~QHde6?N&JcT@{A^{N zGWTY}Gh3hCFUc%v2+Sl7iH(ZIAMQT9Y)9&c&Th`~&t}Z-n$umut|+Y#S32d|_KV2% z9;Y1-q0$1{0{tk}GX*1BuZtRrUQauD$$H)K&tB4&ymvC8RU|DiP1257c)gHxJGeDv zLgsr__tW>w`I#>=2TMK?KYVUOG=@Iduu{*IZE<;xU>W_GU&V}`ZyU=l%q)DhlrRN3 z7kJM3+(yj-n2aZ{3RjSvSI1lvuFlapQQ&F~Lz2ArtY0%a==@JDvOPZf%}eo)^0yd-cVQ z_wori%Ttrc^^%LSYdFn8FV&1L@wdF$;-_WTHQJOd5A^PfyVA)!BpgP*w`Mur_KY`r z*xWC=Ql224F1Z#ecK8UaSpD0nay#02+Nx?VbKH5ut0rzCzUapD;{!g=sDWNgA3wAo zZZ@+ryt245f`0X<=|Y+aP4pn&+_mwBz6Qj#F@Me}zYNW+@eKP^8m@F=Fz>nK*pdK?zI9eHHo{sWbFSR1NC%2hAbR z?Qd&}doD?Y)FeEzt$g&PuafS(Fbu9UeIcP3V<#D;4s}6SdC&>--Jz}Ct!1fOwxbxd z!=evka4`-Y*?speQst79R!UKFODn1L$LZ%dacqi*1Is6^=ZxdUBa$huObYXU>CZ=I zm6M}R)~-Dv%M4z$6*gRk3%(l1sl^Uk0cD&6q9 z0H#_#F&A;ChV}JEezx2>IrG|zUtuih7%remJKiZLH~SD`VQu_U(paHKVNSNS0pdgY zAY;{XGu_waluL~lvNOj(lJ?!Q!gaM}>C05S%X~HE2YA(eK&j$n38EBX9!A+3K|MS} zp24rS&N=Co(tcRY9PeVizqsyG-{b%B=SOvy+l(64n_1ZklJe*Ml}c61KLc0hB!l?B zTMoJe$I~Bf*7k3G+r2LI?PB@%V|+bv_@`UFTjy(MA(kND)tv3*U+=Gubep%C_b8ev z#>QvM%gYML)GT^*B#ji76^eGg4Rid(nDKuwHMBLlak3M$**CvuEvB=slu@)qWj!c* z2yaqslCSPyAQtXzmUIk+vMO0sLrpdE>4!EAw{4fY)^SaR?`&4}r$V+jA*+{{Ho|q4 z_ObserD>)ZnjP7b7KEkZ0V5BxJ04^~#CqY;c&rEGd<$L=0Jshj>@hTql_eZUCaPn1 zFzR$7h0O*4Jp(!gi}S_PK<;=i0to?Ty{H3&2p$NqleU$H6$Od+CZK|;c)MV0dt9(D zPS*o$pbyfc!`T8vJPiw?6a7g3a5@6~w=SGL-!VhLpuZtBUj+C+L1CCCs^dMdFn3K)EKU^!(||!CQ1*RH4SEa?(}Y8HLH}G}wnM6iCmd~J_K!RE z3IX<}(I{{TBq%6IJxEiXO!b05b#-+i8ZZb9rp897`7=l~EM1M{ulQTR1n-Zd5-2nR znFQKV#JZCMXb3Pn*#Bffr2H#O^8e?g*k=ZzV<`}*y2egczkya(|38#S{1@#{L*xG& z@Bb<6Z_l9MA!ximIe>~|*UnRM#}x&Rq~ftOGS!|;_WOO1w%%kK+25N?0l_rYp`b%n zSR8@0V>$dc#mWk9LGq_zNjSWP2?ER(Q6~^Q;7Bc`rjaR9`S)2BNHb$2 z4GmLGq^`E^Z>|X$7eK_5Xur80|K%S2BX_4Eh!nPG6Fij=i1#p~l8K~IZDKdj&h+2rWiS41e>{oZ^Hg?oM~n|nus@7lwwCs$ z?D1C^P>lR^nmv=VFfp>H_q)5fd2lQ2GLzyiQ{d*V|Ea<2ASCPtaP|Sxo{WhCHW08d LwKgd=cDwXHDN#*w literal 0 HcmV?d00001 diff --git a/applications/external/subghz_remote_new/icons/back_10px.png b/applications/external/subghz_remote_new/icons/back_10px.png new file mode 100644 index 0000000000000000000000000000000000000000..f9c615a99e69c0100b03a9ae7b2df903da4ecd66 GIT binary patch literal 154 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2xGmzZ=C-xtZVk{1FcVbv~PUa<$!;&U>c zv7h@-A}f&37T^=&`v3obAT#vPO>_%)r1c48n{Iv*t(u1!X;5977~7Co?ed rv9U?Av01aVRT(gMJdt+jXk=uN>R^g!*w%ImsF1<>&pI=m5)cB{fFDGZlI8yr;B3<$MxhJ?+;A4eL&#) z0Ra}bue?07WhLz78x$BO|L3mq-MMxdP^D^#YeY#(Vo9o1a#1RfVlXl=GSoFN)ipE; zF*LF=Hn1|b&^9ozGB8+QQTzo(LvDUbW?CgwgE3G~h=Hk + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) SubRemScene##id, +typedef enum { +#include "subrem_scene_config.h" + SubRemSceneNum, +} SubRemScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers subrem_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "subrem_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "subrem_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "subrem_scene_config.h" +#undef ADD_SCENE diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_config.h b/applications/external/subghz_remote_new/scenes/subrem_scene_config.h new file mode 100644 index 0000000000..93d4de642e --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_config.h @@ -0,0 +1,3 @@ +ADD_SCENE(subrem, start, Start) +ADD_SCENE(subrem, openmapfile, OpenMapFile) +ADD_SCENE(subrem, remote, Remote) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c new file mode 100644 index 0000000000..8e651a5347 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -0,0 +1,26 @@ +#include "../subghz_remote_app_i.h" + +void subrem_scene_openmapfile_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + if(subrem_load_from_file(app)) { + // if(subghz_get_load_type_file(subghz) == SubGhzLoadTypeFileRaw) { + // subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad); + // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); + // } else { + // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); + // } + } else { + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SubRemSceneStart); + } +} + +bool subrem_scene_openmapfile_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void subrem_scene_openmapfile_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c new file mode 100644 index 0000000000..787a717608 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -0,0 +1,135 @@ +#include "../subghz_remote_app_i.h" +#include "../views/transmitter.h" + +// TODO: +// #include +// #include + +// #include + +void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +bool subrem_scene_remote_update_data_show(void* context) { + SubGhzRemoteApp* app = context; + //UNUSED(app); + bool ret = false; + + subrem_view_remote_add_data_to_show( + //app->subrem_remote_view, "N/A", "N/A", "N/A", "N/A", "N/A"); + app->subrem_remote_view, + "UP", + "DOWN", + "LEFT", + "RIGHT", + "OK"); + // SubGhzProtocolDecoderBase* decoder = subghz_txrx_get_decoder(app->txrx); + + // if(decoder) { + // FuriString* key_str = furi_string_alloc(); + // FuriString* frequency_str = furi_string_alloc(); + // FuriString* modulation_str = furi_string_alloc(); + + // if(subghz_protocol_decoder_base_deserialize( + // decoder, subghz_txrx_get_fff_data(app->txrx)) == SubGhzProtocolStatusOk) { + // subghz_protocol_decoder_base_get_string(decoder, key_str); + + // subghz_txrx_get_frequency_and_modulation( + // app->txrx, frequency_str, modulation_str, false); + // subghz_view_transmitter_add_data_to_show( + // app->subghz_transmitter, + // furi_string_get_cstr(key_str), + // furi_string_get_cstr(frequency_str), + // furi_string_get_cstr(modulation_str), + // subghz_txrx_protocol_is_transmittable(app->txrx, false)); + // ret = true; + // } + // furi_string_free(frequency_str); + // furi_string_free(modulation_str); + // furi_string_free(key_str); + // } + return ret; +} + +void subrem_scene_remote_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + // TODO: reset custom btns + // keeloq_reset_original_btn(); + // subghz_custom_btns_reset(); + + // TODO: init view data + + if(!subrem_scene_remote_update_data_show(app)) { + // view_dispatcher_send_custom_event( + // app->view_dispatcher, SubGhzCustomEventViewTransmitterError); + } + subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app); + + // TODO: notifications + // app->state_notifications = SubGhzNotificationStateIDLE; + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDRemote); +} + +bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { + SubGhzRemoteApp* app = context; + if(event.type == SceneManagerEventTypeCustom) { + // if(event.event == SubGhzCustomEventViewTransmitterSendStart) { + // app->state_notifications = SubGhzNotificationStateIDLE; + + // if(subghz_tx_start(app, subghz_txrx_get_fff_data(app->txrx))) { + // app->state_notifications = SubGhzNotificationStateTx; + // subrem_scene_remote_update_data_show(app); + // DOLPHIN_DEED(DolphinDeedSubGhzSend); + // } + // return true; + // } else if(event.event == SubGhzCustomEventViewTransmitterSendStop) { + // app->state_notifications = SubGhzNotificationStateIDLE; + // subghz_txrx_stop(app->txrx); + // if(subghz_custom_btn_get() != 0) { + // subghz_custom_btn_set(0); + // uint8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); + // furi_hal_subghz_set_rolling_counter_mult(0); + // // Calling restore! + // subghz_tx_start(app, subghz_txrx_get_fff_data(app->txrx)); + // subghz_txrx_stop(app->txrx); + // furi_hal_subghz_set_rolling_counter_mult(tmp_counter); + // } + // return true; + // } else + if(event.event == SubRemCustomEventViewRemoteBack) { + // app->state_notifications = SubGhzNotificationStateIDLE; //TODO: notification + scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, SubRemSceneStart); + return true; + } + // else if(event.event == SubGhzCustomEventViewTransmitterError) { + // furi_string_set(app->error_str, "Protocol not\nfound!"); + // scene_manager_next_scene(app->scene_manager, SubGhzSceneShowErrorSub); + // } + } else if(event.type == SceneManagerEventTypeTick) { + // if(app->state_notifications == SubGhzNotificationStateTx) { + // notification_message(app->notifications, &sequence_blink_magenta_10); + // } + // return true; + } + return false; +} + +void subrem_scene_remote_on_exit(void* context) { + SubGhzRemoteApp* app = context; + UNUSED(app); + // TODO: notifications and reset KL + + //app->state_notifications = SubGhzNotificationStateIDLE; + + // keeloq_reset_mfname(); + // keeloq_reset_kl_type(); + // keeloq_reset_original_btn(); + // subghz_custom_btns_reset(); + // star_line_reset_mfname(); + // star_line_reset_kl_type(); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c new file mode 100644 index 0000000000..0ad9837e98 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -0,0 +1,93 @@ +#include "../subghz_remote_app_i.h" +#include "../helpers/subrem_custom_event.h" + +void subrem_scene_start_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void subrem_scene_start_on_enter(void* context) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + Submenu* submenu = app->submenu; + submenu_add_item( + submenu, + "Open Map File", + SubmenuIndexOpenMapFile, + subrem_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, "Remote", SubmenuIndexOpenView, subrem_scene_start_submenu_callback, app); + // submenu_add_item( + // submenu, + // "ISP Programmer", + // SubmenuIndexSubGhzRemoteProgrammer, + // subrem_scene_start_submenu_callback, + // app); + // submenu_add_item( + // submenu, + // "Wiring", + // SubmenuIndexAvrIsWiring, + // subrem_scene_start_submenu_callback, + // app); + // submenu_add_item( + // submenu, + // "About", + // SubmenuIndexSubGhzRemoteAbout, + // subrem_scene_start_submenu_callback, + // app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu); +} + +bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexOpenMapFile) { + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); + consumed = true; + } else if(event.event == SubmenuIndexOpenView) { + scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); + consumed = true; + } + // } else if(event.event == SubmenuIndexSubGhzRemoteProgrammer) { + // scene_manager_set_scene_state( + // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewProgrammer); + // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); + // consumed = true; + // } else if(event.event == SubmenuIndexSubGhzRemoteReader) { + // scene_manager_set_scene_state( + // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewReader); + // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); + // consumed = true; + // } else if(event.event == SubmenuIndexSubGhzRemoteWriter) { + // scene_manager_set_scene_state( + // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewWriter); + // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); + // consumed = true; + // } else if(event.event == SubmenuIndexAvrIsWiring) { + // scene_manager_next_scene(app->scene_manager, SubRemSceneWiring); + // consumed = true; + // } + scene_manager_set_scene_state(app->scene_manager, SubRemSceneStart, event.event); + } + + return consumed; +} + +void subrem_scene_start_on_exit(void* context) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c new file mode 100644 index 0000000000..d25e65ce71 --- /dev/null +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -0,0 +1,181 @@ +#include "subghz_remote_app_i.h" + +static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + SubGhzRemoteApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool subghz_remote_app_back_event_callback(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void subghz_remote_app_tick_event_callback(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +SubGhzRemoteApp* subghz_remote_app_alloc() { + SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); + + // // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering + // uint8_t attempts = 0; + // while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { + // furi_hal_power_enable_otg(); + // furi_delay_ms(10); + // } + + app->file_path = furi_string_alloc(); + furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); + //app->error = SubGhzRemoteErrorNoError; + + // GUI + app->gui = furi_record_open(RECORD_GUI); + + // View Dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&subrem_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, subghz_remote_app_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, subghz_remote_app_back_event_callback); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, subghz_remote_app_tick_event_callback, 100); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Open Notification record + app->notifications = furi_record_open(RECORD_NOTIFICATION); + + // SubMenu + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewSubmenu, submenu_get_view(app->submenu)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view(app->view_dispatcher, SubRemViewWidget, widget_get_view(app->widget)); + + // Text Input + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewTextInput, text_input_get_view(app->text_input)); + + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view(app->view_dispatcher, SubRemViewPopup, popup_get_view(app->popup)); + + //Dialog + app->dialogs = furi_record_open(RECORD_DIALOGS); + + // Remote view + app->subrem_remote_view = subrem_view_remote_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewIDRemote, + subrem_view_remote_get_view(app->subrem_remote_view)); + /* + // Reader view + app->subghz_remote_reader_view = subghz_remote_reader_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewReader, + subghz_remote_reader_view_get_view(app->subghz_remote_reader_view)); + + // Writer view + app->subghz_remote_writer_view = subghz_remote_writer_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewWriter, + subghz_remote_writer_view_get_view(app->subghz_remote_writer_view)); + + // Chip detect view + app->subghz_remote_chip_detect_view = subghz_remote_chip_detect_view_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewChipDetect, + subghz_remote_chip_detect_view_get_view(app->subghz_remote_chip_detect_view)); +*/ + scene_manager_next_scene(app->scene_manager, SubRemSceneStart); + + return app; +} + +void subghz_remote_app_free(SubGhzRemoteApp* app) { + furi_assert(app); + + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewSubmenu); + submenu_free(app->submenu); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewWidget); + widget_free(app->widget); + + // TextInput + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewTextInput); + text_input_free(app->text_input); + + // Popup + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewPopup); + popup_free(app->popup); + + //Dialog + furi_record_close(RECORD_DIALOGS); + + // Remote view + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); + subrem_view_remote_free(app->subrem_remote_view); + + // // Reader view + // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewReader); + // subghz_remote_reader_view_free(app->subghz_remote_reader_view); + + // // Writer view + // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewWriter); + // subghz_remote_writer_view_free(app->subghz_remote_writer_view); + + // // Chip detect view + // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewChipDetect); + // subghz_remote_chip_detect_view_free(app->subghz_remote_chip_detect_view); + + // // View dispatcher + // view_dispatcher_free(app->view_dispatcher); + // scene_manager_free(app->scene_manager); + + // Notifications + furi_record_close(RECORD_NOTIFICATION); + app->notifications = NULL; + + // Close records + furi_record_close(RECORD_GUI); + + // Path strings + furi_string_free(app->file_path); + + // Disable 5v power + // if(furi_hal_power_is_otg_enabled()) { + // furi_hal_power_disable_otg(); + // } + + free(app); +} + +int32_t subghz_remote_app(void* p) { + UNUSED(p); + SubGhzRemoteApp* subghz_remote_app = subghz_remote_app_alloc(); + + furi_string_set(subghz_remote_app->file_path, SUBREM_APP_FOLDER); + + view_dispatcher_run(subghz_remote_app->view_dispatcher); + + subghz_remote_app_free(subghz_remote_app); + + return 0; +} diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c new file mode 100644 index 0000000000..43bdd73f31 --- /dev/null +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -0,0 +1,28 @@ +#include "subghz_remote_app_i.h" +#include +#include + +#define TAG "SubGhzRemote" + +bool subrem_load_from_file(SubGhzRemoteApp* app) { + furi_assert(app); + + FuriString* file_path = furi_string_alloc(); + + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_sub1_10px); + browser_options.base_path = SUBREM_APP_FOLDER; + + // Input events and views are managed by file_select + bool res = + dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); + + if(res) { + // res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); + res = false; + } + + furi_string_free(file_path); + + return res; +} diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h new file mode 100644 index 0000000000..bc8c61cdd9 --- /dev/null +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -0,0 +1,53 @@ +#pragma once + +#include "helpers/subrem_types.h" + +#include "views/transmitter.h" + +#include "scenes/subrem_scene.h" + +#include // TODO: +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include "views/subghz_remote_view_programmer.h" +// #include "views/subghz_remote_view_reader.h" +// #include "views/subghz_remote_view_writer.h" +// #include "views/subghz_remote_view_chip_detect.h" + +#define SUBREM_APP_EXTENSION ".txt" +#define SUBREM_APP_FOLDER "/ext/subghz_remote" +#define SUBGHZ_REMOTE_MAX_LEN_NAME 64 + +typedef struct { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + NotificationApp* notifications; + DialogsApp* dialogs; + Popup* popup; + Submenu* submenu; + Widget* widget; + TextInput* text_input; + FuriString* file_path; + char file_name_tmp[SUBGHZ_REMOTE_MAX_LEN_NAME]; + + SubRemViewRemote* subrem_remote_view; + + // AvrIspProgrammerView* subghz_remote_programmer_view; + // AvrIspReaderView* subghz_remote_reader_view; + // AvrIspWriterView* subghz_remote_writer_view; + // AvrIspChipDetectView* subghz_remote_chip_detect_view; + + // AvrIspError error; +} SubGhzRemoteApp; + +bool subrem_load_from_file(SubGhzRemoteApp* app); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.c b/applications/external/subghz_remote_new/views/transmitter.c new file mode 100644 index 0000000000..a3589339d8 --- /dev/null +++ b/applications/external/subghz_remote_new/views/transmitter.c @@ -0,0 +1,277 @@ +#include "transmitter.h" +#include "../subghz_remote_app_i.h" + +#include +#include + +#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 16 +struct SubRemViewRemote { + View* view; + SubRemViewRemoteCallback callback; + void* context; +}; +// FIXME: drop +// static char* char_to_str(char* str, int i) { +// char* converted = malloc(sizeof(char) * i + 1); +// memcpy(converted, str, i); + +// converted[i] = '\0'; + +// return converted; +// } + +// TODO: model + +typedef struct { + // FuriString* up_label; + // FuriString* down_label; + // FuriString* left_label; + // FuriString* right_label; + // FuriString* ok_label; + + char* up_label; + char* down_label; + char* left_label; + char* right_label; + char* ok_label; + + uint8_t pressed_btn; + // bool show_button; + // FuriString* temp_button_id; + // bool draw_temp_button; +} SubRemViewRemoteModel; + +void subrem_view_remote_set_callback( + SubRemViewRemote* subrem_view_remote, + SubRemViewRemoteCallback callback, + void* context) { + furi_assert(subrem_view_remote); + + subrem_view_remote->callback = callback; + subrem_view_remote->context = context; +} + +void subrem_view_remote_add_data_to_show( + SubRemViewRemote* subrem_view_remote, + const char* up_label, + const char* down_label, + const char* left_label, + const char* right_label, + const char* ok_label) { + furi_assert(subrem_view_remote); + + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { + strncpy(model->up_label, up_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->down_label, down_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->left_label, left_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + + // model->up_label = char_to_str((char*)up_label, 16); + // model->down_label = char_to_str((char*)down_label, 16); + // model->left_label = char_to_str((char*)left_label, 16); + // model->right_label = char_to_str((char*)right_label, 16); + // model->ok_label = char_to_str((char*)ok_label, 16); + + // furi_string_set(model->up_label, up_label); + // furi_string_set(model->down_label, down_label); + // furi_string_set(model->left_label, left_label); + // furi_string_set(model->right_label, right_label); + // furi_string_set(model->ok_label, ok_label); + }, + true); +} + +void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + //map found, draw all the things + canvas_clear(canvas); + + //canvas_set_font(canvas, FontPrimary); + //canvas_draw_str(canvas, 0, 10, "U: "); + //canvas_draw_str(canvas, 0, 20, "L: "); + //canvas_draw_str(canvas, 0, 30, "R: "); + //canvas_draw_str(canvas, 0, 40, "D: "); + //canvas_draw_str(canvas, 0, 50, "Ok: "); + + //PNGs are located in assets/icons/SubGHzRemote before compilation + + //Icons for Labels + //canvas_draw_icon(canvas, 0, 0, &I_SubGHzRemote_LeftAlignedButtons_9x64); + canvas_draw_icon(canvas, 1, 5, &I_ButtonUp_7x4); + canvas_draw_icon(canvas, 1, 15, &I_ButtonDown_7x4); + canvas_draw_icon(canvas, 2, 23, &I_ButtonLeft_4x7); + canvas_draw_icon(canvas, 2, 33, &I_ButtonRight_4x7); + canvas_draw_icon(canvas, 0, 42, &I_Ok_btn_9x9); + canvas_draw_icon(canvas, 0, 53, &I_back_10px); + + //Labels + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 10, 10, model->up_label); + canvas_draw_str(canvas, 10, 20, model->down_label); + canvas_draw_str(canvas, 10, 30, model->left_label); + canvas_draw_str(canvas, 10, 40, model->right_label); + canvas_draw_str(canvas, 10, 50, model->ok_label); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + + canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); + + //Status text and indicator + // canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, app->send_status); + + canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); + switch(model->pressed_btn) { + case 0: + break; + case 1: + canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9); + break; + case 2: + canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); + break; + case 3: + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); + break; + case 4: + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); + break; + case 5: + canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); + break; + } + + //Repeat indicator + //canvas_draw_str_aligned(canvas, 125, 40, AlignRight, AlignBottom, "Repeat:"); + //canvas_draw_icon(canvas, 115, 39, &I_SubGHzRemote_Repeat_12x14); + //canvas_draw_str_aligned(canvas, 125, 62, AlignRight, AlignBottom, int_to_char(app->repeat)); +} + +bool subrem_view_remote_input(InputEvent* event, void* context) { + furi_assert(context); + SubRemViewRemote* subrem_view_remote = context; + + if(event->key == InputKeyBack && event->type == InputTypeLong) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { + strcpy(model->up_label, "N/A"); + strcpy(model->down_label, "N/A"); + strcpy(model->left_label, "N/A"); + strcpy(model->right_label, "N/A"); + strcpy(model->ok_label, "N/A"); + + // furi_string_reset(model->up_label); + // furi_string_reset(model->down_label); + // furi_string_reset(model->left_label); + // furi_string_reset(model->right_label); + // furi_string_reset(model->ok_label); + }, + false); + return false; + } else if(event->key == InputKeyUp) { + if(event->type == InputTypePress) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 1; }, + true); + return true; + } else if(event->type == InputTypeRelease) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 0; }, + true); + return true; + } + } + return true; +} + +void subrem_view_remote_enter(void* context) { + furi_assert(context); +} + +void subrem_view_remote_exit(void* context) { + furi_assert(context); +} + +SubRemViewRemote* subrem_view_remote_alloc() { + SubRemViewRemote* subrem_view_remote = malloc(sizeof(SubRemViewRemote)); + + // View allocation and configuration + subrem_view_remote->view = view_alloc(); + view_allocate_model( + subrem_view_remote->view, ViewModelTypeLocking, sizeof(SubRemViewRemoteModel)); + view_set_context(subrem_view_remote->view, subrem_view_remote); + view_set_draw_callback(subrem_view_remote->view, (ViewDrawCallback)subrem_view_remote_draw); + view_set_input_callback(subrem_view_remote->view, subrem_view_remote_input); + view_set_enter_callback(subrem_view_remote->view, subrem_view_remote_enter); + view_set_exit_callback(subrem_view_remote->view, subrem_view_remote_exit); + + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { + model->up_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + model->down_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + model->left_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + model->right_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + model->ok_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + + strcpy(model->up_label, "N/A"); + strcpy(model->down_label, "N/A"); + strcpy(model->left_label, "N/A"); + strcpy(model->right_label, "N/A"); + strcpy(model->ok_label, "N/A"); + + // model->up_label = furi_string_alloc(); + // model->down_label = furi_string_alloc(); + // model->left_label = furi_string_alloc(); + // model->right_label = furi_string_alloc(); + // model->ok_label = furi_string_alloc(); + + model->pressed_btn = 0; + }, + true); + return subrem_view_remote; +} + +void subrem_view_remote_free(SubRemViewRemote* subghz_remote) { + furi_assert(subghz_remote); + + with_view_model( + subghz_remote->view, + SubRemViewRemoteModel * model, + { + free(model->up_label); + free(model->down_label); + free(model->left_label); + free(model->right_label); + free(model->ok_label); + + // furi_string_free(model->up_label); + // furi_string_free(model->down_label); + // furi_string_free(model->left_label); + // furi_string_free(model->right_label); + // furi_string_free(model->ok_label); + }, + true); + view_free(subghz_remote->view); + free(subghz_remote); +} + +View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote) { + furi_assert(subrem_view_remote); + return subrem_view_remote->view; +} \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.h b/applications/external/subghz_remote_new/views/transmitter.h new file mode 100644 index 0000000000..a324d09ece --- /dev/null +++ b/applications/external/subghz_remote_new/views/transmitter.h @@ -0,0 +1,27 @@ +#pragma once + +#include +#include "../helpers/subrem_custom_event.h" + +typedef struct SubRemViewRemote SubRemViewRemote; + +typedef void (*SubRemViewRemoteCallback)(SubRemCustomEvent event, void* context); + +void subrem_view_remote_set_callback( + SubRemViewRemote* subrem_view_remote, + SubRemViewRemoteCallback callback, + void* context); + +SubRemViewRemote* subrem_view_remote_alloc(); + +void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote); + +View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote); + +void subrem_view_remote_add_data_to_show( + SubRemViewRemote* subrem_view_remote, + const char* up_label, + const char* down_label, + const char* left_label, + const char* right_label, + const char* ok_label); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter_old.txt b/applications/external/subghz_remote_new/views/transmitter_old.txt new file mode 100644 index 0000000000..ea2dc2f627 --- /dev/null +++ b/applications/external/subghz_remote_new/views/transmitter_old.txt @@ -0,0 +1,317 @@ +#include "transmitter.h" +#include "../subghz_remote_app_i.h" + +#include +#include + +#include + +struct SubGhzRemoteViewRemote { + View* view; + SubGhzRemoteViewRemoteCallback callback; + void* context; +}; + +typedef struct { + FuriString* frequency_str; + FuriString* preset_str; + FuriString* key_str; + // bool show_button; + // FuriString* temp_button_id; + // bool draw_temp_button; +} SubGhzRemoteViewRemoteModel; + +void subghz_view_transmitter_set_callback( + SubGhzRemoteViewRemote* subghz_transmitter, + SubGhzRemoteViewRemoteCallback callback, + void* context) { + furi_assert(subghz_transmitter); + + subghz_transmitter->callback = callback; + subghz_transmitter->context = context; +} + +void subghz_view_transmitter_add_data_to_show( + SubGhzRemoteViewRemote* subghz_transmitter, + const char* key_str, + const char* frequency_str, + const char* preset_str, + bool show_button) { + furi_assert(subghz_transmitter); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_set(model->key_str, key_str); + furi_string_set(model->frequency_str, frequency_str); + furi_string_set(model->preset_str, preset_str); + model->show_button = show_button; + }, + true); +} + +static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) { + const uint8_t button_height = 12; + 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 - 1, + &I_ButtonCenter_7x7); + canvas_draw_str( + canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); + canvas_invert_color(canvas); +} + +void subghz_view_transmitter_draw(Canvas* canvas, SubGhzRemoteViewRemoteModel* model) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned( + canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); + canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); + canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); + + // if(model->draw_temp_button) { + // canvas_set_font(canvas, FontBatteryPercent); + // canvas_draw_str(canvas, 117, 40, furi_string_get_cstr(model->temp_button_id)); + // canvas_set_font(canvas, FontSecondary); + // } + + // if(model->show_button) { + // canvas_draw_str(canvas, 58, 62, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int"); + // subghz_view_transmitter_button_right(canvas, "Send"); + // } +} + +bool subghz_view_transmitter_input(InputEvent* event, void* context) { + furi_assert(context); + SubGhzRemoteViewRemote* subghz_transmitter = context; + bool can_be_sent = false; + + if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->frequency_str); + furi_string_reset(model->preset_str); + furi_string_reset(model->key_str); + furi_string_reset(model->temp_button_id); + model->show_button = false; + model->draw_temp_button = false; + }, + false); + return false; + } + + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + if(model->show_button) { + can_be_sent = true; + } + }, + true); + + if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { + subghz_custom_btn_set(0); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->temp_button_id); + model->draw_temp_button = false; + }, + true); + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); + return true; + } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) { + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); + return true; + } + + // Temp Buttons (UP) + if(can_be_sent && event->key == InputKeyUp && event->type == InputTypePress) { + subghz_custom_btn_set(1); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->temp_button_id); + if(subghz_custom_btn_get_original() != 0) { + if(subghz_custom_btn_get() == 1) { + furi_string_printf( + model->temp_button_id, "%01X", subghz_custom_btn_get_original()); + model->draw_temp_button = true; + } + } + }, + true); + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); + return true; + } else if(can_be_sent && event->key == InputKeyUp && event->type == InputTypeRelease) { + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); + return true; + } + // Down + if(can_be_sent && event->key == InputKeyDown && event->type == InputTypePress) { + subghz_custom_btn_set(2); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->temp_button_id); + if(subghz_custom_btn_get_original() != 0) { + if(subghz_custom_btn_get() == 2) { + furi_string_printf( + model->temp_button_id, "%01X", subghz_custom_btn_get_original()); + model->draw_temp_button = true; + } + } + }, + true); + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); + return true; + } else if(can_be_sent && event->key == InputKeyDown && event->type == InputTypeRelease) { + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); + return true; + } + // Left + if(can_be_sent && event->key == InputKeyLeft && event->type == InputTypePress) { + subghz_custom_btn_set(3); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->temp_button_id); + if(subghz_custom_btn_get_original() != 0) { + if(subghz_custom_btn_get() == 3) { + furi_string_printf( + model->temp_button_id, "%01X", subghz_custom_btn_get_original()); + model->draw_temp_button = true; + } + } + }, + true); + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); + return true; + } else if(can_be_sent && event->key == InputKeyLeft && event->type == InputTypeRelease) { + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); + return true; + } + // Right + if(can_be_sent && event->key == InputKeyRight && event->type == InputTypePress) { + subghz_custom_btn_set(4); + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_reset(model->temp_button_id); + if(subghz_custom_btn_get_original() != 0) { + if(subghz_custom_btn_get() == 4) { + furi_string_printf( + model->temp_button_id, "%01X", subghz_custom_btn_get_original()); + model->draw_temp_button = true; + } + } + }, + true); + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); + return true; + } else if(can_be_sent && event->key == InputKeyRight && event->type == InputTypeRelease) { + subghz_transmitter->callback( + SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); + return true; + } + + return true; +} + +void subghz_view_transmitter_enter(void* context) { + furi_assert(context); +} + +void subghz_view_transmitter_exit(void* context) { + furi_assert(context); +} + +SubGhzRemoteViewRemote* subghz_view_transmitter_alloc() { + SubGhzRemoteViewRemote* subghz_transmitter = malloc(sizeof(SubGhzRemoteViewRemote)); + + // View allocation and configuration + subghz_transmitter->view = view_alloc(); + view_allocate_model( + subghz_transmitter->view, ViewModelTypeLocking, sizeof(SubGhzRemoteViewRemoteModel)); + view_set_context(subghz_transmitter->view, subghz_transmitter); + view_set_draw_callback( + subghz_transmitter->view, (ViewDrawCallback)subghz_view_transmitter_draw); + view_set_input_callback(subghz_transmitter->view, subghz_view_transmitter_input); + view_set_enter_callback(subghz_transmitter->view, subghz_view_transmitter_enter); + view_set_exit_callback(subghz_transmitter->view, subghz_view_transmitter_exit); + + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + model->frequency_str = furi_string_alloc(); + model->preset_str = furi_string_alloc(); + model->key_str = furi_string_alloc(); + model->temp_button_id = furi_string_alloc(); + }, + true); + return subghz_transmitter; +} + +void subghz_view_transmitter_free(SubGhzRemoteViewRemote* subghz_transmitter) { + furi_assert(subghz_transmitter); + + with_view_model( + subghz_transmitter->view, + SubGhzRemoteViewRemoteModel * model, + { + furi_string_free(model->frequency_str); + furi_string_free(model->preset_str); + furi_string_free(model->key_str); + furi_string_free(model->temp_button_id); + }, + true); + view_free(subghz_transmitter->view); + free(subghz_transmitter); +} + +View* subghz_view_transmitter_get_view(SubGhzRemoteViewRemote* subghz_transmitter) { + furi_assert(subghz_transmitter); + return subghz_transmitter->view; +} From 8c3fe81edd8e1f2a138f02f927ef301add559ce5 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Sun, 14 May 2023 23:23:18 +0300 Subject: [PATCH 02/23] Preset logic --- .../subghz_remote_new/helpers/subrem_types.h | 12 + .../subghz_remote_new/subghz_remote_app.c | 13 ++ .../subghz_remote_new/subghz_remote_app_i.c | 215 +++++++++++++++++- .../subghz_remote_new/subghz_remote_app_i.h | 29 +++ 4 files changed, 268 insertions(+), 1 deletion(-) diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h index ffb2f8044e..56687977fb 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_types.h +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -29,6 +29,18 @@ typedef enum { SubRemViewIDRemote, //SubRemViewChipDetect, } SubRemViewID; + +typedef enum { + // Loadin State + SubRemSubKeyTypeNoData = 0, + SubRemSubKeyTypeHaveFileName, + + // Key Type + SubRemSubKeyTypeStaticKey = 100, + SubRemSubKeyTypeDynamicKey, + SubRemSubKeyTypeRawKey, +} SubRemSubKeyType; + /* typedef enum { SubRemErrorNoError, diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index d25e65ce71..35775c9da4 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -102,6 +102,13 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { SubRemViewChipDetect, subghz_remote_chip_detect_view_get_view(app->subghz_remote_chip_detect_view)); */ + for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + app->subs_preset[i] = subrem_sub_file_preset_alloc(); + } + + app->setting = subghz_setting_alloc(); + subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + scene_manager_next_scene(app->scene_manager, SubRemSceneStart); return app; @@ -133,6 +140,12 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); subrem_view_remote_free(app->subrem_remote_view); + subghz_setting_free(app->setting); + + for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + subrem_sub_file_preset_free(app->subs_preset[i]); + } + // // Reader view // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewReader); // subghz_remote_reader_view_free(app->subghz_remote_reader_view); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 43bdd73f31..bc874946d6 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -2,8 +2,220 @@ #include #include +#include +#include + #define TAG "SubGhzRemote" +static const char* map_file_labels[SUBREM_MAX_SUB_KEY_COUNT][2] = { + {"OK", "OKLABEL"}, + {"UP", "ULABEL"}, + {"DOWN", "DLABEL"}, + {"LEFT", "LLABEL"}, + {"RIGHT", "RLABEL"}, +}; + +bool subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { + const char* preset_name = ""; + if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { + preset_name = "AM270"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { + preset_name = "AM650"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { + preset_name = "FM238"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { + preset_name = "FM476"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { + // preset_name = "CUSTOM"; + return false; + } else { + FURI_LOG_E(TAG, "Unknown preset"); + return false; + } + size_t preset_index = subghz_setting_get_inx_preset_by_name(setting, preset_name); + freq_preset->data = subghz_setting_get_preset_data(setting, preset_index); + return true; +} + +SubRemSubFilePreset* subrem_sub_file_preset_alloc() { + SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); + + sub_preset->fff_data = flipper_format_string_alloc(); + sub_preset->file_path = furi_string_alloc(); + sub_preset->label = furi_string_alloc_set_str("N/A"); + sub_preset->type = SubRemSubKeyTypeNoData; + + return sub_preset; +} + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_free(sub_preset->label); + furi_string_free(sub_preset->file_path); + flipper_format_free(sub_preset->fff_data); + + free(sub_preset); +} + +static bool subrem_sub_file_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { + furi_assert(app); + bool ret = false; + + for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + if(!flipper_format_read_string( + fff_data_file, map_file_labels[i][0], app->subs_preset[i]->file_path)) { + FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); + app->subs_preset[i]->type = SubRemSubKeyTypeNoData; + //continue; + } else if(!flipper_format_rewind(fff_data_file)) { + // Rewind error + //continue; + } else if(!flipper_format_read_string( + fff_data_file, map_file_labels[i][1], app->subs_preset[i]->label)) { + FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); + furi_string_set_str(app->subs_preset[i]->label, "N/A"); + } else { + FURI_LOG_I( + TAG, + // "Loaded %s key \r\nLabel %s file %s", + "Loaded %s key: %s %s", + map_file_labels[i][0], + furi_string_get_cstr(app->subs_preset[i]->label), + furi_string_get_cstr(app->subs_preset[i]->file_path)); + app->subs_preset[i]->type = SubRemSubKeyTypeHaveFileName; // TODO + ret = true; + } + flipper_format_rewind(fff_data_file); + } + return ret; +} + +static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { + furi_assert(app); + FuriString* temp_str = furi_string_alloc(); + uint32_t temp_data32; + bool ret = false; + SubRemSubFilePreset* sub_preset; + + // TODO: + // const SubGhzProtocolRegistry* protocol_registry_items = + // subghz_environment_get_protocol_registry(app->environment); + + for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + sub_preset = app->subs_preset[i]; + if(sub_preset->type == SubRemSubKeyTypeNoData) { + continue; + } + do { + if(!flipper_format_file_open_existing( + fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { + FURI_LOG_E( + TAG, + "Error open file %s", + furi_string_get_cstr(sub_preset->file_path)); // TODO: warning + break; + } + + if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + break; + } + + if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + temp_data32 == SUBGHZ_KEY_FILE_VERSION) { + } else { + FURI_LOG_E(TAG, "Type or version mismatch"); + break; + } + + //Load frequency + if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { + FURI_LOG_W(TAG, "Cannot read frequency. Defaulting to 433.92 MHz"); + sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency( + app->setting); // TODO: Get default from settings + } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { + FURI_LOG_E(TAG, "This frequency can only be used for RX"); + break; + } else { + sub_preset->freq_preset.frequency = temp_data32; + } + + //Load preset + if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { + FURI_LOG_E(TAG, "Missing Preset"); + break; + } + + if(!subrem_set_preset_data( + app->setting, &sub_preset->freq_preset, furi_string_get_cstr(temp_str))) { + FURI_LOG_E(TAG, "Cannot load preset."); + break; + } + + //Load protocol + if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + + FlipperFormat* fff_data = sub_preset->fff_data; + if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { + //if RAW + subghz_protocol_raw_gen_fff_data( + fff_data, furi_string_get_cstr(sub_preset->file_path)); + sub_preset->type = SubRemSubKeyTypeRawKey; + } else { + stream_copy_full( + flipper_format_get_raw_stream(fff_data_file), + flipper_format_get_raw_stream(fff_data)); + } + + // subghz_protocol_registry_get_by_name( + // protocol_registry_items, furi_string_get_cstr(temp_str)); // TODO: check dynamic and protocol found + + } while(false); + + flipper_format_file_close(fff_data_file); + } + furi_string_free(temp_str); + + ret = false; // TODO: + return ret; +} + +bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { + furi_assert(app); + furi_assert(file_path); + // TODO: drop furi log + FURI_LOG_I(TAG, "Load Map File Start"); // drop + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + bool ret = false; + FURI_LOG_I(TAG, "Open Map File.."); // drop + if(!flipper_format_file_open_existing(fff_data_file, file_path)) { + FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); + } else { + if(!subrem_sub_file_preset_load(app, fff_data_file)) { + // TODO: error popup or return error type + FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); + } else if(!(flipper_format_file_close(fff_data_file) && + subrem_sub_presets_check(app, fff_data_file))) { + ret = true; + } + } + + flipper_format_file_close(fff_data_file); + flipper_format_free(fff_data_file); + + furi_record_close(RECORD_STORAGE); + + FURI_LOG_I(TAG, "Load Map File Done"); // drop + ret = false; // TODO + return ret; +} + bool subrem_load_from_file(SubGhzRemoteApp* app) { furi_assert(app); @@ -18,7 +230,8 @@ bool subrem_load_from_file(SubGhzRemoteApp* app) { dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); if(res) { - // res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); + res = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); + // FIXME res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); res = false; } diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index bc8c61cdd9..e01ba939ea 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -18,6 +18,12 @@ #include #include +#include +#include +#include + +#include // FIXME: + // #include "views/subghz_remote_view_programmer.h" // #include "views/subghz_remote_view_reader.h" // #include "views/subghz_remote_view_writer.h" @@ -26,6 +32,25 @@ #define SUBREM_APP_EXTENSION ".txt" #define SUBREM_APP_FOLDER "/ext/subghz_remote" #define SUBGHZ_REMOTE_MAX_LEN_NAME 64 +#define SUBREM_MAX_SUB_KEY_COUNT (5U) + +typedef struct { + uint32_t frequency; + uint8_t* data; +} FreqPreset; + +// Sub File preset +typedef struct { + FlipperFormat* fff_data; + FreqPreset freq_preset; + FuriString* file_path; + FuriString* label; + SubRemSubKeyType type; +} SubRemSubFilePreset; + +SubRemSubFilePreset* subrem_sub_file_preset_alloc(); + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); typedef struct { Gui* gui; @@ -42,6 +67,10 @@ typedef struct { SubRemViewRemote* subrem_remote_view; + SubRemSubFilePreset* subs_preset[SUBREM_MAX_SUB_KEY_COUNT]; + + SubGhzSetting* setting; + // AvrIspProgrammerView* subghz_remote_programmer_view; // AvrIspReaderView* subghz_remote_reader_view; // AvrIspWriterView* subghz_remote_writer_view; From 3f33fe8cb0864604e758bec767cad51ff04efa1a Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Mon, 15 May 2023 15:05:04 +0300 Subject: [PATCH 03/23] add TX --- .../helpers/subrem_custom_event.h | 7 + .../scenes/subrem_scene_openmapfile.c | 1 + .../scenes/subrem_scene_remote.c | 26 +++- .../subghz_remote_new/subghz_remote_app.c | 37 +++++ .../subghz_remote_new/subghz_remote_app_i.c | 144 ++++++++++++++++-- .../subghz_remote_new/subghz_remote_app_i.h | 9 +- .../subghz_remote_new/views/transmitter.c | 4 + 7 files changed, 206 insertions(+), 22 deletions(-) diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index d1559a7960..0e0ab94ef4 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -11,6 +11,13 @@ typedef enum { //SubRemCustomEvent SubRemCustomEventViewRemoteBack = 100, + SubRemCustomEventViewRemoteStartUP, + SubRemCustomEventViewRemoteStartDOWN, + SubRemCustomEventViewRemoteStartLEFT, + SubRemCustomEventViewRemoteStartRIGHT, + SubRemCustomEventViewRemoteStartOK, + SubRemCustomEventViewRemoteStop, + // SubRemCustomEventSceneDeleteSuccess = 100, // SubRemCustomEventSceneDelete, // SubRemCustomEventSceneDeleteRAW, diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index 8e651a5347..67ccca1c39 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -10,6 +10,7 @@ void subrem_scene_openmapfile_on_enter(void* context) { // } else { // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); // } + scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); } else { scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SubRemSceneStart); } diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c index 787a717608..58e253d1ce 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -21,11 +21,18 @@ bool subrem_scene_remote_update_data_show(void* context) { subrem_view_remote_add_data_to_show( //app->subrem_remote_view, "N/A", "N/A", "N/A", "N/A", "N/A"); app->subrem_remote_view, - "UP", - "DOWN", - "LEFT", - "RIGHT", - "OK"); + // "UP", + // "DOWN", + // "LEFT", + // "RIGHT", + // "OK"); + + furi_string_get_cstr(app->subs_preset[0]->label), + furi_string_get_cstr(app->subs_preset[1]->label), + furi_string_get_cstr(app->subs_preset[2]->label), + furi_string_get_cstr(app->subs_preset[3]->label), + furi_string_get_cstr(app->subs_preset[4]->label)); + // SubGhzProtocolDecoderBase* decoder = subghz_txrx_get_decoder(app->txrx); // if(decoder) { @@ -105,7 +112,16 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { scene_manager_search_and_switch_to_previous_scene( app->scene_manager, SubRemSceneStart); return true; + } else if(event.event == SubRemCustomEventViewRemoteStartUP) { + if(subghz_tx_start_sub(app, app->subs_preset[0])) { + notification_message(app->notifications, &sequence_blink_start_magenta); + } + } else if(event.event == SubRemCustomEventViewRemoteStop) { + subghz_tx_stop_sub(app, app->subs_preset[0]); + notification_message(app->notifications, &sequence_blink_stop); } + // notification_message(app->notification, &sequence_blink_stop); + // else if(event.event == SubGhzCustomEventViewTransmitterError) { // furi_string_set(app->error_str, "Protocol not\nfound!"); // scene_manager_next_scene(app->scene_manager, SubGhzSceneShowErrorSub); diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index 35775c9da4..1bfa3a1b3a 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -1,5 +1,7 @@ #include "subghz_remote_app_i.h" +#include + static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubGhzRemoteApp* app = context; @@ -21,6 +23,17 @@ static void subghz_remote_app_tick_event_callback(void* context) { SubGhzRemoteApp* subghz_remote_app_alloc() { SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); + // Enable power for External CC1101 if it is connected + furi_hal_subghz_enable_ext_power(); + // Auto switch to internal radio if external radio is not available + furi_delay_ms(15); + if(!furi_hal_subghz_check_radio()) { + furi_hal_subghz_select_radio_type(SubGhzRadioInternal); + furi_hal_subghz_init_radio_type(SubGhzRadioInternal); + } + + furi_hal_power_suppress_charge_enter(); + // // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering // uint8_t attempts = 0; // while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { @@ -109,6 +122,21 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->setting = subghz_setting_alloc(); subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + app->environment = subghz_environment_alloc(); + + subghz_environment_load_keystore(app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); + subghz_environment_load_keystore( + app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + subghz_environment_set_came_atomo_rainbow_table_file_name( + app->environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + app->environment, EXT_PATH("subghz/assets/alutech_at_4n")); + subghz_environment_set_nice_flor_s_rainbow_table_file_name( + app->environment, EXT_PATH("subghz/assets/nice_flor_s")); + subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry); + + app->receiver = subghz_receiver_alloc_init(app->environment); + scene_manager_next_scene(app->scene_manager, SubRemSceneStart); return app; @@ -117,6 +145,13 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { void subghz_remote_app_free(SubGhzRemoteApp* app) { furi_assert(app); + furi_hal_power_suppress_charge_exit(); + + // Disable power for External CC1101 if it was enabled and module is connected + furi_hal_subghz_disable_ext_power(); + // Reinit SPI handles for internal radio / nfc + furi_hal_subghz_init_radio_type(SubGhzRadioInternal); + // Submenu view_dispatcher_remove_view(app->view_dispatcher, SubRemViewSubmenu); submenu_free(app->submenu); @@ -140,6 +175,8 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); subrem_view_remote_free(app->subrem_remote_view); + subghz_receiver_free(app->receiver); + subghz_environment_free(app->environment); subghz_setting_free(app->setting); for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index bc874946d6..7ebad702fb 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -8,11 +8,11 @@ #define TAG "SubGhzRemote" static const char* map_file_labels[SUBREM_MAX_SUB_KEY_COUNT][2] = { - {"OK", "OKLABEL"}, {"UP", "ULABEL"}, {"DOWN", "DLABEL"}, {"LEFT", "LLABEL"}, {"RIGHT", "RLABEL"}, + {"OK", "OKLABEL"}, }; bool subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { @@ -42,7 +42,9 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() { sub_preset->fff_data = flipper_format_string_alloc(); sub_preset->file_path = furi_string_alloc(); + sub_preset->protocaol_name = furi_string_alloc(); sub_preset->label = furi_string_alloc_set_str("N/A"); + sub_preset->type = SubRemSubKeyTypeNoData; return sub_preset; @@ -52,13 +54,35 @@ void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { furi_assert(sub_preset); furi_string_free(sub_preset->label); + furi_string_free(sub_preset->protocaol_name); furi_string_free(sub_preset->file_path); flipper_format_free(sub_preset->fff_data); free(sub_preset); } -static bool subrem_sub_file_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { +void subrem_subs_file_preset_reset(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_set_str(sub_preset->label, "N/A"); + furi_string_reset(sub_preset->protocaol_name); + furi_string_reset(sub_preset->file_path); + + Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); + stream_clean(fff_data_stream); + + sub_preset->type = SubRemSubKeyTypeNoData; +} + +void subrem_sub_file_presets_reset(SubGhzRemoteApp* app) { + furi_assert(app); + + for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + subrem_subs_file_preset_reset(app->subs_preset[i]); + } +} + +static bool subrem_sub_file_presets_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); bool ret = false; @@ -83,7 +107,7 @@ static bool subrem_sub_file_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff map_file_labels[i][0], furi_string_get_cstr(app->subs_preset[i]->label), furi_string_get_cstr(app->subs_preset[i]->file_path)); - app->subs_preset[i]->type = SubRemSubKeyTypeHaveFileName; // TODO + app->subs_preset[i]->type = SubRemSubKeyTypeHaveFileName; // TODO: ret = true; } flipper_format_rewind(fff_data_file); @@ -91,6 +115,67 @@ static bool subrem_sub_file_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff return ret; } +bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { + furi_assert(app); + furi_assert(sub_preset); + bool ret = false; + + FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); + + do { + flipper_format_rewind(sub_preset->fff_data); // FIXME: + + app->transmitter = subghz_transmitter_alloc_init( + app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); + + if(app->transmitter) { + if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) != + SubGhzProtocolStatusOk) { + FURI_LOG_E(TAG, "Deserialize error!"); + break; + } + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + + furi_hal_subghz_idle(); + + furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + + if(!furi_hal_subghz_tx()) { + FURI_LOG_E(TAG, "Sending not allowed"); + break; + } + + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); + + ret = true; + } + } while(false); + + // ret = false; // TODO: + return ret; +} + +void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { + furi_assert(app); + furi_assert(sub_preset); + + //Stop TX + furi_hal_subghz_stop_async_tx(); + + subghz_transmitter_stop(app->transmitter); + subghz_transmitter_free(app->transmitter); + furi_hal_subghz_idle(); + + // TODO: need saving logic +} + static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); FuriString* temp_str = furi_string_alloc(); @@ -98,10 +183,6 @@ static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_da bool ret = false; SubRemSubFilePreset* sub_preset; - // TODO: - // const SubGhzProtocolRegistry* protocol_registry_items = - // subghz_environment_get_protocol_registry(app->environment); - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { sub_preset = app->subs_preset[i]; if(sub_preset->type == SubRemSubKeyTypeNoData) { @@ -172,16 +253,44 @@ static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_da flipper_format_get_raw_stream(fff_data)); } - // subghz_protocol_registry_get_by_name( - // protocol_registry_items, furi_string_get_cstr(temp_str)); // TODO: check dynamic and protocol found + const SubGhzProtocolRegistry* protocol_registry_items = + subghz_environment_get_protocol_registry(app->environment); + + const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name( + protocol_registry_items, furi_string_get_cstr(temp_str)); + if(!protocol) { + FURI_LOG_E(TAG, "Protocol not found"); + break; + } else if(protocol->flag & SubGhzProtocolFlag_Send) { // FIXME: + + if(protocol->type == SubGhzProtocolTypeStatic) { + sub_preset->type = SubRemSubKeyTypeStaticKey; + } else if(protocol->type == SubGhzProtocolTypeDynamic) { + sub_preset->type = SubRemSubKeyTypeDynamicKey; + } else if(protocol->type == SubGhzProtocolTypeRAW) { + sub_preset->type = SubRemSubKeyTypeRawKey; + // } else if(protocol->type == SubGhzProtocolTypeBinRAW) { // TODO: BINRAW + } else { + FURI_LOG_E(TAG, "Unsuported Protocol"); + break; + } + + furi_string_set(sub_preset->protocaol_name, temp_str); + } // TODO: check dynamic and protocol found + + ret |= true; + + if(ret) { + FURI_LOG_I(TAG, "Protocol Loaded"); + } } while(false); flipper_format_file_close(fff_data_file); } furi_string_free(temp_str); - ret = false; // TODO: + //ret = false; // TODO: return ret; } @@ -194,14 +303,19 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); bool ret = false; FURI_LOG_I(TAG, "Open Map File.."); // drop + + subrem_sub_file_presets_reset(app); + if(!flipper_format_file_open_existing(fff_data_file, file_path)) { FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); } else { - if(!subrem_sub_file_preset_load(app, fff_data_file)) { + if(!subrem_sub_file_presets_load(app, fff_data_file)) { // TODO: error popup or return error type FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); - } else if(!(flipper_format_file_close(fff_data_file) && - subrem_sub_presets_check(app, fff_data_file))) { + } else if( + (flipper_format_file_close(fff_data_file)) && + (subrem_sub_presets_check(app, fff_data_file))) { + FURI_LOG_I(TAG, "Load Map File Seccesful"); ret = true; } } @@ -211,8 +325,7 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { furi_record_close(RECORD_STORAGE); - FURI_LOG_I(TAG, "Load Map File Done"); // drop - ret = false; // TODO + //ret = false; // TODO: return ret; } @@ -232,7 +345,6 @@ bool subrem_load_from_file(SubGhzRemoteApp* app) { if(res) { res = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); // FIXME res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); - res = false; } furi_string_free(file_path); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index e01ba939ea..d954eca023 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -44,6 +44,7 @@ typedef struct { FlipperFormat* fff_data; FreqPreset freq_preset; FuriString* file_path; + FuriString* protocaol_name; FuriString* label; SubRemSubKeyType type; } SubRemSubFilePreset; @@ -70,6 +71,9 @@ typedef struct { SubRemSubFilePreset* subs_preset[SUBREM_MAX_SUB_KEY_COUNT]; SubGhzSetting* setting; + SubGhzEnvironment* environment; + SubGhzReceiver* receiver; + SubGhzTransmitter* transmitter; // AvrIspProgrammerView* subghz_remote_programmer_view; // AvrIspReaderView* subghz_remote_reader_view; @@ -79,4 +83,7 @@ typedef struct { // AvrIspError error; } SubGhzRemoteApp; -bool subrem_load_from_file(SubGhzRemoteApp* app); \ No newline at end of file +bool subrem_load_from_file(SubGhzRemoteApp* app); + +bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); +void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.c b/applications/external/subghz_remote_new/views/transmitter.c index a3589339d8..6f43a14066 100644 --- a/applications/external/subghz_remote_new/views/transmitter.c +++ b/applications/external/subghz_remote_new/views/transmitter.c @@ -185,6 +185,8 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { SubRemViewRemoteModel * model, { model->pressed_btn = 1; }, true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); return true; } else if(event->type == InputTypeRelease) { with_view_model( @@ -192,6 +194,8 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { SubRemViewRemoteModel * model, { model->pressed_btn = 0; }, true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStop, subrem_view_remote->context); return true; } } From cdf8daff867049d16986b1109eb814cbd9ba631a Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Mon, 15 May 2023 22:11:18 +0300 Subject: [PATCH 04/23] add tx 2 --- .../helpers/subrem_custom_event.h | 1 + .../scenes/subrem_scene_remote.c | 65 +++++++++++++++- .../subghz_remote_new/subghz_remote_app.c | 2 + .../subghz_remote_new/subghz_remote_app_i.c | 21 ++++- .../subghz_remote_new/subghz_remote_app_i.h | 13 +++- .../subghz_remote_new/views/transmitter.c | 78 +++++++++++++------ .../subghz_remote_new/views/transmitter.h | 4 +- 7 files changed, 152 insertions(+), 32 deletions(-) diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index 0e0ab94ef4..0c999d5e50 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -17,6 +17,7 @@ typedef enum { SubRemCustomEventViewRemoteStartRIGHT, SubRemCustomEventViewRemoteStartOK, SubRemCustomEventViewRemoteStop, + SubRemCustomEventViewRemoteForceStop, // SubRemCustomEventSceneDeleteSuccess = 100, // SubRemCustomEventSceneDelete, diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c index 58e253d1ce..f7da910abf 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -1,6 +1,8 @@ #include "../subghz_remote_app_i.h" #include "../views/transmitter.h" +#include + // TODO: // #include // #include @@ -13,6 +15,12 @@ void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, event); } +void subrem_scene_remote_raw_callback_end_tx(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewRemoteForceStop); +} + bool subrem_scene_remote_update_data_show(void* context) { SubGhzRemoteApp* app = context; //UNUSED(app); @@ -113,12 +121,65 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { app->scene_manager, SubRemSceneStart); return true; } else if(event.event == SubRemCustomEventViewRemoteStartUP) { - if(subghz_tx_start_sub(app, app->subs_preset[0])) { + if(subghz_tx_start_sub( + app, app->subs_preset[0], subrem_scene_remote_raw_callback_end_tx)) { + app->chusen_sub = 0; + subrem_view_remote_set_state(app->subrem_remote_view, 1); + notification_message(app->notifications, &sequence_blink_start_magenta); + } + return true; + } else if(event.event == SubRemCustomEventViewRemoteStartDOWN) { + if(subghz_tx_start_sub( + app, app->subs_preset[1], subrem_scene_remote_raw_callback_end_tx)) { + app->chusen_sub = 1; + subrem_view_remote_set_state(app->subrem_remote_view, 2); + notification_message(app->notifications, &sequence_blink_start_magenta); + } + return true; + } else if(event.event == SubRemCustomEventViewRemoteStartLEFT) { + if(subghz_tx_start_sub( + app, app->subs_preset[2], subrem_scene_remote_raw_callback_end_tx)) { + app->chusen_sub = 2; + subrem_view_remote_set_state(app->subrem_remote_view, 3); notification_message(app->notifications, &sequence_blink_start_magenta); } + return true; + } else if(event.event == SubRemCustomEventViewRemoteStartRIGHT) { + if(subghz_tx_start_sub( + app, app->subs_preset[3], subrem_scene_remote_raw_callback_end_tx)) { + app->chusen_sub = 3; + subrem_view_remote_set_state(app->subrem_remote_view, 4); + notification_message(app->notifications, &sequence_blink_start_magenta); + } + return true; + } else if(event.event == SubRemCustomEventViewRemoteStartOK) { + if(subghz_tx_start_sub( + app, app->subs_preset[4], subrem_scene_remote_raw_callback_end_tx)) { + app->chusen_sub = 4; + subrem_view_remote_set_state(app->subrem_remote_view, 5); + notification_message(app->notifications, &sequence_blink_start_magenta); + } + return true; + } else if(event.event == SubRemCustomEventViewRemoteForceStop) { + if(app->tx_running) { + subghz_tx_stop_sub(app); + subrem_view_remote_set_state(app->subrem_remote_view, 0); + } + notification_message(app->notifications, &sequence_blink_stop); + return true; } else if(event.event == SubRemCustomEventViewRemoteStop) { - subghz_tx_stop_sub(app, app->subs_preset[0]); + // if(app->tx_running && + // (app->subs_preset[app->chusen_sub]->type == SubRemSubKeyTypeRawKey)) { + // subghz_tx_stop_sub(app); + // subrem_view_remote_set_state(app->subrem_remote_view, 0); + // } + // notification_message(app->notifications, &sequence_blink_stop); + if(app->tx_running) { + subghz_tx_stop_sub(app); + subrem_view_remote_set_state(app->subrem_remote_view, 0); + } notification_message(app->notifications, &sequence_blink_stop); + return true; } // notification_message(app->notification, &sequence_blink_stop); diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index 1bfa3a1b3a..17a559da85 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -137,6 +137,8 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->receiver = subghz_receiver_alloc_init(app->environment); + app->tx_running = false; + scene_manager_next_scene(app->scene_manager, SubRemSceneStart); return app; diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 7ebad702fb..ef22a9e6d1 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -115,7 +115,10 @@ static bool subrem_sub_file_presets_load(SubGhzRemoteApp* app, FlipperFormat* ff return ret; } -bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { +bool subghz_tx_start_sub( + SubGhzRemoteApp* app, + SubRemSubFilePreset* sub_preset, + SubGhzProtocolEncoderRAWCallbackEnd callback) { furi_assert(app); furi_assert(sub_preset); bool ret = false; @@ -152,19 +155,26 @@ bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) break; } + if(sub_preset->type == SubRemSubKeyTypeRawKey) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( + app->transmitter), + callback, + app); + } + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); ret = true; } } while(false); + app->tx_running = ret; // TODO: - // ret = false; // TODO: return ret; } -void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { +void subghz_tx_stop_sub(SubGhzRemoteApp* app) { furi_assert(app); - furi_assert(sub_preset); //Stop TX furi_hal_subghz_stop_async_tx(); @@ -173,7 +183,10 @@ void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { subghz_transmitter_free(app->transmitter); furi_hal_subghz_idle(); + // SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; + // TODO: need saving logic + app->tx_running = false; } static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index d954eca023..13f3d63c53 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -18,6 +18,8 @@ #include #include +#include + #include #include #include @@ -75,6 +77,10 @@ typedef struct { SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; + bool tx_running; + + uint8_t chusen_sub; + // AvrIspProgrammerView* subghz_remote_programmer_view; // AvrIspReaderView* subghz_remote_reader_view; // AvrIspWriterView* subghz_remote_writer_view; @@ -85,5 +91,8 @@ typedef struct { bool subrem_load_from_file(SubGhzRemoteApp* app); -bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); -void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); \ No newline at end of file +bool subghz_tx_start_sub( + SubGhzRemoteApp* app, + SubRemSubFilePreset* sub_preset, + SubGhzProtocolEncoderRAWCallbackEnd callback); +void subghz_tx_stop_sub(SubGhzRemoteApp* app); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.c b/applications/external/subghz_remote_new/views/transmitter.c index 6f43a14066..a814880f97 100644 --- a/applications/external/subghz_remote_new/views/transmitter.c +++ b/applications/external/subghz_remote_new/views/transmitter.c @@ -85,6 +85,15 @@ void subrem_view_remote_add_data_to_show( true); } +void subrem_view_remote_set_state(SubRemViewRemote* subrem_view_remote, uint8_t state) { + furi_assert(subrem_view_remote); + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = state; }, + true); +} + void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); @@ -139,10 +148,10 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); break; case 3: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); break; case 4: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); break; case 5: canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); @@ -177,28 +186,51 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { // furi_string_reset(model->ok_label); }, false); - return false; - } else if(event->key == InputKeyUp) { - if(event->type == InputTypePress) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 1; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); - return true; - } else if(event->type == InputTypeRelease) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 0; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStop, subrem_view_remote->context); - return true; - } + return false; // TODO: check + } else if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 0; }, + true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteForceStop, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyBack) { + return true; } + // BACK button processing end + + if(event->key == InputKeyUp && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyDown && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartDOWN, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyLeft && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartLEFT, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyRight && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartRIGHT, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyOk && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartOK, subrem_view_remote->context); + return true; + } else if(event->type == InputTypeRelease) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 0; }, + true); + subrem_view_remote->callback(SubRemCustomEventViewRemoteStop, subrem_view_remote->context); + return true; + } + return true; } diff --git a/applications/external/subghz_remote_new/views/transmitter.h b/applications/external/subghz_remote_new/views/transmitter.h index a324d09ece..64985ff121 100644 --- a/applications/external/subghz_remote_new/views/transmitter.h +++ b/applications/external/subghz_remote_new/views/transmitter.h @@ -24,4 +24,6 @@ void subrem_view_remote_add_data_to_show( const char* down_label, const char* left_label, const char* right_label, - const char* ok_label); \ No newline at end of file + const char* ok_label); + +void subrem_view_remote_set_state(SubRemViewRemote* subrem_view_remote, uint8_t state); \ No newline at end of file From 075dfe8109ab3de051188f43f738443b48ebfd54 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Wed, 17 May 2023 17:48:05 +0300 Subject: [PATCH 05/23] Revert "add tx 2" This reverts commit cdf8daff867049d16986b1109eb814cbd9ba631a. --- .../helpers/subrem_custom_event.h | 1 - .../scenes/subrem_scene_remote.c | 65 +--------------- .../subghz_remote_new/subghz_remote_app.c | 2 - .../subghz_remote_new/subghz_remote_app_i.c | 21 +---- .../subghz_remote_new/subghz_remote_app_i.h | 13 +--- .../subghz_remote_new/views/transmitter.c | 78 ++++++------------- .../subghz_remote_new/views/transmitter.h | 4 +- 7 files changed, 32 insertions(+), 152 deletions(-) diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index 0c999d5e50..0e0ab94ef4 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -17,7 +17,6 @@ typedef enum { SubRemCustomEventViewRemoteStartRIGHT, SubRemCustomEventViewRemoteStartOK, SubRemCustomEventViewRemoteStop, - SubRemCustomEventViewRemoteForceStop, // SubRemCustomEventSceneDeleteSuccess = 100, // SubRemCustomEventSceneDelete, diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c index f7da910abf..58e253d1ce 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -1,8 +1,6 @@ #include "../subghz_remote_app_i.h" #include "../views/transmitter.h" -#include - // TODO: // #include // #include @@ -15,12 +13,6 @@ void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, event); } -void subrem_scene_remote_raw_callback_end_tx(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewRemoteForceStop); -} - bool subrem_scene_remote_update_data_show(void* context) { SubGhzRemoteApp* app = context; //UNUSED(app); @@ -121,65 +113,12 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { app->scene_manager, SubRemSceneStart); return true; } else if(event.event == SubRemCustomEventViewRemoteStartUP) { - if(subghz_tx_start_sub( - app, app->subs_preset[0], subrem_scene_remote_raw_callback_end_tx)) { - app->chusen_sub = 0; - subrem_view_remote_set_state(app->subrem_remote_view, 1); - notification_message(app->notifications, &sequence_blink_start_magenta); - } - return true; - } else if(event.event == SubRemCustomEventViewRemoteStartDOWN) { - if(subghz_tx_start_sub( - app, app->subs_preset[1], subrem_scene_remote_raw_callback_end_tx)) { - app->chusen_sub = 1; - subrem_view_remote_set_state(app->subrem_remote_view, 2); - notification_message(app->notifications, &sequence_blink_start_magenta); - } - return true; - } else if(event.event == SubRemCustomEventViewRemoteStartLEFT) { - if(subghz_tx_start_sub( - app, app->subs_preset[2], subrem_scene_remote_raw_callback_end_tx)) { - app->chusen_sub = 2; - subrem_view_remote_set_state(app->subrem_remote_view, 3); + if(subghz_tx_start_sub(app, app->subs_preset[0])) { notification_message(app->notifications, &sequence_blink_start_magenta); } - return true; - } else if(event.event == SubRemCustomEventViewRemoteStartRIGHT) { - if(subghz_tx_start_sub( - app, app->subs_preset[3], subrem_scene_remote_raw_callback_end_tx)) { - app->chusen_sub = 3; - subrem_view_remote_set_state(app->subrem_remote_view, 4); - notification_message(app->notifications, &sequence_blink_start_magenta); - } - return true; - } else if(event.event == SubRemCustomEventViewRemoteStartOK) { - if(subghz_tx_start_sub( - app, app->subs_preset[4], subrem_scene_remote_raw_callback_end_tx)) { - app->chusen_sub = 4; - subrem_view_remote_set_state(app->subrem_remote_view, 5); - notification_message(app->notifications, &sequence_blink_start_magenta); - } - return true; - } else if(event.event == SubRemCustomEventViewRemoteForceStop) { - if(app->tx_running) { - subghz_tx_stop_sub(app); - subrem_view_remote_set_state(app->subrem_remote_view, 0); - } - notification_message(app->notifications, &sequence_blink_stop); - return true; } else if(event.event == SubRemCustomEventViewRemoteStop) { - // if(app->tx_running && - // (app->subs_preset[app->chusen_sub]->type == SubRemSubKeyTypeRawKey)) { - // subghz_tx_stop_sub(app); - // subrem_view_remote_set_state(app->subrem_remote_view, 0); - // } - // notification_message(app->notifications, &sequence_blink_stop); - if(app->tx_running) { - subghz_tx_stop_sub(app); - subrem_view_remote_set_state(app->subrem_remote_view, 0); - } + subghz_tx_stop_sub(app, app->subs_preset[0]); notification_message(app->notifications, &sequence_blink_stop); - return true; } // notification_message(app->notification, &sequence_blink_stop); diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index 17a559da85..1bfa3a1b3a 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -137,8 +137,6 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->receiver = subghz_receiver_alloc_init(app->environment); - app->tx_running = false; - scene_manager_next_scene(app->scene_manager, SubRemSceneStart); return app; diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index ef22a9e6d1..7ebad702fb 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -115,10 +115,7 @@ static bool subrem_sub_file_presets_load(SubGhzRemoteApp* app, FlipperFormat* ff return ret; } -bool subghz_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback) { +bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { furi_assert(app); furi_assert(sub_preset); bool ret = false; @@ -155,26 +152,19 @@ bool subghz_tx_start_sub( break; } - if(sub_preset->type == SubRemSubKeyTypeRawKey) { - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( - app->transmitter), - callback, - app); - } - furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); ret = true; } } while(false); - app->tx_running = ret; // TODO: + // ret = false; // TODO: return ret; } -void subghz_tx_stop_sub(SubGhzRemoteApp* app) { +void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { furi_assert(app); + furi_assert(sub_preset); //Stop TX furi_hal_subghz_stop_async_tx(); @@ -183,10 +173,7 @@ void subghz_tx_stop_sub(SubGhzRemoteApp* app) { subghz_transmitter_free(app->transmitter); furi_hal_subghz_idle(); - // SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; - // TODO: need saving logic - app->tx_running = false; } static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 13f3d63c53..d954eca023 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -18,8 +18,6 @@ #include #include -#include - #include #include #include @@ -77,10 +75,6 @@ typedef struct { SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; - bool tx_running; - - uint8_t chusen_sub; - // AvrIspProgrammerView* subghz_remote_programmer_view; // AvrIspReaderView* subghz_remote_reader_view; // AvrIspWriterView* subghz_remote_writer_view; @@ -91,8 +85,5 @@ typedef struct { bool subrem_load_from_file(SubGhzRemoteApp* app); -bool subghz_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback); -void subghz_tx_stop_sub(SubGhzRemoteApp* app); \ No newline at end of file +bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); +void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.c b/applications/external/subghz_remote_new/views/transmitter.c index a814880f97..6f43a14066 100644 --- a/applications/external/subghz_remote_new/views/transmitter.c +++ b/applications/external/subghz_remote_new/views/transmitter.c @@ -85,15 +85,6 @@ void subrem_view_remote_add_data_to_show( true); } -void subrem_view_remote_set_state(SubRemViewRemote* subrem_view_remote, uint8_t state) { - furi_assert(subrem_view_remote); - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = state; }, - true); -} - void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); @@ -148,10 +139,10 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); break; case 3: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); break; case 4: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); break; case 5: canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); @@ -186,51 +177,28 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { // furi_string_reset(model->ok_label); }, false); - return false; // TODO: check - } else if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 0; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteForceStop, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyBack) { - return true; + return false; + } else if(event->key == InputKeyUp) { + if(event->type == InputTypePress) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 1; }, + true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); + return true; + } else if(event->type == InputTypeRelease) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 0; }, + true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStop, subrem_view_remote->context); + return true; + } } - // BACK button processing end - - if(event->key == InputKeyUp && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyDown && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartDOWN, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyLeft && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartLEFT, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyRight && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartRIGHT, subrem_view_remote->context); - return true; - } else if(event->key == InputKeyOk && event->type == InputTypePress) { - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartOK, subrem_view_remote->context); - return true; - } else if(event->type == InputTypeRelease) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 0; }, - true); - subrem_view_remote->callback(SubRemCustomEventViewRemoteStop, subrem_view_remote->context); - return true; - } - return true; } diff --git a/applications/external/subghz_remote_new/views/transmitter.h b/applications/external/subghz_remote_new/views/transmitter.h index 64985ff121..a324d09ece 100644 --- a/applications/external/subghz_remote_new/views/transmitter.h +++ b/applications/external/subghz_remote_new/views/transmitter.h @@ -24,6 +24,4 @@ void subrem_view_remote_add_data_to_show( const char* down_label, const char* left_label, const char* right_label, - const char* ok_label); - -void subrem_view_remote_set_state(SubRemViewRemote* subrem_view_remote, uint8_t state); \ No newline at end of file + const char* ok_label); \ No newline at end of file From 24e4c6522122a0429f876df1a8514b4ed832984e Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Wed, 17 May 2023 17:52:46 +0300 Subject: [PATCH 06/23] some improvement and cleanup --- .../helpers/subrem_custom_event.h | 66 +------ .../subghz_remote_new/helpers/subrem_types.h | 43 ++-- .../scenes/subrem_scene_openmapfile.c | 7 +- .../scenes/subrem_scene_remote.c | 165 ++++++++-------- .../scenes/subrem_scene_start.c | 54 ++---- .../subghz_remote_new/subghz_remote_app.c | 48 +---- .../subghz_remote_new/subghz_remote_app_i.c | 183 +++++++++++------- .../subghz_remote_new/subghz_remote_app_i.h | 36 ++-- .../views/{transmitter.c => remote.c} | 157 +++++++++------ .../views/{transmitter.h => remote.h} | 13 +- 10 files changed, 371 insertions(+), 401 deletions(-) rename applications/external/subghz_remote_new/views/{transmitter.c => remote.c} (67%) rename applications/external/subghz_remote_new/views/{transmitter.h => remote.h} (66%) diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index 0e0ab94ef4..90d60f0269 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -6,69 +6,17 @@ typedef enum { // SubRemCustomEventManagerSetRAW, //SubmenuIndex - SubmenuIndexOpenMapFile, - SubmenuIndexOpenView, // TODO: temp debug + SubmenuIndexSubRemOpenMapFile, + SubmenuIndexSubRemRemoteView, // TODO: temp debug + SubmenuIndexSubRemAbout, //SubRemCustomEvent - SubRemCustomEventViewRemoteBack = 100, - SubRemCustomEventViewRemoteStartUP, + SubRemCustomEventViewRemoteStartUP = 100, SubRemCustomEventViewRemoteStartDOWN, SubRemCustomEventViewRemoteStartLEFT, SubRemCustomEventViewRemoteStartRIGHT, SubRemCustomEventViewRemoteStartOK, + SubRemCustomEventViewRemoteBack, SubRemCustomEventViewRemoteStop, - - // SubRemCustomEventSceneDeleteSuccess = 100, - // SubRemCustomEventSceneDelete, - // SubRemCustomEventSceneDeleteRAW, - // SubRemCustomEventSceneDeleteRAWBack, - - // SubRemCustomEventSceneReceiverInfoTxStart, - // SubRemCustomEventSceneReceiverInfoTxStop, - // SubRemCustomEventSceneReceiverInfoSave, - // SubRemCustomEventSceneSaveName, - // SubRemCustomEventSceneSaveSuccess, - // SubRemCustomEventSceneShowErrorBack, - // SubRemCustomEventSceneShowErrorOk, - // SubRemCustomEventSceneShowErrorSub, - // SubRemCustomEventSceneShowOnlyRX, - // SubRemCustomEventSceneAnalyzerLock, - // SubRemCustomEventSceneAnalyzerUnlock, - // SubRemCustomEventSceneSettingLock, - - // SubRemCustomEventSceneExit, - // SubRemCustomEventSceneStay, - - // SubRemCustomEventSceneRpcLoad, - // SubRemCustomEventSceneRpcButtonPress, - // SubRemCustomEventSceneRpcButtonRelease, - // SubRemCustomEventSceneRpcSessionClose, - - // SubRemCustomEventViewReceiverOK, - // SubRemCustomEventViewReceiverConfig, - // SubRemCustomEventViewReceiverBack, - // SubRemCustomEventViewReceiverOffDisplay, - // SubRemCustomEventViewReceiverUnlock, - // SubRemCustomEventViewReceiverDeleteItem, - - // SubRemCustomEventViewReadRAWBack, - // SubRemCustomEventViewReadRAWIDLE, - // SubRemCustomEventViewReadRAWREC, - // SubRemCustomEventViewReadRAWConfig, - // SubRemCustomEventViewReadRAWErase, - // SubRemCustomEventViewReadRAWSendStart, - // SubRemCustomEventViewReadRAWSendStop, - // SubRemCustomEventViewReadRAWSave, - // SubRemCustomEventViewReadRAWTXRXStop, - // SubRemCustomEventViewReadRAWMore, - - // SubRemCustomEventViewTransmitterBack, - // SubRemCustomEventViewTransmitterSendStart, - // SubRemCustomEventViewTransmitterSendStop, - // SubRemCustomEventViewTransmitterError, - - // SubRemCustomEventViewFreqAnalOkShort, - // SubRemCustomEventViewFreqAnalOkLong, - - // SubRemCustomEventByteInputDone, -} SubRemCustomEvent; + SubRemCustomEventViewRemoteForcedStop, +} SubRemCustomEvent; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h index 56687977fb..0bf31e6a4a 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_types.h +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -2,50 +2,39 @@ #include #include -/* -#define AVR_ISP_VERSION_APP "0.1" -#define AVR_ISP_DEVELOPED "SkorP" -#define AVR_ISP_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" -#define AVR_ISP_APP_FILE_VERSION 1 -#define AVR_ISP_APP_FILE_TYPE "Flipper Dump AVR" -#define AVR_ISP_APP_EXTENSION ".avr" -*/ +// #define SUBREM_APP_APP_FILE_VERSION 1 +// #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file" +#define SUBREM_APP_EXTENSION ".txt" -// TODO: rename Filepath -//#define SUBREMOTEMAP_FOLDER "/ext/subghz_remote" -#define SUBGHZ_REMOTE_APP_EXTENSION ".txt" -#define SUBGHZ_REMOTE_APP_PATH_PREFIX "/ext/subghz_remote" +typedef enum { + SubRemSubKeyNameUp = (0U), + SubRemSubKeyNameDown, + SubRemSubKeyNameLeft, + SubRemSubKeyNameRight, + SubRemSubKeyNameOk, + SubRemSubKeyNameMaxCount, +} SubRemSubKeyName; typedef enum { - //SubRemViewVariableItemList, SubRemViewSubmenu, - //SubRemViewProgrammer, - //SubRemViewReader, - //SubRemViewWriter, SubRemViewWidget, SubRemViewPopup, SubRemViewTextInput, SubRemViewIDRemote, - //SubRemViewChipDetect, } SubRemViewID; typedef enum { // Loadin State SubRemSubKeyTypeNoData = 0, - SubRemSubKeyTypeHaveFileName, + // SubRemSubKeyTypeHaveFileName, // Key Type SubRemSubKeyTypeStaticKey = 100, SubRemSubKeyTypeDynamicKey, SubRemSubKeyTypeRawKey, -} SubRemSubKeyType; +} SubRemSubKeyType; // TODO: depricated -/* -typedef enum { - SubRemErrorNoError, - SubRemErrorReading, - SubRemErrorWriting, - SubRemErrorVerification, - SubRemErrorWritingFuse, -} SubRemError;*/ \ No newline at end of file +// typedef enum { +// +// } SubRemLoadMapState; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index 67ccca1c39..504bfee2ec 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -4,14 +4,9 @@ void subrem_scene_openmapfile_on_enter(void* context) { SubGhzRemoteApp* app = context; if(subrem_load_from_file(app)) { - // if(subghz_get_load_type_file(subghz) == SubGhzLoadTypeFileRaw) { - // subghz_rx_key_state_set(subghz, SubGhzRxKeyStateRAWLoad); - // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneReadRAW); - // } else { - // scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSavedMenu); - // } scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); } else { + // TODO: Map Preset Reset scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SubRemSceneStart); } } diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c index 58e253d1ce..a04399cd3f 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -1,5 +1,9 @@ #include "../subghz_remote_app_i.h" -#include "../views/transmitter.h" +#include "../views/remote.h" + +#include + +#define TAG "SubRemScenRemote" // TODO: // #include @@ -13,61 +17,48 @@ void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { view_dispatcher_send_custom_event(app->view_dispatcher, event); } -bool subrem_scene_remote_update_data_show(void* context) { +void subrem_scene_remote_raw_callback_end_tx(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewRemoteForcedStop); +} + +static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) { + uint8_t ret = 0; + + if(event_id == SubRemCustomEventViewRemoteStartUP) { + ret = SubRemSubKeyNameUp; + } else if(event_id == SubRemCustomEventViewRemoteStartDOWN) { + ret = SubRemSubKeyNameDown; + } else if(event_id == SubRemCustomEventViewRemoteStartLEFT) { + ret = SubRemSubKeyNameLeft; + } else if(event_id == SubRemCustomEventViewRemoteStartRIGHT) { + ret = SubRemSubKeyNameRight; + } else if(event_id == SubRemCustomEventViewRemoteStartOK) { + ret = SubRemSubKeyNameOk; + } + + return ret; +} + +static bool subrem_scene_remote_update_data_show(void* context) { SubGhzRemoteApp* app = context; - //UNUSED(app); bool ret = false; subrem_view_remote_add_data_to_show( - //app->subrem_remote_view, "N/A", "N/A", "N/A", "N/A", "N/A"); app->subrem_remote_view, - // "UP", - // "DOWN", - // "LEFT", - // "RIGHT", - // "OK"); - furi_string_get_cstr(app->subs_preset[0]->label), furi_string_get_cstr(app->subs_preset[1]->label), furi_string_get_cstr(app->subs_preset[2]->label), furi_string_get_cstr(app->subs_preset[3]->label), furi_string_get_cstr(app->subs_preset[4]->label)); - // SubGhzProtocolDecoderBase* decoder = subghz_txrx_get_decoder(app->txrx); - - // if(decoder) { - // FuriString* key_str = furi_string_alloc(); - // FuriString* frequency_str = furi_string_alloc(); - // FuriString* modulation_str = furi_string_alloc(); - - // if(subghz_protocol_decoder_base_deserialize( - // decoder, subghz_txrx_get_fff_data(app->txrx)) == SubGhzProtocolStatusOk) { - // subghz_protocol_decoder_base_get_string(decoder, key_str); - - // subghz_txrx_get_frequency_and_modulation( - // app->txrx, frequency_str, modulation_str, false); - // subghz_view_transmitter_add_data_to_show( - // app->subghz_transmitter, - // furi_string_get_cstr(key_str), - // furi_string_get_cstr(frequency_str), - // furi_string_get_cstr(modulation_str), - // subghz_txrx_protocol_is_transmittable(app->txrx, false)); - // ret = true; - // } - // furi_string_free(frequency_str); - // furi_string_free(modulation_str); - // furi_string_free(key_str); - // } return ret; } void subrem_scene_remote_on_enter(void* context) { SubGhzRemoteApp* app = context; - // TODO: reset custom btns - // keeloq_reset_original_btn(); - // subghz_custom_btns_reset(); - // TODO: init view data if(!subrem_scene_remote_update_data_show(app)) { @@ -84,63 +75,71 @@ void subrem_scene_remote_on_enter(void* context) { bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { SubGhzRemoteApp* app = context; if(event.type == SceneManagerEventTypeCustom) { - // if(event.event == SubGhzCustomEventViewTransmitterSendStart) { - // app->state_notifications = SubGhzNotificationStateIDLE; - - // if(subghz_tx_start(app, subghz_txrx_get_fff_data(app->txrx))) { - // app->state_notifications = SubGhzNotificationStateTx; - // subrem_scene_remote_update_data_show(app); - // DOLPHIN_DEED(DolphinDeedSubGhzSend); - // } - // return true; - // } else if(event.event == SubGhzCustomEventViewTransmitterSendStop) { - // app->state_notifications = SubGhzNotificationStateIDLE; - // subghz_txrx_stop(app->txrx); - // if(subghz_custom_btn_get() != 0) { - // subghz_custom_btn_set(0); - // uint8_t tmp_counter = furi_hal_subghz_get_rolling_counter_mult(); - // furi_hal_subghz_set_rolling_counter_mult(0); - // // Calling restore! - // subghz_tx_start(app, subghz_txrx_get_fff_data(app->txrx)); - // subghz_txrx_stop(app->txrx); - // furi_hal_subghz_set_rolling_counter_mult(tmp_counter); - // } - // return true; - // } else if(event.event == SubRemCustomEventViewRemoteBack) { - // app->state_notifications = SubGhzNotificationStateIDLE; //TODO: notification - scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SubRemSceneStart); + if(!scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, SubRemSceneOpenMapFile)) { + if(!scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, SubRemSceneStart)) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } + } return true; - } else if(event.event == SubRemCustomEventViewRemoteStartUP) { - if(subghz_tx_start_sub(app, app->subs_preset[0])) { + } else if( + event.event == SubRemCustomEventViewRemoteStartUP || + event.event == SubRemCustomEventViewRemoteStartDOWN || + event.event == SubRemCustomEventViewRemoteStartLEFT || + event.event == SubRemCustomEventViewRemoteStartRIGHT || + event.event == SubRemCustomEventViewRemoteStartOK) { + // Start sending sub + subghz_tx_stop_sub(app, true); + app->chusen_sub = subrem_scene_remote_event_to_index(event.event); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading); + if(subghz_tx_start_sub( + app, + app->subs_preset[app->chusen_sub], + subrem_scene_remote_raw_callback_end_tx)) { + subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub); + subrem_view_remote_set_state( + app->subrem_remote_view, SubRemViewRemoteStateSending); notification_message(app->notifications, &sequence_blink_start_magenta); + } else { + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); } - } else if(event.event == SubRemCustomEventViewRemoteStop) { - subghz_tx_stop_sub(app, app->subs_preset[0]); + return true; + } else if(event.event == SubRemCustomEventViewRemoteForcedStop) { + subghz_tx_stop_sub(app, true); + subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + notification_message(app->notifications, &sequence_blink_stop); + return true; + } else if(event.event == SubRemCustomEventViewRemoteStop) { + if(subghz_tx_stop_sub(app, false)) { + subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + + notification_message(app->notifications, &sequence_blink_stop); + } + return true; } - // notification_message(app->notification, &sequence_blink_stop); - - // else if(event.event == SubGhzCustomEventViewTransmitterError) { - // furi_string_set(app->error_str, "Protocol not\nfound!"); - // scene_manager_next_scene(app->scene_manager, SubGhzSceneShowErrorSub); - // } - } else if(event.type == SceneManagerEventTypeTick) { - // if(app->state_notifications == SubGhzNotificationStateTx) { - // notification_message(app->notifications, &sequence_blink_magenta_10); - // } - // return true; } + // } else if(event.type == SceneManagerEventTypeTick) { + // } return false; } void subrem_scene_remote_on_exit(void* context) { SubGhzRemoteApp* app = context; - UNUSED(app); - // TODO: notifications and reset KL - //app->state_notifications = SubGhzNotificationStateIDLE; + subghz_tx_stop_sub(app, true); + + subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + + notification_message(app->notifications, &sequence_blink_stop); + + // TODO: notifications and reset KL // keeloq_reset_mfname(); // keeloq_reset_kl_type(); diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c index 0ad9837e98..75328ab8a7 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -16,23 +16,17 @@ void subrem_scene_start_on_enter(void* context) { submenu_add_item( submenu, "Open Map File", - SubmenuIndexOpenMapFile, + SubmenuIndexSubRemOpenMapFile, subrem_scene_start_submenu_callback, app); +#if FURI_DEBUG submenu_add_item( - submenu, "Remote", SubmenuIndexOpenView, subrem_scene_start_submenu_callback, app); - // submenu_add_item( - // submenu, - // "ISP Programmer", - // SubmenuIndexSubGhzRemoteProgrammer, - // subrem_scene_start_submenu_callback, - // app); - // submenu_add_item( - // submenu, - // "Wiring", - // SubmenuIndexAvrIsWiring, - // subrem_scene_start_submenu_callback, - // app); + submenu, + "Remote_Debug", + SubmenuIndexSubRemRemoteView, + subrem_scene_start_submenu_callback, + app); +#endif // submenu_add_item( // submenu, // "About", @@ -53,33 +47,21 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexOpenMapFile) { + if(event.event == SubmenuIndexSubRemOpenMapFile) { + //scene_manager_set_scene_state(app->scene_manager, SubRemSceneStart, event.event); scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); consumed = true; - } else if(event.event == SubmenuIndexOpenView) { - scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); - consumed = true; } - // } else if(event.event == SubmenuIndexSubGhzRemoteProgrammer) { - // scene_manager_set_scene_state( - // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewProgrammer); - // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); - // consumed = true; - // } else if(event.event == SubmenuIndexSubGhzRemoteReader) { - // scene_manager_set_scene_state( - // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewReader); - // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); - // consumed = true; - // } else if(event.event == SubmenuIndexSubGhzRemoteWriter) { - // scene_manager_set_scene_state( - // app->scene_manager, SubRemSceneChipDetect, SubGhzRemoteViewWriter); - // scene_manager_next_scene(app->scene_manager, SubRemSceneChipDetect); - // consumed = true; - // } else if(event.event == SubmenuIndexAvrIsWiring) { - // scene_manager_next_scene(app->scene_manager, SubRemSceneWiring); + // } else if(event.event == SubmenuIndexSubRemAbout) { + // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); // consumed = true; // } - scene_manager_set_scene_state(app->scene_manager, SubRemSceneStart, event.event); +#if FURI_DEBUG + else if(event.event == SubmenuIndexSubRemRemoteView) { + scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); + consumed = true; + } +#endif } return consumed; diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index 1bfa3a1b3a..ad6fe13fbc 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -93,29 +93,8 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->view_dispatcher, SubRemViewIDRemote, subrem_view_remote_get_view(app->subrem_remote_view)); - /* - // Reader view - app->subghz_remote_reader_view = subghz_remote_reader_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SubRemViewReader, - subghz_remote_reader_view_get_view(app->subghz_remote_reader_view)); - // Writer view - app->subghz_remote_writer_view = subghz_remote_writer_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SubRemViewWriter, - subghz_remote_writer_view_get_view(app->subghz_remote_writer_view)); - - // Chip detect view - app->subghz_remote_chip_detect_view = subghz_remote_chip_detect_view_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, - SubRemViewChipDetect, - subghz_remote_chip_detect_view_get_view(app->subghz_remote_chip_detect_view)); -*/ - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { app->subs_preset[i] = subrem_sub_file_preset_alloc(); } @@ -137,6 +116,8 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->receiver = subghz_receiver_alloc_init(app->environment); + app->tx_running = false; + scene_manager_next_scene(app->scene_manager, SubRemSceneStart); return app; @@ -179,26 +160,10 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { subghz_environment_free(app->environment); subghz_setting_free(app->setting); - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { subrem_sub_file_preset_free(app->subs_preset[i]); } - // // Reader view - // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewReader); - // subghz_remote_reader_view_free(app->subghz_remote_reader_view); - - // // Writer view - // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewWriter); - // subghz_remote_writer_view_free(app->subghz_remote_writer_view); - - // // Chip detect view - // view_dispatcher_remove_view(app->view_dispatcher, SubRemViewChipDetect); - // subghz_remote_chip_detect_view_free(app->subghz_remote_chip_detect_view); - - // // View dispatcher - // view_dispatcher_free(app->view_dispatcher); - // scene_manager_free(app->scene_manager); - // Notifications furi_record_close(RECORD_NOTIFICATION); app->notifications = NULL; @@ -209,11 +174,6 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { // Path strings furi_string_free(app->file_path); - // Disable 5v power - // if(furi_hal_power_is_otg_enabled()) { - // furi_hal_power_disable_otg(); - // } - free(app); } diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 7ebad702fb..dac0d15b73 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -7,15 +7,16 @@ #define TAG "SubGhzRemote" -static const char* map_file_labels[SUBREM_MAX_SUB_KEY_COUNT][2] = { - {"UP", "ULABEL"}, - {"DOWN", "DLABEL"}, - {"LEFT", "LLABEL"}, - {"RIGHT", "RLABEL"}, - {"OK", "OKLABEL"}, +static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { + [SubRemSubKeyNameUp] = {"UP", "ULABEL"}, + [SubRemSubKeyNameDown] = {"DOWN", "DLABEL"}, + [SubRemSubKeyNameLeft] = {"LEFT", "LLABEL"}, + [SubRemSubKeyNameRight] = {"RIGHT", "RLABEL"}, + [SubRemSubKeyNameOk] = {"OK", "OKLABEL"}, }; -bool subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { +static bool + subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { const char* preset_name = ""; if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { preset_name = "AM270"; @@ -45,7 +46,7 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() { sub_preset->protocaol_name = furi_string_alloc(); sub_preset->label = furi_string_alloc_set_str("N/A"); - sub_preset->type = SubRemSubKeyTypeNoData; + sub_preset->type = SubGhzProtocolTypeUnknown; return sub_preset; } @@ -61,7 +62,7 @@ void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { free(sub_preset); } -void subrem_subs_file_preset_reset(SubRemSubFilePreset* sub_preset) { +static void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { furi_assert(sub_preset); furi_string_set_str(sub_preset->label, "N/A"); @@ -71,43 +72,45 @@ void subrem_subs_file_preset_reset(SubRemSubFilePreset* sub_preset) { Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); stream_clean(fff_data_stream); - sub_preset->type = SubRemSubKeyTypeNoData; + sub_preset->type = SubGhzProtocolTypeUnknown; } -void subrem_sub_file_presets_reset(SubGhzRemoteApp* app) { +void subrem_map_preset_reset(SubGhzRemoteApp* app) { furi_assert(app); - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { - subrem_subs_file_preset_reset(app->subs_preset[i]); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + subrem_sub_file_preset_reset(app->subs_preset[i]); } } -static bool subrem_sub_file_presets_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { +static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); bool ret = false; - - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + SubRemSubFilePreset* sub_preset; + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = app->subs_preset[i]; if(!flipper_format_read_string( - fff_data_file, map_file_labels[i][0], app->subs_preset[i]->file_path)) { + fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { +#if FURO_LOG FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); - app->subs_preset[i]->type = SubRemSubKeyTypeNoData; - //continue; +#endif + sub_preset->type = SubGhzProtocolTypeUnknown; } else if(!flipper_format_rewind(fff_data_file)) { // Rewind error - //continue; } else if(!flipper_format_read_string( - fff_data_file, map_file_labels[i][1], app->subs_preset[i]->label)) { + fff_data_file, map_file_labels[i][1], sub_preset->label)) { +#if FURO_LOG FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); - furi_string_set_str(app->subs_preset[i]->label, "N/A"); +#endif + furi_string_set_str(sub_preset->label, + "N/A"); // TODO: Standart name or part of name } else { FURI_LOG_I( TAG, - // "Loaded %s key \r\nLabel %s file %s", - "Loaded %s key: %s %s", + "%-5s: %s %s", map_file_labels[i][0], - furi_string_get_cstr(app->subs_preset[i]->label), - furi_string_get_cstr(app->subs_preset[i]->file_path)); - app->subs_preset[i]->type = SubRemSubKeyTypeHaveFileName; // TODO: + furi_string_get_cstr(sub_preset->label), + furi_string_get_cstr(sub_preset->file_path)); ret = true; } flipper_format_rewind(fff_data_file); @@ -115,11 +118,20 @@ static bool subrem_sub_file_presets_load(SubGhzRemoteApp* app, FlipperFormat* ff return ret; } -bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { +bool subghz_tx_start_sub( + SubGhzRemoteApp* app, + SubRemSubFilePreset* sub_preset, + SubGhzProtocolEncoderRAWCallbackEnd callback) { furi_assert(app); furi_assert(sub_preset); bool ret = false; + subghz_tx_stop_sub(app, true); + + if(sub_preset->type == SubGhzProtocolTypeUnknown) { + return false; + } + FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); do { @@ -152,19 +164,27 @@ bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) break; } + if(sub_preset->type == SubGhzProtocolTypeRAW) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( + app->transmitter), + callback, + app); + } + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); ret = true; } } while(false); - // ret = false; // TODO: + app->tx_running = ret; // TODO: + return ret; } -void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { +static void subghz_tx_stop(SubGhzRemoteApp* app) { furi_assert(app); - furi_assert(sub_preset); //Stop TX furi_hal_subghz_stop_async_tx(); @@ -172,29 +192,46 @@ void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { subghz_transmitter_stop(app->transmitter); subghz_transmitter_free(app->transmitter); furi_hal_subghz_idle(); +} + +bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { + furi_assert(app); + + if(forced || (app->subs_preset[app->chusen_sub]->type != SubGhzProtocolTypeRAW)) { + // SubRemSubKeyTypeRawKey)) { + if(app->tx_running) { + subghz_tx_stop(app); + app->tx_running = false; + return true; + } + } + + return false; + + // SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; // TODO: need saving logic } -static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { +static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; bool ret = false; + bool sub_preset_loaded = false; SubRemSubFilePreset* sub_preset; - for(uint8_t i = 0; i < SUBREM_MAX_SUB_KEY_COUNT; i++) { + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { sub_preset = app->subs_preset[i]; - if(sub_preset->type == SubRemSubKeyTypeNoData) { + sub_preset_loaded = false; + if(furi_string_empty(sub_preset->file_path)) { + // FURI_LOG_I(TAG, "Empty file path"); continue; } do { if(!flipper_format_file_open_existing( fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { - FURI_LOG_E( - TAG, - "Error open file %s", - furi_string_get_cstr(sub_preset->file_path)); // TODO: warning + FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); break; } @@ -213,9 +250,9 @@ static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_da //Load frequency if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - FURI_LOG_W(TAG, "Cannot read frequency. Defaulting to 433.92 MHz"); - sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency( - app->setting); // TODO: Get default from settings + FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); + sub_preset->freq_preset.frequency = + subghz_setting_get_default_frequency(app->setting); } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { FURI_LOG_E(TAG, "This frequency can only be used for RX"); break; @@ -246,7 +283,6 @@ static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_da //if RAW subghz_protocol_raw_gen_fff_data( fff_data, furi_string_get_cstr(sub_preset->file_path)); - sub_preset->type = SubRemSubKeyTypeRawKey; } else { stream_copy_full( flipper_format_get_raw_stream(fff_data_file), @@ -262,70 +298,82 @@ static bool subrem_sub_presets_check(SubGhzRemoteApp* app, FlipperFormat* fff_da if(!protocol) { FURI_LOG_E(TAG, "Protocol not found"); break; - } else if(protocol->flag & SubGhzProtocolFlag_Send) { // FIXME: - - if(protocol->type == SubGhzProtocolTypeStatic) { - sub_preset->type = SubRemSubKeyTypeStaticKey; - } else if(protocol->type == SubGhzProtocolTypeDynamic) { - sub_preset->type = SubRemSubKeyTypeDynamicKey; - } else if(protocol->type == SubGhzProtocolTypeRAW) { - sub_preset->type = SubRemSubKeyTypeRawKey; - // } else if(protocol->type == SubGhzProtocolTypeBinRAW) { // TODO: BINRAW + } else if(protocol->flag & SubGhzProtocolFlag_Send) { + if((protocol->type == SubGhzProtocolTypeStatic) || + (protocol->type == SubGhzProtocolTypeDynamic) || + // (protocol->type == SubGhzProtocolTypeBinRAW) || // TODO: BINRAW + (protocol->type == SubGhzProtocolTypeRAW)) { + sub_preset->type = protocol->type; } else { FURI_LOG_E(TAG, "Unsuported Protocol"); break; } furi_string_set(sub_preset->protocaol_name, temp_str); - } // TODO: check dynamic and protocol found + } else { + FURI_LOG_E(TAG, "Protocol does not support transmission"); + } + sub_preset_loaded = true; ret |= true; - - if(ret) { - FURI_LOG_I(TAG, "Protocol Loaded"); - } +#if FURI_DEBUG + FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); +#endif } while(false); + // TODO: + // Load file state logic + // Label depending on the state + + if(!sub_preset_loaded) { + furi_string_set_str(sub_preset->label, "N/A"); + } + flipper_format_file_close(fff_data_file); } furi_string_free(temp_str); - //ret = false; // TODO: return ret; } bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { furi_assert(app); furi_assert(file_path); - // TODO: drop furi log - FURI_LOG_I(TAG, "Load Map File Start"); // drop +#if FURI_DEBUG + FURI_LOG_I(TAG, "Load Map File Start"); +#endif Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); bool ret = false; - FURI_LOG_I(TAG, "Open Map File.."); // drop - - subrem_sub_file_presets_reset(app); +#if FURI_DEBUG + FURI_LOG_I(TAG, "Open Map File.."); +#endif + subrem_map_preset_reset(app); if(!flipper_format_file_open_existing(fff_data_file, file_path)) { FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); } else { - if(!subrem_sub_file_presets_load(app, fff_data_file)) { - // TODO: error popup or return error type - FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); + if(!subrem_map_preset_load(app, fff_data_file)) { + FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); + // ret = // error for popup } else if( (flipper_format_file_close(fff_data_file)) && - (subrem_sub_presets_check(app, fff_data_file))) { + (subrem_map_preset_check(app, fff_data_file))) { FURI_LOG_I(TAG, "Load Map File Seccesful"); ret = true; } } + // TODO: Pop for error or return error type + if(!ret) { + FURI_LOG_E(TAG, "Broken Map File"); + } + flipper_format_file_close(fff_data_file); flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); - //ret = false; // TODO: return ret; } @@ -344,7 +392,6 @@ bool subrem_load_from_file(SubGhzRemoteApp* app) { if(res) { res = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); - // FIXME res = subghz_key_load(app, furi_string_get_cstr(app->file_path), true); } furi_string_free(file_path); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index d954eca023..8941f1401f 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -1,12 +1,12 @@ #pragma once #include "helpers/subrem_types.h" +#include // TODO: -#include "views/transmitter.h" +#include "views/remote.h" #include "scenes/subrem_scene.h" -#include // TODO: #include #include #include @@ -18,21 +18,16 @@ #include #include +#include + #include #include #include #include // FIXME: -// #include "views/subghz_remote_view_programmer.h" -// #include "views/subghz_remote_view_reader.h" -// #include "views/subghz_remote_view_writer.h" -// #include "views/subghz_remote_view_chip_detect.h" - -#define SUBREM_APP_EXTENSION ".txt" -#define SUBREM_APP_FOLDER "/ext/subghz_remote" +#define SUBREM_APP_FOLDER ANY_PATH("subghz_remote") #define SUBGHZ_REMOTE_MAX_LEN_NAME 64 -#define SUBREM_MAX_SUB_KEY_COUNT (5U) typedef struct { uint32_t frequency; @@ -46,7 +41,7 @@ typedef struct { FuriString* file_path; FuriString* protocaol_name; FuriString* label; - SubRemSubKeyType type; + SubGhzProtocolType type; } SubRemSubFilePreset; SubRemSubFilePreset* subrem_sub_file_preset_alloc(); @@ -68,22 +63,25 @@ typedef struct { SubRemViewRemote* subrem_remote_view; - SubRemSubFilePreset* subs_preset[SUBREM_MAX_SUB_KEY_COUNT]; + SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; SubGhzSetting* setting; SubGhzEnvironment* environment; SubGhzReceiver* receiver; SubGhzTransmitter* transmitter; - // AvrIspProgrammerView* subghz_remote_programmer_view; - // AvrIspReaderView* subghz_remote_reader_view; - // AvrIspWriterView* subghz_remote_writer_view; - // AvrIspChipDetectView* subghz_remote_chip_detect_view; + bool tx_running; + + uint8_t chusen_sub; - // AvrIspError error; + // TODO: LoadFileError } SubGhzRemoteApp; bool subrem_load_from_file(SubGhzRemoteApp* app); -bool subghz_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); -void subghz_tx_stop_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); \ No newline at end of file +bool subghz_tx_start_sub( + SubGhzRemoteApp* app, + SubRemSubFilePreset* sub_preset, + SubGhzProtocolEncoderRAWCallbackEnd callback); + +bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/transmitter.c b/applications/external/subghz_remote_new/views/remote.c similarity index 67% rename from applications/external/subghz_remote_new/views/transmitter.c rename to applications/external/subghz_remote_new/views/remote.c index 6f43a14066..c631c76cc2 100644 --- a/applications/external/subghz_remote_new/views/transmitter.c +++ b/applications/external/subghz_remote_new/views/remote.c @@ -1,27 +1,18 @@ -#include "transmitter.h" +#include "remote.h" #include "../subghz_remote_app_i.h" #include #include #define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 16 + struct SubRemViewRemote { View* view; SubRemViewRemoteCallback callback; void* context; }; -// FIXME: drop -// static char* char_to_str(char* str, int i) { -// char* converted = malloc(sizeof(char) * i + 1); -// memcpy(converted, str, i); - -// converted[i] = '\0'; - -// return converted; -// } // TODO: model - typedef struct { // FuriString* up_label; // FuriString* down_label; @@ -35,6 +26,8 @@ typedef struct { char* right_label; char* ok_label; + SubRemViewRemoteState state; + uint8_t pressed_btn; // bool show_button; // FuriString* temp_button_id; @@ -70,12 +63,6 @@ void subrem_view_remote_add_data_to_show( strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - // model->up_label = char_to_str((char*)up_label, 16); - // model->down_label = char_to_str((char*)down_label, 16); - // model->left_label = char_to_str((char*)left_label, 16); - // model->right_label = char_to_str((char*)right_label, 16); - // model->ok_label = char_to_str((char*)ok_label, 16); - // furi_string_set(model->up_label, up_label); // furi_string_set(model->down_label, down_label); // furi_string_set(model->left_label, left_label); @@ -85,6 +72,23 @@ void subrem_view_remote_add_data_to_show( true); } +void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn) { + furi_assert(subrem_view_remote); + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = presed_btn; }, + true); +} + +void subrem_view_remote_set_state( + SubRemViewRemote* subrem_view_remote, + SubRemViewRemoteState state) { + furi_assert(subrem_view_remote); + with_view_model( + subrem_view_remote->view, SubRemViewRemoteModel * model, { model->state = state; }, true); +} + void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); @@ -126,29 +130,44 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); //Status text and indicator - // canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, app->send_status); + + //canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, model->state); canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); - switch(model->pressed_btn) { - case 0: - break; - case 1: - canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9); - break; - case 2: - canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); - break; - case 3: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); - break; - case 4: - canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); - break; - case 5: - canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); - break; - } + if(model->state == SubRemViewRemoteStateIdle) { + canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); + } else { + switch(model->state) { + case SubRemViewRemoteStateSending: + canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Send"); + break; + case SubRemViewRemoteStateLoading: + canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Load"); + break; + default: + canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); + break; + } + + switch(model->pressed_btn) { + case SubRemSubKeyNameUp: + canvas_draw_icon(canvas, 116, 17, &I_Pin_arrow_up_7x9); + break; + case SubRemSubKeyNameDown: + canvas_draw_icon_ex(canvas, 116, 17, &I_Pin_arrow_up_7x9, IconRotation180); + break; + case SubRemSubKeyNameLeft: + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation270); + break; + case SubRemSubKeyNameRight: + canvas_draw_icon_ex(canvas, 115, 18, &I_Pin_arrow_up_7x9, IconRotation90); + break; + case SubRemSubKeyNameOk: + canvas_draw_icon(canvas, 116, 18, &I_Pin_star_7x7); + break; + } + } //Repeat indicator //canvas_draw_str_aligned(canvas, 125, 40, AlignRight, AlignBottom, "Repeat:"); //canvas_draw_icon(canvas, 115, 39, &I_SubGHzRemote_Repeat_12x14); @@ -160,6 +179,7 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { SubRemViewRemote* subrem_view_remote = context; if(event->key == InputKeyBack && event->type == InputTypeLong) { + // TODO: remove reset Debug with_view_model( subrem_view_remote->view, SubRemViewRemoteModel * model, @@ -177,28 +197,47 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { // furi_string_reset(model->ok_label); }, false); - return false; - } else if(event->key == InputKeyUp) { - if(event->type == InputTypePress) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 1; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); - return true; - } else if(event->type == InputTypeRelease) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = 0; }, - true); - subrem_view_remote->callback( - SubRemCustomEventViewRemoteStop, subrem_view_remote->context); - return true; - } + subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyBack && event->type == InputTypeShort) { + with_view_model( + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { model->pressed_btn = 0; }, + true); + subrem_view_remote->callback( + SubRemCustomEventViewRemoteForcedStop, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyBack) { + return true; } + // BACK button processing end + + if(event->key == InputKeyUp && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartUP, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyDown && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartDOWN, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyLeft && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartLEFT, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyRight && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartRIGHT, subrem_view_remote->context); + return true; + } else if(event->key == InputKeyOk && event->type == InputTypePress) { + subrem_view_remote->callback( + SubRemCustomEventViewRemoteStartOK, subrem_view_remote->context); + return true; + } else if(event->type == InputTypeRelease) { + subrem_view_remote->callback(SubRemCustomEventViewRemoteStop, subrem_view_remote->context); + return true; + } + return true; } @@ -227,6 +266,8 @@ SubRemViewRemote* subrem_view_remote_alloc() { subrem_view_remote->view, SubRemViewRemoteModel * model, { + model->state = SubRemViewRemoteStateIdle; + model->up_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); model->down_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); model->left_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); diff --git a/applications/external/subghz_remote_new/views/transmitter.h b/applications/external/subghz_remote_new/views/remote.h similarity index 66% rename from applications/external/subghz_remote_new/views/transmitter.h rename to applications/external/subghz_remote_new/views/remote.h index a324d09ece..76121cf8a0 100644 --- a/applications/external/subghz_remote_new/views/transmitter.h +++ b/applications/external/subghz_remote_new/views/remote.h @@ -3,6 +3,12 @@ #include #include "../helpers/subrem_custom_event.h" +typedef enum { + SubRemViewRemoteStateIdle, + SubRemViewRemoteStateLoading, + SubRemViewRemoteStateSending, +} SubRemViewRemoteState; + typedef struct SubRemViewRemote SubRemViewRemote; typedef void (*SubRemViewRemoteCallback)(SubRemCustomEvent event, void* context); @@ -24,4 +30,9 @@ void subrem_view_remote_add_data_to_show( const char* down_label, const char* left_label, const char* right_label, - const char* ok_label); \ No newline at end of file + const char* ok_label); + +void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn); +void subrem_view_remote_set_state( + SubRemViewRemote* subrem_view_remote, + SubRemViewRemoteState state); \ No newline at end of file From 9da2e4fae876ea1c83a24e38fac389e3c68e7efa Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Thu, 18 May 2023 12:01:17 +0300 Subject: [PATCH 07/23] add save dynamic --- .../subghz_remote_new/application.fam | 1 + .../scenes/subrem_scene_openmapfile.c | 20 +++++++- .../subghz_remote_new/subghz_remote_app_i.c | 46 ++++++++++++++++++- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam index 4f633b9610..389f02b61a 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_new/application.fam @@ -7,6 +7,7 @@ App( "gui", "dialogs", ], + cdefines=["SUBREM_LIGHT"], icon="A_SubGHzRemote_14", stack_size=4 * 1024, order=12, diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index 504bfee2ec..cb93134ab6 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -7,7 +7,25 @@ void subrem_scene_openmapfile_on_enter(void* context) { scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); } else { // TODO: Map Preset Reset - scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SubRemSceneStart); + + // #if SUBREM_LIGHT + // dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); + // #else + DialogMessage* message = dialog_message_alloc(); + + dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter); + dialog_message_set_text(message, "Can't load\nMap file", 64, 32, AlignCenter, AlignCenter); + dialog_message_set_buttons(message, "Back", NULL, NULL); + dialog_message_show(app->dialogs, message); + + dialog_message_free(message); + // #endif + + if(!scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, SubRemSceneStart)) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } } } diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index dac0d15b73..da3f317174 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -118,6 +118,43 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data return ret; } +bool subghz_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { + // furi_assert(subghz); + furi_assert(flipper_format); + furi_assert(dev_file_name); + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); + + bool saved = false; + FuriString* file_dir = furi_string_alloc(); + + path_extract_dirname(dev_file_name, file_dir); + do { + //removing additional fields + flipper_format_delete_key(flipper_format, "Repeat"); + //flipper_format_delete_key(flipper_format, "Manufacture"); + + // Create subghz folder directory if necessary + // if(!storage_simply_mkdir(storage, furi_string_get_cstr(file_dir))) { + // dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); + // break; + // } + + if(!storage_simply_remove(storage, dev_file_name)) { + break; + } + //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); + stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + + saved = true; + } while(0); + furi_string_free(file_dir); + furi_record_close(RECORD_STORAGE); + return saved; +} + bool subghz_tx_start_sub( SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset, @@ -196,11 +233,18 @@ static void subghz_tx_stop(SubGhzRemoteApp* app) { bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { furi_assert(app); + SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; - if(forced || (app->subs_preset[app->chusen_sub]->type != SubGhzProtocolTypeRAW)) { + if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { // SubRemSubKeyTypeRawKey)) { if(app->tx_running) { subghz_tx_stop(app); + + if(sub_preset->type == SubGhzProtocolTypeDynamic) { + subghz_save_protocol_to_file( + sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); + } + app->tx_running = false; return true; } From 0b25cc5a5c9777085bc93bddb1d66a29e15a9f44 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 19 May 2023 21:06:03 +0300 Subject: [PATCH 08/23] fap --- .../subghz_remote_new/application.fam | 13 +- .../helpers/subrem_custom_event.h | 6 +- .../subghz_remote_new/helpers/subrem_types.h | 18 +- .../scenes/subrem_scene_openmapfile.c | 21 +- .../scenes/subrem_scene_remote.c | 34 +- .../scenes/subrem_scene_start.c | 1 - .../subghz_remote_new/subghz_remote_app.c | 39 +-- .../subghz_remote_new/subghz_remote_app_i.c | 66 ++-- .../subghz_remote_new/subghz_remote_app_i.h | 23 +- .../external/subghz_remote_new/views/remote.c | 38 +-- .../views/transmitter_old.txt | 317 ------------------ 11 files changed, 92 insertions(+), 484 deletions(-) delete mode 100644 applications/external/subghz_remote_new/views/transmitter_old.txt diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam index 389f02b61a..09eb7e64e8 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_new/application.fam @@ -1,16 +1,19 @@ App( - appid="subghz_remote_new", - name="SubRem new", - apptype=FlipperAppType.EXTERNAL, + appid="subrem_remote_fap", + name="Sub-GHz Remote", + apptype=FlipperAppType.APP, entry_point="subghz_remote_app", + cdefines=[ + "APP_SUBGHZREMOTE", + "SUBREM_LIGHT", + ], requires=[ "gui", "dialogs", ], - cdefines=["SUBREM_LIGHT"], icon="A_SubGHzRemote_14", stack_size=4 * 1024, - order=12, + order=50, fap_category="Debug", fap_icon_assets="icons", ) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index 90d60f0269..46ab8ad547 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -1,13 +1,9 @@ #pragma once typedef enum { - // SubRemCustomEventManagerNoSet = 0, - // SubRemCustomEventManagerSet, - // SubRemCustomEventManagerSetRAW, - //SubmenuIndex SubmenuIndexSubRemOpenMapFile, - SubmenuIndexSubRemRemoteView, // TODO: temp debug + SubmenuIndexSubRemRemoteView, SubmenuIndexSubRemAbout, //SubRemCustomEvent diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h index 0bf31e6a4a..1b99aac6d2 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_types.h +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -3,6 +3,7 @@ #include #include +// TODO: File version/type logic // #define SUBREM_APP_APP_FILE_VERSION 1 // #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file" #define SUBREM_APP_EXTENSION ".txt" @@ -25,16 +26,7 @@ typedef enum { } SubRemViewID; typedef enum { - // Loadin State - SubRemSubKeyTypeNoData = 0, - // SubRemSubKeyTypeHaveFileName, - - // Key Type - SubRemSubKeyTypeStaticKey = 100, - SubRemSubKeyTypeDynamicKey, - SubRemSubKeyTypeRawKey, -} SubRemSubKeyType; // TODO: depricated - -// typedef enum { -// -// } SubRemLoadMapState; \ No newline at end of file + SubRemLoadMapStateBack = 0, + SubRemLoadMapStateError, + SubRemLoadMapStateOK, +} SubRemLoadMapState; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index cb93134ab6..3391845e12 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -2,15 +2,12 @@ void subrem_scene_openmapfile_on_enter(void* context) { SubGhzRemoteApp* app = context; + SubRemLoadMapState load_state = subrem_load_from_file(app); - if(subrem_load_from_file(app)) { - scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); - } else { - // TODO: Map Preset Reset - - // #if SUBREM_LIGHT - // dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); - // #else + if(load_state == SubRemLoadMapStateError) { +#ifdef SUBREM_LIGHT + dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); +#else DialogMessage* message = dialog_message_alloc(); dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter); @@ -19,8 +16,12 @@ void subrem_scene_openmapfile_on_enter(void* context) { dialog_message_show(app->dialogs, message); dialog_message_free(message); - // #endif - +#endif + } + if(load_state == SubRemLoadMapStateOK) { + scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); + } else { + // TODO: Map Preset Reset if(!scene_manager_search_and_switch_to_previous_scene( app->scene_manager, SubRemSceneStart)) { scene_manager_stop(app->scene_manager); diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c index a04399cd3f..c245832336 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c @@ -5,12 +5,6 @@ #define TAG "SubRemScenRemote" -// TODO: -// #include -// #include - -// #include - void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { furi_assert(context); SubGhzRemoteApp* app = context; @@ -59,16 +53,10 @@ static bool subrem_scene_remote_update_data_show(void* context) { void subrem_scene_remote_on_enter(void* context) { SubGhzRemoteApp* app = context; - // TODO: init view data + subrem_scene_remote_update_data_show(app); - if(!subrem_scene_remote_update_data_show(app)) { - // view_dispatcher_send_custom_event( - // app->view_dispatcher, SubGhzCustomEventViewTransmitterError); - } subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app); - // TODO: notifications - // app->state_notifications = SubGhzNotificationStateIDLE; view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDRemote); } @@ -92,10 +80,10 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { event.event == SubRemCustomEventViewRemoteStartRIGHT || event.event == SubRemCustomEventViewRemoteStartOK) { // Start sending sub - subghz_tx_stop_sub(app, true); + subrem_tx_stop_sub(app, true); app->chusen_sub = subrem_scene_remote_event_to_index(event.event); subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading); - if(subghz_tx_start_sub( + if(subrem_tx_start_sub( app, app->subs_preset[app->chusen_sub], subrem_scene_remote_raw_callback_end_tx)) { @@ -105,17 +93,18 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { notification_message(app->notifications, &sequence_blink_start_magenta); } else { subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + notification_message(app->notifications, &sequence_blink_stop); } return true; } else if(event.event == SubRemCustomEventViewRemoteForcedStop) { - subghz_tx_stop_sub(app, true); + subrem_tx_stop_sub(app, true); subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); notification_message(app->notifications, &sequence_blink_stop); return true; } else if(event.event == SubRemCustomEventViewRemoteStop) { - if(subghz_tx_stop_sub(app, false)) { + if(subrem_tx_stop_sub(app, false)) { subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); @@ -132,19 +121,10 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { void subrem_scene_remote_on_exit(void* context) { SubGhzRemoteApp* app = context; - subghz_tx_stop_sub(app, true); + subrem_tx_stop_sub(app, true); subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); notification_message(app->notifications, &sequence_blink_stop); - - // TODO: notifications and reset KL - - // keeloq_reset_mfname(); - // keeloq_reset_kl_type(); - // keeloq_reset_original_btn(); - // subghz_custom_btns_reset(); - // star_line_reset_mfname(); - // star_line_reset_kl_type(); } diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c index 75328ab8a7..962eda54ca 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -48,7 +48,6 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexSubRemOpenMapFile) { - //scene_manager_set_scene_state(app->scene_manager, SubRemSceneStart, event.event); scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); consumed = true; } diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index ad6fe13fbc..0b3f645ab8 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -34,16 +34,8 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { furi_hal_power_suppress_charge_enter(); - // // Enable 5v power, multiple attempts to avoid issues with power chip protection false triggering - // uint8_t attempts = 0; - // while(!furi_hal_power_is_otg_enabled() && attempts++ < 5) { - // furi_hal_power_enable_otg(); - // furi_delay_ms(10); - // } - app->file_path = furi_string_alloc(); - furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); - //app->error = SubGhzRemoteErrorNoError; + furi_string_set(app->file_path, SUBREM_APP_FOLDER); // GUI app->gui = furi_record_open(RECORD_GUI); @@ -71,19 +63,6 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { view_dispatcher_add_view( app->view_dispatcher, SubRemViewSubmenu, submenu_get_view(app->submenu)); - // Widget - app->widget = widget_alloc(); - view_dispatcher_add_view(app->view_dispatcher, SubRemViewWidget, widget_get_view(app->widget)); - - // Text Input - app->text_input = text_input_alloc(); - view_dispatcher_add_view( - app->view_dispatcher, SubRemViewTextInput, text_input_get_view(app->text_input)); - - // Popup - app->popup = popup_alloc(); - view_dispatcher_add_view(app->view_dispatcher, SubRemViewPopup, popup_get_view(app->popup)); - //Dialog app->dialogs = furi_record_open(RECORD_DIALOGS); @@ -118,7 +97,11 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->tx_running = false; +#ifdef SUBREM_LIGHT + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); +#else scene_manager_next_scene(app->scene_manager, SubRemSceneStart); +#endif return app; } @@ -137,18 +120,6 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { view_dispatcher_remove_view(app->view_dispatcher, SubRemViewSubmenu); submenu_free(app->submenu); - // Widget - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewWidget); - widget_free(app->widget); - - // TextInput - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewTextInput); - text_input_free(app->text_input); - - // Popup - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewPopup); - popup_free(app->popup); - //Dialog furi_record_close(RECORD_DIALOGS); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index da3f317174..2437dd2baa 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -2,9 +2,13 @@ #include #include -#include #include +// #include +// #include + +#include + #define TAG "SubGhzRemote" static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { @@ -91,7 +95,7 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data sub_preset = app->subs_preset[i]; if(!flipper_format_read_string( fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { -#if FURO_LOG +#if FURI_DEBUG FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); #endif sub_preset->type = SubGhzProtocolTypeUnknown; @@ -99,11 +103,10 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data // Rewind error } else if(!flipper_format_read_string( fff_data_file, map_file_labels[i][1], sub_preset->label)) { -#if FURO_LOG +#if FURI_DEBUG FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); #endif - furi_string_set_str(sub_preset->label, - "N/A"); // TODO: Standart name or part of name + path_extract_filename(sub_preset->file_path, sub_preset->label, true); } else { FURI_LOG_I( TAG, @@ -118,8 +121,7 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data return ret; } -bool subghz_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { - // furi_assert(subghz); +bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { furi_assert(flipper_format); furi_assert(dev_file_name); @@ -135,12 +137,6 @@ bool subghz_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev flipper_format_delete_key(flipper_format, "Repeat"); //flipper_format_delete_key(flipper_format, "Manufacture"); - // Create subghz folder directory if necessary - // if(!storage_simply_mkdir(storage, furi_string_get_cstr(file_dir))) { - // dialog_message_show_storage_error(subghz->dialogs, "Cannot create\nfolder"); - // break; - // } - if(!storage_simply_remove(storage, dev_file_name)) { break; } @@ -155,7 +151,7 @@ bool subghz_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev return saved; } -bool subghz_tx_start_sub( +bool subrem_tx_start_sub( SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset, SubGhzProtocolEncoderRAWCallbackEnd callback) { @@ -163,7 +159,7 @@ bool subghz_tx_start_sub( furi_assert(sub_preset); bool ret = false; - subghz_tx_stop_sub(app, true); + subrem_tx_stop_sub(app, true); if(sub_preset->type == SubGhzProtocolTypeUnknown) { return false; @@ -171,8 +167,12 @@ bool subghz_tx_start_sub( FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); + // subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); + // keeloq_reset_original_btn(); + // subghz_custom_btns_reset(); + do { - flipper_format_rewind(sub_preset->fff_data); // FIXME: + flipper_format_rewind(sub_preset->fff_data); // app->transmitter = subghz_transmitter_alloc_init( app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); @@ -215,7 +215,7 @@ bool subghz_tx_start_sub( } } while(false); - app->tx_running = ret; // TODO: + app->tx_running = ret; return ret; } @@ -231,7 +231,7 @@ static void subghz_tx_stop(SubGhzRemoteApp* app) { furi_hal_subghz_idle(); } -bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { +bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { furi_assert(app); SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; @@ -241,8 +241,15 @@ bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { subghz_tx_stop(app); if(sub_preset->type == SubGhzProtocolTypeDynamic) { - subghz_save_protocol_to_file( + subrem_save_protocol_to_file( sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); + + // keeloq_reset_mfname(); + // keeloq_reset_kl_type(); + // keeloq_reset_original_btn(); + // subghz_custom_btns_reset(); + // star_line_reset_mfname(); + // star_line_reset_kl_type(); } app->tx_running = false; @@ -251,10 +258,6 @@ bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { } return false; - - // SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; - - // TODO: need saving logic } static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { @@ -408,7 +411,7 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { } } - // TODO: Pop for error or return error type + // TODO: Popup for error or return error type if(!ret) { FURI_LOG_E(TAG, "Broken Map File"); } @@ -421,24 +424,25 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { return ret; } -bool subrem_load_from_file(SubGhzRemoteApp* app) { +SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { furi_assert(app); FuriString* file_path = furi_string_alloc(); + SubRemLoadMapState ret = SubRemLoadMapStateBack; DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_sub1_10px); browser_options.base_path = SUBREM_APP_FOLDER; // Input events and views are managed by file_select - bool res = - dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); - - if(res) { - res = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); + if(!dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) { + } else if(subrem_map_file_load(app, furi_string_get_cstr(app->file_path))) { + ret = SubRemLoadMapStateOK; + } else { + ret = SubRemLoadMapStateError; } furi_string_free(file_path); - return res; + return ret; } diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 8941f1401f..0cff3898ac 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -1,7 +1,9 @@ #pragma once #include "helpers/subrem_types.h" -#include // TODO: +#include + +// #include #include "views/remote.h" @@ -18,16 +20,16 @@ #include #include +#include + #include #include #include #include -#include // FIXME: - -#define SUBREM_APP_FOLDER ANY_PATH("subghz_remote") -#define SUBGHZ_REMOTE_MAX_LEN_NAME 64 +#define SUBREM_APP_FOLDER EXT_PATH("subghz_remote") +#define SUBREM_MAX_LEN_NAME 64 typedef struct { uint32_t frequency; @@ -54,12 +56,9 @@ typedef struct { SceneManager* scene_manager; NotificationApp* notifications; DialogsApp* dialogs; - Popup* popup; Submenu* submenu; - Widget* widget; - TextInput* text_input; FuriString* file_path; - char file_name_tmp[SUBGHZ_REMOTE_MAX_LEN_NAME]; + char file_name_tmp[SUBREM_MAX_LEN_NAME]; SubRemViewRemote* subrem_remote_view; @@ -77,11 +76,11 @@ typedef struct { // TODO: LoadFileError } SubGhzRemoteApp; -bool subrem_load_from_file(SubGhzRemoteApp* app); +SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); -bool subghz_tx_start_sub( +bool subrem_tx_start_sub( SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset, SubGhzProtocolEncoderRAWCallbackEnd callback); -bool subghz_tx_stop_sub(SubGhzRemoteApp* app, bool forced); \ No newline at end of file +bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/remote.c b/applications/external/subghz_remote_new/views/remote.c index c631c76cc2..85c63568ea 100644 --- a/applications/external/subghz_remote_new/views/remote.c +++ b/applications/external/subghz_remote_new/views/remote.c @@ -29,9 +29,6 @@ typedef struct { SubRemViewRemoteState state; uint8_t pressed_btn; - // bool show_button; - // FuriString* temp_button_id; - // bool draw_temp_button; } SubRemViewRemoteModel; void subrem_view_remote_set_callback( @@ -93,18 +90,8 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); - //map found, draw all the things canvas_clear(canvas); - //canvas_set_font(canvas, FontPrimary); - //canvas_draw_str(canvas, 0, 10, "U: "); - //canvas_draw_str(canvas, 0, 20, "L: "); - //canvas_draw_str(canvas, 0, 30, "R: "); - //canvas_draw_str(canvas, 0, 40, "D: "); - //canvas_draw_str(canvas, 0, 50, "Ok: "); - - //PNGs are located in assets/icons/SubGHzRemote before compilation - //Icons for Labels //canvas_draw_icon(canvas, 0, 0, &I_SubGHzRemote_LeftAlignedButtons_9x64); canvas_draw_icon(canvas, 1, 5, &I_ButtonUp_7x4); @@ -121,6 +108,7 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_str(canvas, 10, 30, model->left_label); canvas_draw_str(canvas, 10, 40, model->right_label); canvas_draw_str(canvas, 10, 50, model->ok_label); + // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); @@ -130,9 +118,6 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); //Status text and indicator - - //canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, model->state); - canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); if(model->state == SubRemViewRemoteStateIdle) { @@ -146,7 +131,9 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Load"); break; default: - canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); +#if FURI_DEBUG + canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Wrong_state"); +#endif break; } @@ -179,7 +166,6 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { SubRemViewRemote* subrem_view_remote = context; if(event->key == InputKeyBack && event->type == InputTypeLong) { - // TODO: remove reset Debug with_view_model( subrem_view_remote->view, SubRemViewRemoteModel * model, @@ -189,12 +175,6 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { strcpy(model->left_label, "N/A"); strcpy(model->right_label, "N/A"); strcpy(model->ok_label, "N/A"); - - // furi_string_reset(model->up_label); - // furi_string_reset(model->down_label); - // furi_string_reset(model->left_label); - // furi_string_reset(model->right_label); - // furi_string_reset(model->ok_label); }, false); subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context); @@ -280,11 +260,11 @@ SubRemViewRemote* subrem_view_remote_alloc() { strcpy(model->right_label, "N/A"); strcpy(model->ok_label, "N/A"); - // model->up_label = furi_string_alloc(); - // model->down_label = furi_string_alloc(); - // model->left_label = furi_string_alloc(); - // model->right_label = furi_string_alloc(); - // model->ok_label = furi_string_alloc(); + // model->up_label = furi_string_alloc_set_str("N/A"); + // model->down_label = furi_string_alloc_set_str("N/A"); + // model->left_label = furi_string_alloc_set_str("N/A"); + // model->right_label = furi_string_alloc_set_str("N/A"); + // model->ok_label = furi_string_alloc_set_str("N/A"); model->pressed_btn = 0; }, diff --git a/applications/external/subghz_remote_new/views/transmitter_old.txt b/applications/external/subghz_remote_new/views/transmitter_old.txt deleted file mode 100644 index ea2dc2f627..0000000000 --- a/applications/external/subghz_remote_new/views/transmitter_old.txt +++ /dev/null @@ -1,317 +0,0 @@ -#include "transmitter.h" -#include "../subghz_remote_app_i.h" - -#include -#include - -#include - -struct SubGhzRemoteViewRemote { - View* view; - SubGhzRemoteViewRemoteCallback callback; - void* context; -}; - -typedef struct { - FuriString* frequency_str; - FuriString* preset_str; - FuriString* key_str; - // bool show_button; - // FuriString* temp_button_id; - // bool draw_temp_button; -} SubGhzRemoteViewRemoteModel; - -void subghz_view_transmitter_set_callback( - SubGhzRemoteViewRemote* subghz_transmitter, - SubGhzRemoteViewRemoteCallback callback, - void* context) { - furi_assert(subghz_transmitter); - - subghz_transmitter->callback = callback; - subghz_transmitter->context = context; -} - -void subghz_view_transmitter_add_data_to_show( - SubGhzRemoteViewRemote* subghz_transmitter, - const char* key_str, - const char* frequency_str, - const char* preset_str, - bool show_button) { - furi_assert(subghz_transmitter); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_set(model->key_str, key_str); - furi_string_set(model->frequency_str, frequency_str); - furi_string_set(model->preset_str, preset_str); - model->show_button = show_button; - }, - true); -} - -static void subghz_view_transmitter_button_right(Canvas* canvas, const char* str) { - const uint8_t button_height = 12; - 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 - 1, - &I_ButtonCenter_7x7); - canvas_draw_str( - canvas, x + horizontal_offset + icon_width_with_offset, y - vertical_offset, str); - canvas_invert_color(canvas); -} - -void subghz_view_transmitter_draw(Canvas* canvas, SubGhzRemoteViewRemoteModel* model) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - canvas_set_font(canvas, FontSecondary); - elements_multiline_text_aligned( - canvas, 0, 0, AlignLeft, AlignTop, furi_string_get_cstr(model->key_str)); - canvas_draw_str(canvas, 78, 7, furi_string_get_cstr(model->frequency_str)); - canvas_draw_str(canvas, 113, 7, furi_string_get_cstr(model->preset_str)); - - // if(model->draw_temp_button) { - // canvas_set_font(canvas, FontBatteryPercent); - // canvas_draw_str(canvas, 117, 40, furi_string_get_cstr(model->temp_button_id)); - // canvas_set_font(canvas, FontSecondary); - // } - - // if(model->show_button) { - // canvas_draw_str(canvas, 58, 62, furi_hal_subghz_get_radio_type() ? "R: Ext" : "R: Int"); - // subghz_view_transmitter_button_right(canvas, "Send"); - // } -} - -bool subghz_view_transmitter_input(InputEvent* event, void* context) { - furi_assert(context); - SubGhzRemoteViewRemote* subghz_transmitter = context; - bool can_be_sent = false; - - if(event->key == InputKeyBack && event->type == InputTypeShort) { - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->frequency_str); - furi_string_reset(model->preset_str); - furi_string_reset(model->key_str); - furi_string_reset(model->temp_button_id); - model->show_button = false; - model->draw_temp_button = false; - }, - false); - return false; - } - - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - if(model->show_button) { - can_be_sent = true; - } - }, - true); - - if(can_be_sent && event->key == InputKeyOk && event->type == InputTypePress) { - subghz_custom_btn_set(0); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->temp_button_id); - model->draw_temp_button = false; - }, - true); - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); - return true; - } else if(can_be_sent && event->key == InputKeyOk && event->type == InputTypeRelease) { - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); - return true; - } - - // Temp Buttons (UP) - if(can_be_sent && event->key == InputKeyUp && event->type == InputTypePress) { - subghz_custom_btn_set(1); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->temp_button_id); - if(subghz_custom_btn_get_original() != 0) { - if(subghz_custom_btn_get() == 1) { - furi_string_printf( - model->temp_button_id, "%01X", subghz_custom_btn_get_original()); - model->draw_temp_button = true; - } - } - }, - true); - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); - return true; - } else if(can_be_sent && event->key == InputKeyUp && event->type == InputTypeRelease) { - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); - return true; - } - // Down - if(can_be_sent && event->key == InputKeyDown && event->type == InputTypePress) { - subghz_custom_btn_set(2); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->temp_button_id); - if(subghz_custom_btn_get_original() != 0) { - if(subghz_custom_btn_get() == 2) { - furi_string_printf( - model->temp_button_id, "%01X", subghz_custom_btn_get_original()); - model->draw_temp_button = true; - } - } - }, - true); - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); - return true; - } else if(can_be_sent && event->key == InputKeyDown && event->type == InputTypeRelease) { - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); - return true; - } - // Left - if(can_be_sent && event->key == InputKeyLeft && event->type == InputTypePress) { - subghz_custom_btn_set(3); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->temp_button_id); - if(subghz_custom_btn_get_original() != 0) { - if(subghz_custom_btn_get() == 3) { - furi_string_printf( - model->temp_button_id, "%01X", subghz_custom_btn_get_original()); - model->draw_temp_button = true; - } - } - }, - true); - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); - return true; - } else if(can_be_sent && event->key == InputKeyLeft && event->type == InputTypeRelease) { - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); - return true; - } - // Right - if(can_be_sent && event->key == InputKeyRight && event->type == InputTypePress) { - subghz_custom_btn_set(4); - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_reset(model->temp_button_id); - if(subghz_custom_btn_get_original() != 0) { - if(subghz_custom_btn_get() == 4) { - furi_string_printf( - model->temp_button_id, "%01X", subghz_custom_btn_get_original()); - model->draw_temp_button = true; - } - } - }, - true); - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStart, subghz_transmitter->context); - return true; - } else if(can_be_sent && event->key == InputKeyRight && event->type == InputTypeRelease) { - subghz_transmitter->callback( - SubGhzCustomEventViewTransmitterSendStop, subghz_transmitter->context); - return true; - } - - return true; -} - -void subghz_view_transmitter_enter(void* context) { - furi_assert(context); -} - -void subghz_view_transmitter_exit(void* context) { - furi_assert(context); -} - -SubGhzRemoteViewRemote* subghz_view_transmitter_alloc() { - SubGhzRemoteViewRemote* subghz_transmitter = malloc(sizeof(SubGhzRemoteViewRemote)); - - // View allocation and configuration - subghz_transmitter->view = view_alloc(); - view_allocate_model( - subghz_transmitter->view, ViewModelTypeLocking, sizeof(SubGhzRemoteViewRemoteModel)); - view_set_context(subghz_transmitter->view, subghz_transmitter); - view_set_draw_callback( - subghz_transmitter->view, (ViewDrawCallback)subghz_view_transmitter_draw); - view_set_input_callback(subghz_transmitter->view, subghz_view_transmitter_input); - view_set_enter_callback(subghz_transmitter->view, subghz_view_transmitter_enter); - view_set_exit_callback(subghz_transmitter->view, subghz_view_transmitter_exit); - - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - model->frequency_str = furi_string_alloc(); - model->preset_str = furi_string_alloc(); - model->key_str = furi_string_alloc(); - model->temp_button_id = furi_string_alloc(); - }, - true); - return subghz_transmitter; -} - -void subghz_view_transmitter_free(SubGhzRemoteViewRemote* subghz_transmitter) { - furi_assert(subghz_transmitter); - - with_view_model( - subghz_transmitter->view, - SubGhzRemoteViewRemoteModel * model, - { - furi_string_free(model->frequency_str); - furi_string_free(model->preset_str); - furi_string_free(model->key_str); - furi_string_free(model->temp_button_id); - }, - true); - view_free(subghz_transmitter->view); - free(subghz_transmitter); -} - -View* subghz_view_transmitter_get_view(SubGhzRemoteViewRemote* subghz_transmitter) { - furi_assert(subghz_transmitter); - return subghz_transmitter->view; -} From 1f97e9be343724c0100c0e9bdd60461b88913d33 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 19 May 2023 21:21:36 +0300 Subject: [PATCH 09/23] fix repeat --- .../subghz_remote_new/application.fam | 2 +- .../subghz_remote_new/subghz_remote_app_i.c | 20 ++++++++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam index 09eb7e64e8..f2cdd25b07 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_new/application.fam @@ -1,7 +1,7 @@ App( appid="subrem_remote_fap", name="Sub-GHz Remote", - apptype=FlipperAppType.APP, + apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_app", cdefines=[ "APP_SUBGHZREMOTE", diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 2437dd2baa..18ebb05f6f 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -129,23 +129,31 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); bool saved = false; + uint32_t repeat = 200; FuriString* file_dir = furi_string_alloc(); path_extract_dirname(dev_file_name, file_dir); do { - //removing additional fields + // removing additional fields flipper_format_delete_key(flipper_format, "Repeat"); - //flipper_format_delete_key(flipper_format, "Manufacture"); + // flipper_format_delete_key(flipper_format, "Manufacture"); if(!storage_simply_remove(storage, dev_file_name)) { break; } + //ToDo check Write stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + saved = true; } while(0); + furi_string_free(file_dir); furi_record_close(RECORD_STORAGE); return saved; @@ -267,7 +275,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat bool ret = false; bool sub_preset_loaded = false; SubRemSubFilePreset* sub_preset; - + uint32_t repeat = 200; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { sub_preset = app->subs_preset[i]; sub_preset_loaded = false; @@ -275,6 +283,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat // FURI_LOG_I(TAG, "Empty file path"); continue; } + repeat = 200; do { if(!flipper_format_file_open_existing( fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { @@ -361,6 +370,11 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat FURI_LOG_E(TAG, "Protocol does not support transmission"); } + if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + sub_preset_loaded = true; ret |= true; #if FURI_DEBUG From e295c7aac250dda004f4a6f19a2d09232901d715 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 19 May 2023 22:59:43 +0300 Subject: [PATCH 10/23] Load states & fix label length --- .../subghz_remote_new/helpers/subrem_types.h | 15 +++++ .../scenes/subrem_scene_openmapfile.c | 2 +- .../scenes/subrem_scene_start.c | 6 +- .../subghz_remote_new/subghz_remote_app_i.c | 55 ++++++++++++------- .../subghz_remote_new/subghz_remote_app_i.h | 3 +- .../external/subghz_remote_new/views/remote.c | 2 +- 6 files changed, 57 insertions(+), 26 deletions(-) diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h index 1b99aac6d2..13b42897f6 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_types.h +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -25,8 +25,23 @@ typedef enum { SubRemViewIDRemote, } SubRemViewID; +typedef enum { + SubRemLoadSubStateNotSet, + SubRemLoadSubStatePreloaded, + SubRemLoadSubStateError, + SubRemLoadSubStateErrorNoFile, + SubRemLoadSubStateErrorFreq, + SubRemLoadSubStateErrorMod, + SubRemLoadSubStateErrorProtocol, + SubRemLoadSubStateOK, +} SubRemLoadSubState; + typedef enum { SubRemLoadMapStateBack = 0, SubRemLoadMapStateError, + SubRemLoadMapStateErrorOpenError, + SubRemLoadMapStateErrorStorage, + SubRemLoadMapStateErrorBrokenFile, + SubRemLoadMapStateNotAllOK, SubRemLoadMapStateOK, } SubRemLoadMapState; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index 3391845e12..ea5c14a0a5 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -18,7 +18,7 @@ void subrem_scene_openmapfile_on_enter(void* context) { dialog_message_free(message); #endif } - if(load_state == SubRemLoadMapStateOK) { + if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) { scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); } else { // TODO: Map Preset Reset diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c index 962eda54ca..a4bfa50475 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -34,8 +34,10 @@ void subrem_scene_start_on_enter(void* context) { // subrem_scene_start_submenu_callback, // app); - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); + // TODO: set scene state in subrem alloc + // submenu_set_selected_item( + // submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); + submenu_set_selected_item(submenu, SubmenuIndexSubRemOpenMapFile); view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu); } diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 18ebb05f6f..4f5065b077 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -51,6 +51,7 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() { sub_preset->label = furi_string_alloc_set_str("N/A"); sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; return sub_preset; } @@ -77,6 +78,7 @@ static void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { stream_clean(fff_data_stream); sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; } void subrem_map_preset_reset(SubGhzRemoteApp* app) { @@ -108,6 +110,7 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data #endif path_extract_filename(sub_preset->file_path, sub_preset->label, true); } else { + // Preload seccesful FURI_LOG_I( TAG, "%-5s: %s %s", @@ -115,6 +118,7 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data furi_string_get_cstr(sub_preset->label), furi_string_get_cstr(sub_preset->file_path)); ret = true; + sub_preset->load_state = SubRemLoadSubStatePreloaded; } flipper_format_rewind(fff_data_file); } @@ -268,21 +272,23 @@ bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { return false; } -static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { +static SubRemLoadMapState + subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; - bool ret = false; - bool sub_preset_loaded = false; + bool all_loaded = true; + SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; + SubRemLoadSubState sub_preset_loaded; SubRemSubFilePreset* sub_preset; uint32_t repeat = 200; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { sub_preset = app->subs_preset[i]; - sub_preset_loaded = false; if(furi_string_empty(sub_preset->file_path)) { // FURI_LOG_I(TAG, "Empty file path"); continue; } + sub_preset_loaded = SubRemLoadSubStateErrorNoFile; repeat = 200; do { if(!flipper_format_file_open_existing( @@ -305,6 +311,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat } //Load frequency + sub_preset_loaded = SubRemLoadSubStateErrorFreq; if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); sub_preset->freq_preset.frequency = @@ -317,6 +324,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat } //Load preset + sub_preset_loaded = SubRemLoadSubStateErrorMod; if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { FURI_LOG_E(TAG, "Missing Preset"); break; @@ -329,6 +337,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat } //Load protocol + sub_preset_loaded = SubRemLoadSubStateErrorProtocol; if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { FURI_LOG_E(TAG, "Missing Protocol"); break; @@ -375,8 +384,8 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat break; } - sub_preset_loaded = true; - ret |= true; + sub_preset_loaded = SubRemLoadSubStateOK; + ret = SubRemLoadMapStateNotAllOK; #if FURI_DEBUG FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); #endif @@ -385,9 +394,15 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat // TODO: // Load file state logic // Label depending on the state + // Move to remote scene - if(!sub_preset_loaded) { + if(sub_preset_loaded != SubRemLoadSubStateOK) { furi_string_set_str(sub_preset->label, "N/A"); + all_loaded = false; + } + + if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { + ret = SubRemLoadMapStateOK; } flipper_format_file_close(fff_data_file); @@ -397,7 +412,7 @@ static bool subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_dat return ret; } -bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { +SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { furi_assert(app); furi_assert(file_path); #if FURI_DEBUG @@ -405,7 +420,7 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { #endif Storage* storage = furi_record_open(RECORD_STORAGE); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); - bool ret = false; + SubRemLoadMapState ret = SubRemLoadMapStateErrorOpenError; #if FURI_DEBUG FURI_LOG_I(TAG, "Open Map File.."); #endif @@ -413,20 +428,23 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { if(!flipper_format_file_open_existing(fff_data_file, file_path)) { FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); + ret = SubRemLoadMapStateErrorOpenError; } else { if(!subrem_map_preset_load(app, fff_data_file)) { FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); // ret = // error for popup - } else if( - (flipper_format_file_close(fff_data_file)) && - (subrem_map_preset_check(app, fff_data_file))) { - FURI_LOG_I(TAG, "Load Map File Seccesful"); - ret = true; + } else if(!flipper_format_file_close(fff_data_file)) { + ret = SubRemLoadMapStateErrorOpenError; + } else { + ret = subrem_map_preset_check(app, fff_data_file); } } - // TODO: Popup for error or return error type - if(!ret) { + if(ret == SubRemLoadMapStateOK) { + FURI_LOG_I(TAG, "Load Map File Seccesful"); + } else if(ret == SubRemLoadMapStateNotAllOK) { + FURI_LOG_I(TAG, "Load Map File Seccesful [Not all files]"); + } else { FURI_LOG_E(TAG, "Broken Map File"); } @@ -434,7 +452,6 @@ bool subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path) { flipper_format_free(fff_data_file); furi_record_close(RECORD_STORAGE); - return ret; } @@ -450,10 +467,8 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { // Input events and views are managed by file_select if(!dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options)) { - } else if(subrem_map_file_load(app, furi_string_get_cstr(app->file_path))) { - ret = SubRemLoadMapStateOK; } else { - ret = SubRemLoadMapStateError; + ret = subrem_map_file_load(app, furi_string_get_cstr(app->file_path)); } furi_string_free(file_path); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 0cff3898ac..06abe659cb 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -44,6 +44,7 @@ typedef struct { FuriString* protocaol_name; FuriString* label; SubGhzProtocolType type; + SubRemLoadSubState load_state; } SubRemSubFilePreset; SubRemSubFilePreset* subrem_sub_file_preset_alloc(); @@ -72,8 +73,6 @@ typedef struct { bool tx_running; uint8_t chusen_sub; - - // TODO: LoadFileError } SubGhzRemoteApp; SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); diff --git a/applications/external/subghz_remote_new/views/remote.c b/applications/external/subghz_remote_new/views/remote.c index 85c63568ea..1f867cd0b6 100644 --- a/applications/external/subghz_remote_new/views/remote.c +++ b/applications/external/subghz_remote_new/views/remote.c @@ -4,7 +4,7 @@ #include #include -#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 16 +#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 12 struct SubRemViewRemote { View* view; From b11b0a4911c7fbde841197562bea464b52f47eba Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Sat, 20 May 2023 15:05:26 +0300 Subject: [PATCH 11/23] udp --- applications/external/subghz_remote_new/subghz_remote_app.c | 4 ++++ applications/external/subghz_remote_new/subghz_remote_app_i.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index 0b3f645ab8..b957fb8bcb 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -42,6 +42,7 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { // View Dispatcher app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&subrem_scene_handlers, app); view_dispatcher_enable_queue(app->view_dispatcher); @@ -127,6 +128,9 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); subrem_view_remote_free(app->subrem_remote_view); + scene_manager_free(app->scene_manager); + view_dispatcher_free(app->view_dispatcher); + subghz_receiver_free(app->receiver); subghz_environment_free(app->environment); subghz_setting_free(app->setting); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index 4f5065b077..adc2219419 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -288,7 +288,9 @@ static SubRemLoadMapState // FURI_LOG_I(TAG, "Empty file path"); continue; } + sub_preset_loaded = SubRemLoadSubStateErrorNoFile; + repeat = 200; do { if(!flipper_format_file_open_existing( @@ -386,6 +388,7 @@ static SubRemLoadMapState sub_preset_loaded = SubRemLoadSubStateOK; ret = SubRemLoadMapStateNotAllOK; + #if FURI_DEBUG FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); #endif From 26bcebd5758176c969b49dd17fbefcbf6248a58f Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Sun, 21 May 2023 10:29:58 +0300 Subject: [PATCH 12/23] move part of preset --- .../subghz_remote/helpers/subrem_presets.c | 40 ++ .../subghz_remote/helpers/subrem_presets.h | 27 ++ .../scenes/subrem_scene_remote.c | 12 +- .../main/subghz_remote/subghz_remote_app.c | 6 +- .../main/subghz_remote/subghz_remote_app_i.c | 345 ++++++++---------- .../main/subghz_remote/subghz_remote_app_i.h | 28 +- 6 files changed, 237 insertions(+), 221 deletions(-) create mode 100644 applications/main/subghz_remote/helpers/subrem_presets.c create mode 100644 applications/main/subghz_remote/helpers/subrem_presets.h diff --git a/applications/main/subghz_remote/helpers/subrem_presets.c b/applications/main/subghz_remote/helpers/subrem_presets.c new file mode 100644 index 0000000000..03e497198b --- /dev/null +++ b/applications/main/subghz_remote/helpers/subrem_presets.c @@ -0,0 +1,40 @@ +#include "subrem_presets.h" + +SubRemSubFilePreset* subrem_sub_file_preset_alloc() { + SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); + + sub_preset->fff_data = flipper_format_string_alloc(); + sub_preset->file_path = furi_string_alloc(); + sub_preset->protocaol_name = furi_string_alloc(); + sub_preset->label = furi_string_alloc_set_str("N/A"); + + sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; + + return sub_preset; +} + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_free(sub_preset->label); + furi_string_free(sub_preset->protocaol_name); + furi_string_free(sub_preset->file_path); + flipper_format_free(sub_preset->fff_data); + + free(sub_preset); +} + +void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_set_str(sub_preset->label, "N/A"); + furi_string_reset(sub_preset->protocaol_name); + furi_string_reset(sub_preset->file_path); + + Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); + stream_clean(fff_data_stream); + + sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; +} diff --git a/applications/main/subghz_remote/helpers/subrem_presets.h b/applications/main/subghz_remote/helpers/subrem_presets.h new file mode 100644 index 0000000000..60eedad576 --- /dev/null +++ b/applications/main/subghz_remote/helpers/subrem_presets.h @@ -0,0 +1,27 @@ +#pragma once + +#include "subrem_types.h" +#include +#include + +typedef struct { + uint32_t frequency; + uint8_t* data; +} FreqPreset; + +// Sub File preset +typedef struct { + FlipperFormat* fff_data; + FreqPreset freq_preset; + FuriString* file_path; + FuriString* protocaol_name; + FuriString* label; + SubGhzProtocolType type; + SubRemLoadSubState load_state; +} SubRemSubFilePreset; + +SubRemSubFilePreset* subrem_sub_file_preset_alloc(); + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); + +void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset); diff --git a/applications/main/subghz_remote/scenes/subrem_scene_remote.c b/applications/main/subghz_remote/scenes/subrem_scene_remote.c index c245832336..1b8dbc4717 100644 --- a/applications/main/subghz_remote/scenes/subrem_scene_remote.c +++ b/applications/main/subghz_remote/scenes/subrem_scene_remote.c @@ -41,11 +41,11 @@ static bool subrem_scene_remote_update_data_show(void* context) { subrem_view_remote_add_data_to_show( app->subrem_remote_view, - furi_string_get_cstr(app->subs_preset[0]->label), - furi_string_get_cstr(app->subs_preset[1]->label), - furi_string_get_cstr(app->subs_preset[2]->label), - furi_string_get_cstr(app->subs_preset[3]->label), - furi_string_get_cstr(app->subs_preset[4]->label)); + furi_string_get_cstr(app->map_preset->subs_preset[0]->label), + furi_string_get_cstr(app->map_preset->subs_preset[1]->label), + furi_string_get_cstr(app->map_preset->subs_preset[2]->label), + furi_string_get_cstr(app->map_preset->subs_preset[3]->label), + furi_string_get_cstr(app->map_preset->subs_preset[4]->label)); return ret; } @@ -85,7 +85,7 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading); if(subrem_tx_start_sub( app, - app->subs_preset[app->chusen_sub], + app->map_preset->subs_preset[app->chusen_sub], subrem_scene_remote_raw_callback_end_tx)) { subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub); subrem_view_remote_set_state( diff --git a/applications/main/subghz_remote/subghz_remote_app.c b/applications/main/subghz_remote/subghz_remote_app.c index b957fb8bcb..4f9138e2aa 100644 --- a/applications/main/subghz_remote/subghz_remote_app.c +++ b/applications/main/subghz_remote/subghz_remote_app.c @@ -74,8 +74,9 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { SubRemViewIDRemote, subrem_view_remote_get_view(app->subrem_remote_view)); + app->map_preset = malloc(sizeof(SubRemMapPreset)); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - app->subs_preset[i] = subrem_sub_file_preset_alloc(); + app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc(); } app->setting = subghz_setting_alloc(); @@ -136,8 +137,9 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { subghz_setting_free(app->setting); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_free(app->subs_preset[i]); + subrem_sub_file_preset_free(app->map_preset->subs_preset[i]); } + free(app->map_preset); // Notifications furi_record_close(RECORD_NOTIFICATION); diff --git a/applications/main/subghz_remote/subghz_remote_app_i.c b/applications/main/subghz_remote/subghz_remote_app_i.c index 349fb87cdb..9c35a0e036 100644 --- a/applications/main/subghz_remote/subghz_remote_app_i.c +++ b/applications/main/subghz_remote/subghz_remote_app_i.c @@ -42,50 +42,11 @@ static bool return true; } -SubRemSubFilePreset* subrem_sub_file_preset_alloc() { - SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); - - sub_preset->fff_data = flipper_format_string_alloc(); - sub_preset->file_path = furi_string_alloc(); - sub_preset->protocaol_name = furi_string_alloc(); - sub_preset->label = furi_string_alloc_set_str("N/A"); - - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; - - return sub_preset; -} - -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); - - furi_string_free(sub_preset->label); - furi_string_free(sub_preset->protocaol_name); - furi_string_free(sub_preset->file_path); - flipper_format_free(sub_preset->fff_data); - - free(sub_preset); -} - -static void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); - - furi_string_set_str(sub_preset->label, "N/A"); - furi_string_reset(sub_preset->protocaol_name); - furi_string_reset(sub_preset->file_path); - - Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); - stream_clean(fff_data_stream); - - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; -} - -void subrem_map_preset_reset(SubGhzRemoteApp* app) { - furi_assert(app); +void subrem_map_preset_reset(SubRemMapPreset* map_preset) { + furi_assert(map_preset); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_reset(app->subs_preset[i]); + subrem_sub_file_preset_reset(map_preset->subs_preset[i]); } } @@ -94,7 +55,7 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data bool ret = false; SubRemSubFilePreset* sub_preset; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->subs_preset[i]; + sub_preset = app->map_preset->subs_preset[i]; if(!flipper_format_read_string( fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { #if FURI_DEBUG @@ -125,153 +86,6 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data return ret; } -bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { - furi_assert(flipper_format); - furi_assert(dev_file_name); - - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); - - bool saved = false; - uint32_t repeat = 200; - FuriString* file_dir = furi_string_alloc(); - - path_extract_dirname(dev_file_name, file_dir); - do { - // removing additional fields - flipper_format_delete_key(flipper_format, "Repeat"); - // flipper_format_delete_key(flipper_format, "Manufacture"); - - if(!storage_simply_remove(storage, dev_file_name)) { - break; - } - - //ToDo check Write - stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); - - if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - saved = true; - } while(0); - - furi_string_free(file_dir); - furi_record_close(RECORD_STORAGE); - return saved; -} - -bool subrem_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback) { - furi_assert(app); - furi_assert(sub_preset); - bool ret = false; - - subrem_tx_stop_sub(app, true); - - if(sub_preset->type == SubGhzProtocolTypeUnknown) { - return false; - } - - FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); - - subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); - keeloq_reset_original_btn(); - subghz_custom_btns_reset(); - - do { - flipper_format_rewind(sub_preset->fff_data); // - - app->transmitter = subghz_transmitter_alloc_init( - app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); - - if(app->transmitter) { - if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) != - SubGhzProtocolStatusOk) { - FURI_LOG_E(TAG, "Deserialize error!"); - break; - } - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - furi_hal_subghz_idle(); - - furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - - if(!furi_hal_subghz_tx()) { - FURI_LOG_E(TAG, "Sending not allowed"); - break; - } - - if(sub_preset->type == SubGhzProtocolTypeRAW) { - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( - app->transmitter), - callback, - app); - } - - furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); - - ret = true; - } - } while(false); - - app->tx_running = ret; - - return ret; -} - -static void subghz_tx_stop(SubGhzRemoteApp* app) { - furi_assert(app); - - //Stop TX - furi_hal_subghz_stop_async_tx(); - - subghz_transmitter_stop(app->transmitter); - subghz_transmitter_free(app->transmitter); - furi_hal_subghz_idle(); -} - -bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { - furi_assert(app); - SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; - - if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { - // SubRemSubKeyTypeRawKey)) { - if(app->tx_running) { - subghz_tx_stop(app); - - if(sub_preset->type == SubGhzProtocolTypeDynamic) { - subrem_save_protocol_to_file( - sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); - - keeloq_reset_mfname(); - keeloq_reset_kl_type(); - keeloq_reset_original_btn(); - subghz_custom_btns_reset(); - star_line_reset_mfname(); - star_line_reset_kl_type(); - } - - app->tx_running = false; - return true; - } - } - - return false; -} - static SubRemLoadMapState subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); @@ -283,7 +97,7 @@ static SubRemLoadMapState SubRemSubFilePreset* sub_preset; uint32_t repeat = 200; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->subs_preset[i]; + sub_preset = app->map_preset->subs_preset[i]; if(furi_string_empty(sub_preset->file_path)) { // FURI_LOG_I(TAG, "Empty file path"); continue; @@ -427,7 +241,7 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p #if FURI_DEBUG FURI_LOG_I(TAG, "Open Map File.."); #endif - subrem_map_preset_reset(app); + subrem_map_preset_reset(app->map_preset); if(!flipper_format_file_open_existing(fff_data_file, file_path)) { FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); @@ -458,6 +272,153 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p return ret; } +bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { + furi_assert(flipper_format); + furi_assert(dev_file_name); + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); + + bool saved = false; + uint32_t repeat = 200; + FuriString* file_dir = furi_string_alloc(); + + path_extract_dirname(dev_file_name, file_dir); + do { + // removing additional fields + flipper_format_delete_key(flipper_format, "Repeat"); + // flipper_format_delete_key(flipper_format, "Manufacture"); + + if(!storage_simply_remove(storage, dev_file_name)) { + break; + } + + //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); + stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + + saved = true; + } while(0); + + furi_string_free(file_dir); + furi_record_close(RECORD_STORAGE); + return saved; +} + +bool subrem_tx_start_sub( + SubGhzRemoteApp* app, + SubRemSubFilePreset* sub_preset, + SubGhzProtocolEncoderRAWCallbackEnd callback) { + furi_assert(app); + furi_assert(sub_preset); + bool ret = false; + + subrem_tx_stop_sub(app, true); + + if(sub_preset->type == SubGhzProtocolTypeUnknown) { + return false; + } + + FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); + + subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); + keeloq_reset_original_btn(); + subghz_custom_btns_reset(); + + do { + flipper_format_rewind(sub_preset->fff_data); // + + app->transmitter = subghz_transmitter_alloc_init( + app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); + + if(app->transmitter) { + if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) != + SubGhzProtocolStatusOk) { + FURI_LOG_E(TAG, "Deserialize error!"); + break; + } + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + + furi_hal_subghz_idle(); + + furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + + if(!furi_hal_subghz_tx()) { + FURI_LOG_E(TAG, "Sending not allowed"); + break; + } + + if(sub_preset->type == SubGhzProtocolTypeRAW) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( + app->transmitter), + callback, + app); + } + + furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); + + ret = true; + } + } while(false); + + app->tx_running = ret; + + return ret; +} + +static void subghz_tx_stop(SubGhzRemoteApp* app) { + furi_assert(app); + + //Stop TX + furi_hal_subghz_stop_async_tx(); + + subghz_transmitter_stop(app->transmitter); + subghz_transmitter_free(app->transmitter); + furi_hal_subghz_idle(); +} + +bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { + furi_assert(app); + SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; + + if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { + // SubRemSubKeyTypeRawKey)) { + if(app->tx_running) { + subghz_tx_stop(app); + + if(sub_preset->type == SubGhzProtocolTypeDynamic) { + subrem_save_protocol_to_file( + sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); + + keeloq_reset_mfname(); + keeloq_reset_kl_type(); + keeloq_reset_original_btn(); + subghz_custom_btns_reset(); + star_line_reset_mfname(); + star_line_reset_kl_type(); + } + + app->tx_running = false; + return true; + } + } + + return false; +} + SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { furi_assert(app); diff --git a/applications/main/subghz_remote/subghz_remote_app_i.h b/applications/main/subghz_remote/subghz_remote_app_i.h index 40d70411ab..5d34968cdc 100644 --- a/applications/main/subghz_remote/subghz_remote_app_i.h +++ b/applications/main/subghz_remote/subghz_remote_app_i.h @@ -1,6 +1,8 @@ #pragma once #include "helpers/subrem_types.h" +#include "helpers/subrem_presets.h" + #include #include "views/remote.h" @@ -30,25 +32,8 @@ #define SUBREM_MAX_LEN_NAME 64 typedef struct { - uint32_t frequency; - uint8_t* data; -} FreqPreset; - -// Sub File preset -typedef struct { - FlipperFormat* fff_data; - FreqPreset freq_preset; - FuriString* file_path; - FuriString* protocaol_name; - FuriString* label; - SubGhzProtocolType type; - SubRemLoadSubState load_state; -} SubRemSubFilePreset; - -SubRemSubFilePreset* subrem_sub_file_preset_alloc(); - -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); - + SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; +} SubRemMapPreset; typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; @@ -56,12 +41,13 @@ typedef struct { NotificationApp* notifications; DialogsApp* dialogs; Submenu* submenu; + FuriString* file_path; - char file_name_tmp[SUBREM_MAX_LEN_NAME]; + // char file_name_tmp[SUBREM_MAX_LEN_NAME]; SubRemViewRemote* subrem_remote_view; - SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; + SubRemMapPreset* map_preset; SubGhzSetting* setting; SubGhzEnvironment* environment; From 311533a0ac4cd106c2a7c3f53c2a11bffb26328b Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Sun, 21 May 2023 23:34:42 +0300 Subject: [PATCH 13/23] Using TxRx from subghz --- .../subghz_remote/helpers/subrem_presets.c | 139 +++++++ .../subghz_remote/helpers/subrem_presets.h | 13 +- .../main/subghz_remote/helpers/subrem_types.h | 2 +- .../scenes/subrem_scene_openmapfile.c | 3 +- .../scenes/subrem_scene_remote.c | 51 +-- .../main/subghz_remote/subghz_remote_app.c | 22 +- .../main/subghz_remote/subghz_remote_app_i.c | 342 +++++------------- .../main/subghz_remote/subghz_remote_app_i.h | 19 +- .../main/subghz_remote/views/remote.c | 36 +- .../main/subghz_remote/views/remote.h | 12 +- 10 files changed, 308 insertions(+), 331 deletions(-) diff --git a/applications/main/subghz_remote/helpers/subrem_presets.c b/applications/main/subghz_remote/helpers/subrem_presets.c index 03e497198b..9601aae6ce 100644 --- a/applications/main/subghz_remote/helpers/subrem_presets.c +++ b/applications/main/subghz_remote/helpers/subrem_presets.c @@ -1,5 +1,7 @@ #include "subrem_presets.h" +#define TAG "SubRemPresets" + SubRemSubFilePreset* subrem_sub_file_preset_alloc() { SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); @@ -8,6 +10,8 @@ SubRemSubFilePreset* subrem_sub_file_preset_alloc() { sub_preset->protocaol_name = furi_string_alloc(); sub_preset->label = furi_string_alloc_set_str("N/A"); + sub_preset->freq_preset.name = furi_string_alloc(); + sub_preset->type = SubGhzProtocolTypeUnknown; sub_preset->load_state = SubRemLoadSubStateNotSet; @@ -22,6 +26,8 @@ void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { furi_string_free(sub_preset->file_path); flipper_format_free(sub_preset->fff_data); + furi_string_free(sub_preset->freq_preset.name); + free(sub_preset); } @@ -38,3 +44,136 @@ void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { sub_preset->type = SubGhzProtocolTypeUnknown; sub_preset->load_state = SubRemLoadSubStateNotSet; } + +SubRemLoadSubState subrem_sub_preset_load( + SubRemSubFilePreset* sub_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file) { + furi_assert(sub_preset); + furi_assert(txrx); + furi_assert(fff_data_file); + + Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); + + SubRemLoadSubState ret; + FuriString* temp_str = furi_string_alloc(); + uint32_t temp_data32; + uint32_t repeat = 200; + + ret = SubRemLoadSubStateError; + + do { + stream_clean(fff_data_stream); + if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + break; + } + + if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + temp_data32 == SUBGHZ_KEY_FILE_VERSION) { + } else { + FURI_LOG_E(TAG, "Type or version mismatch"); + break; + } + + SubGhzSetting* setting = subghz_txrx_get_setting(txrx); // txrx->setting; + + //Load frequency or using default from settings + ret = SubRemLoadSubStateErrorFreq; + if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { + FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); + sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting); + } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { + FURI_LOG_E(TAG, "This frequency can only be used for RX"); + break; + } + sub_preset->freq_preset.frequency = temp_data32; + + //Load preset + ret = SubRemLoadSubStateErrorMod; + if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { + FURI_LOG_E(TAG, "Missing Preset"); + break; + } + + furi_string_set_str( + temp_str, subghz_txrx_get_preset_name(txrx, furi_string_get_cstr(temp_str))); + if(!strcmp(furi_string_get_cstr(temp_str), "")) { + break; + } + + if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) { + FURI_LOG_E(TAG, "CUSTOM preset is not supported"); + break; + // TODO Custom preset loading logic if need + // sub_preset->freq_preset.preset_index = + // subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str)); + } + + furi_string_set(sub_preset->freq_preset.name, temp_str); + + // Load protocol + ret = SubRemLoadSubStateErrorProtocol; + if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + + FlipperFormat* fff_data = sub_preset->fff_data; + if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { + //if RAW + subghz_protocol_raw_gen_fff_data( + fff_data, furi_string_get_cstr(sub_preset->file_path)); + } else { + stream_copy_full( + flipper_format_get_raw_stream(fff_data_file), + flipper_format_get_raw_stream(fff_data)); + } + + if(subghz_txrx_load_decoder_by_name_protocol(txrx, furi_string_get_cstr(temp_str))) { + SubGhzProtocolStatus status = + subghz_protocol_decoder_base_deserialize(subghz_txrx_get_decoder(txrx), fff_data); + if(status != SubGhzProtocolStatusOk) { + break; + } + } else { + FURI_LOG_E(TAG, "Protocol not found"); + break; + } + + const SubGhzProtocol* protocol = subghz_txrx_get_decoder(txrx)->protocol; + + if(protocol->flag & SubGhzProtocolFlag_Send) { + if((protocol->type == SubGhzProtocolTypeStatic) || + (protocol->type == SubGhzProtocolTypeDynamic) || + // TODO: BINRAW It probably works, but checks are needed. + // (protocol->type == SubGhzProtocolTypeBinRAW) || + (protocol->type == SubGhzProtocolTypeRAW)) { + sub_preset->type = protocol->type; + } else { + FURI_LOG_E(TAG, "Unsuported Protocol"); + break; + } + + furi_string_set(sub_preset->protocaol_name, temp_str); + } else { + FURI_LOG_E(TAG, "Protocol does not support transmission"); + break; + } + + if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + + ret = SubRemLoadSubStateOK; + +#if FURI_DEBUG + FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); +#endif + } while(false); + + furi_string_free(temp_str); + return ret; +} diff --git a/applications/main/subghz_remote/helpers/subrem_presets.h b/applications/main/subghz_remote/helpers/subrem_presets.h index 60eedad576..fd4a2d7802 100644 --- a/applications/main/subghz_remote/helpers/subrem_presets.h +++ b/applications/main/subghz_remote/helpers/subrem_presets.h @@ -3,10 +3,12 @@ #include "subrem_types.h" #include #include +#include "../../subghz/helpers/subghz_txrx.h" typedef struct { + FuriString* name; uint32_t frequency; - uint8_t* data; + // size_t preset_index; // Need for custom preset } FreqPreset; // Sub File preset @@ -20,8 +22,17 @@ typedef struct { SubRemLoadSubState load_state; } SubRemSubFilePreset; +typedef struct { + SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; +} SubRemMapPreset; + SubRemSubFilePreset* subrem_sub_file_preset_alloc(); void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset); + +SubRemLoadSubState subrem_sub_preset_load( + SubRemSubFilePreset* sub_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file); diff --git a/applications/main/subghz_remote/helpers/subrem_types.h b/applications/main/subghz_remote/helpers/subrem_types.h index 13b42897f6..def8078988 100644 --- a/applications/main/subghz_remote/helpers/subrem_types.h +++ b/applications/main/subghz_remote/helpers/subrem_types.h @@ -26,7 +26,7 @@ typedef enum { } SubRemViewID; typedef enum { - SubRemLoadSubStateNotSet, + SubRemLoadSubStateNotSet = 0, SubRemLoadSubStatePreloaded, SubRemLoadSubStateError, SubRemLoadSubStateErrorNoFile, diff --git a/applications/main/subghz_remote/scenes/subrem_scene_openmapfile.c b/applications/main/subghz_remote/scenes/subrem_scene_openmapfile.c index ea5c14a0a5..796699c831 100644 --- a/applications/main/subghz_remote/scenes/subrem_scene_openmapfile.c +++ b/applications/main/subghz_remote/scenes/subrem_scene_openmapfile.c @@ -4,7 +4,8 @@ void subrem_scene_openmapfile_on_enter(void* context) { SubGhzRemoteApp* app = context; SubRemLoadMapState load_state = subrem_load_from_file(app); - if(load_state == SubRemLoadMapStateError) { + if(load_state != SubRemLoadMapStateOK && load_state != SubRemLoadMapStateNotAllOK && + load_state != SubRemLoadMapStateBack) { #ifdef SUBREM_LIGHT dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); #else diff --git a/applications/main/subghz_remote/scenes/subrem_scene_remote.c b/applications/main/subghz_remote/scenes/subrem_scene_remote.c index 1b8dbc4717..eaa1c41d94 100644 --- a/applications/main/subghz_remote/scenes/subrem_scene_remote.c +++ b/applications/main/subghz_remote/scenes/subrem_scene_remote.c @@ -37,17 +37,16 @@ static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) { static bool subrem_scene_remote_update_data_show(void* context) { SubGhzRemoteApp* app = context; - bool ret = false; - subrem_view_remote_add_data_to_show( - app->subrem_remote_view, - furi_string_get_cstr(app->map_preset->subs_preset[0]->label), - furi_string_get_cstr(app->map_preset->subs_preset[1]->label), - furi_string_get_cstr(app->map_preset->subs_preset[2]->label), - furi_string_get_cstr(app->map_preset->subs_preset[3]->label), - furi_string_get_cstr(app->map_preset->subs_preset[4]->label)); + const char* labels[SubRemSubKeyNameMaxCount]; - return ret; + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + labels[i] = furi_string_get_cstr(app->map_preset->subs_preset[i]->label); + } + + subrem_view_remote_add_data_to_show(app->subrem_remote_view, labels); + + return true; } void subrem_scene_remote_on_enter(void* context) { @@ -81,32 +80,37 @@ bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { event.event == SubRemCustomEventViewRemoteStartOK) { // Start sending sub subrem_tx_stop_sub(app, true); - app->chusen_sub = subrem_scene_remote_event_to_index(event.event); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading); - if(subrem_tx_start_sub( - app, - app->map_preset->subs_preset[app->chusen_sub], - subrem_scene_remote_raw_callback_end_tx)) { - subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub); + + uint8_t chusen_sub = subrem_scene_remote_event_to_index(event.event); + app->chusen_sub = chusen_sub; + + subrem_view_remote_set_state( + app->subrem_remote_view, SubRemViewRemoteStateLoading, chusen_sub); + + if(subrem_tx_start_sub(app, app->map_preset->subs_preset[chusen_sub])) { + if(app->map_preset->subs_preset[chusen_sub]->type == SubGhzProtocolTypeRAW) { + subghz_txrx_set_raw_file_encoder_worker_callback_end( + app->txrx, subrem_scene_remote_raw_callback_end_tx, app); + } subrem_view_remote_set_state( - app->subrem_remote_view, SubRemViewRemoteStateSending); + app->subrem_remote_view, SubRemViewRemoteStateSending, chusen_sub); notification_message(app->notifications, &sequence_blink_start_magenta); } else { - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + subrem_view_remote_set_state( + app->subrem_remote_view, SubRemViewRemoteStateIdle, 0); notification_message(app->notifications, &sequence_blink_stop); } return true; } else if(event.event == SubRemCustomEventViewRemoteForcedStop) { subrem_tx_stop_sub(app, true); - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0); notification_message(app->notifications, &sequence_blink_stop); return true; } else if(event.event == SubRemCustomEventViewRemoteStop) { if(subrem_tx_stop_sub(app, false)) { - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + subrem_view_remote_set_state( + app->subrem_remote_view, SubRemViewRemoteStateIdle, 0); notification_message(app->notifications, &sequence_blink_stop); } @@ -123,8 +127,7 @@ void subrem_scene_remote_on_exit(void* context) { subrem_tx_stop_sub(app, true); - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0); notification_message(app->notifications, &sequence_blink_stop); } diff --git a/applications/main/subghz_remote/subghz_remote_app.c b/applications/main/subghz_remote/subghz_remote_app.c index 4f9138e2aa..7383757d25 100644 --- a/applications/main/subghz_remote/subghz_remote_app.c +++ b/applications/main/subghz_remote/subghz_remote_app.c @@ -79,23 +79,9 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc(); } - app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); + app->txrx = subghz_txrx_alloc(); - app->environment = subghz_environment_alloc(); - - subghz_environment_load_keystore(app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); - subghz_environment_load_keystore( - app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); - subghz_environment_set_came_atomo_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/came_atomo")); - subghz_environment_set_alutech_at_4n_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/alutech_at_4n")); - subghz_environment_set_nice_flor_s_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/nice_flor_s")); - subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry); - - app->receiver = subghz_receiver_alloc_init(app->environment); + subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app); app->tx_running = false; @@ -132,9 +118,7 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { scene_manager_free(app->scene_manager); view_dispatcher_free(app->view_dispatcher); - subghz_receiver_free(app->receiver); - subghz_environment_free(app->environment); - subghz_setting_free(app->setting); + subghz_txrx_free(app->txrx); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { subrem_sub_file_preset_free(app->map_preset->subs_preset[i]); diff --git a/applications/main/subghz_remote/subghz_remote_app_i.c b/applications/main/subghz_remote/subghz_remote_app_i.c index 9c35a0e036..fb34b59f70 100644 --- a/applications/main/subghz_remote/subghz_remote_app_i.c +++ b/applications/main/subghz_remote/subghz_remote_app_i.c @@ -4,6 +4,8 @@ #include +#include "../subghz/helpers/subghz_txrx_i.h" + // #include // #include @@ -11,6 +13,12 @@ #define TAG "SubGhzRemote" +// XXX Using TxRx +// [x] use TxRx preset subrem_sub_preset_load & subrem_tx_start_sub +// [x] subrem_sub_preset_load & drop subrem_set_preset_data +// [x] subrem_tx_start_sub +// [x] subrem_tx_stop_sub + static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { [SubRemSubKeyNameUp] = {"UP", "ULABEL"}, [SubRemSubKeyNameDown] = {"DOWN", "DLABEL"}, @@ -19,43 +27,69 @@ static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { [SubRemSubKeyNameOk] = {"OK", "OKLABEL"}, }; -static bool - subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { - const char* preset_name = ""; - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - preset_name = "AM270"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - preset_name = "AM650"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - preset_name = "FM238"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - preset_name = "FM476"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - // preset_name = "CUSTOM"; - return false; - } else { - FURI_LOG_E(TAG, "Unknown preset"); - return false; +static void subrem_map_preset_reset(SubRemMapPreset* map_preset) { + furi_assert(map_preset); + + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + subrem_sub_file_preset_reset(map_preset->subs_preset[i]); } - size_t preset_index = subghz_setting_get_inx_preset_by_name(setting, preset_name); - freq_preset->data = subghz_setting_get_preset_data(setting, preset_index); - return true; } -void subrem_map_preset_reset(SubRemMapPreset* map_preset) { +static SubRemLoadMapState subrem_map_preset_check( + SubRemMapPreset* map_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file) { furi_assert(map_preset); + furi_assert(txrx); + + bool all_loaded = true; + SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; + + SubRemLoadSubState sub_preset_loaded; + SubRemSubFilePreset* sub_preset; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_reset(map_preset->subs_preset[i]); + sub_preset = map_preset->subs_preset[i]; + + sub_preset_loaded = SubRemLoadSubStateErrorNoFile; + + if(furi_string_empty(sub_preset->file_path)) { + // FURI_LOG_I(TAG, "Empty file path"); + } else if(!flipper_format_file_open_existing( + fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { + FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); + } else { + sub_preset_loaded = subrem_sub_preset_load(sub_preset, txrx, fff_data_file); + } + + // TODO: + // Load file state logic + // Label depending on the state + // Move to remote scene + + if(sub_preset_loaded != SubRemLoadSubStateOK) { + furi_string_set_str(sub_preset->label, "N/A"); + all_loaded = false; + } else { + ret = SubRemLoadMapStateNotAllOK; + } + + if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { + ret = SubRemLoadMapStateOK; + } + + flipper_format_file_close(fff_data_file); } + + return ret; } -static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { - furi_assert(app); +static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* fff_data_file) { + furi_assert(map_preset); bool ret = false; SubRemSubFilePreset* sub_preset; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->map_preset->subs_preset[i]; + sub_preset = map_preset->subs_preset[i]; if(!flipper_format_read_string( fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { #if FURI_DEBUG @@ -69,8 +103,13 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data #if FURI_DEBUG FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); #endif + // TODO move to remote scene path_extract_filename(sub_preset->file_path, sub_preset->label, true); + ret = true; } else { + ret = true; + } + if(ret) { // Preload seccesful FURI_LOG_I( TAG, @@ -78,154 +117,11 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data map_file_labels[i][0], furi_string_get_cstr(sub_preset->label), furi_string_get_cstr(sub_preset->file_path)); - ret = true; sub_preset->load_state = SubRemLoadSubStatePreloaded; } - flipper_format_rewind(fff_data_file); - } - return ret; -} - -static SubRemLoadMapState - subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { - furi_assert(app); - FuriString* temp_str = furi_string_alloc(); - uint32_t temp_data32; - bool all_loaded = true; - SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; - SubRemLoadSubState sub_preset_loaded; - SubRemSubFilePreset* sub_preset; - uint32_t repeat = 200; - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->map_preset->subs_preset[i]; - if(furi_string_empty(sub_preset->file_path)) { - // FURI_LOG_I(TAG, "Empty file path"); - continue; - } - - sub_preset_loaded = SubRemLoadSubStateErrorNoFile; - repeat = 200; - do { - if(!flipper_format_file_open_existing( - fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { - FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); - break; - } - - if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - break; - } - - if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || - (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && - temp_data32 == SUBGHZ_KEY_FILE_VERSION) { - } else { - FURI_LOG_E(TAG, "Type or version mismatch"); - break; - } - - //Load frequency - sub_preset_loaded = SubRemLoadSubStateErrorFreq; - if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); - sub_preset->freq_preset.frequency = - subghz_setting_get_default_frequency(app->setting); - } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { - FURI_LOG_E(TAG, "This frequency can only be used for RX"); - break; - } else { - sub_preset->freq_preset.frequency = temp_data32; - } - - //Load preset - sub_preset_loaded = SubRemLoadSubStateErrorMod; - if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { - FURI_LOG_E(TAG, "Missing Preset"); - break; - } - - if(!subrem_set_preset_data( - app->setting, &sub_preset->freq_preset, furi_string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Cannot load preset."); - break; - } - - //Load protocol - sub_preset_loaded = SubRemLoadSubStateErrorProtocol; - if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - FlipperFormat* fff_data = sub_preset->fff_data; - if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { - //if RAW - subghz_protocol_raw_gen_fff_data( - fff_data, furi_string_get_cstr(sub_preset->file_path)); - } else { - stream_copy_full( - flipper_format_get_raw_stream(fff_data_file), - flipper_format_get_raw_stream(fff_data)); - } - - const SubGhzProtocolRegistry* protocol_registry_items = - subghz_environment_get_protocol_registry(app->environment); - - const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name( - protocol_registry_items, furi_string_get_cstr(temp_str)); - - if(!protocol) { - FURI_LOG_E(TAG, "Protocol not found"); - break; - } else if(protocol->flag & SubGhzProtocolFlag_Send) { - if((protocol->type == SubGhzProtocolTypeStatic) || - (protocol->type == SubGhzProtocolTypeDynamic) || - // (protocol->type == SubGhzProtocolTypeBinRAW) || // TODO: BINRAW - (protocol->type == SubGhzProtocolTypeRAW)) { - sub_preset->type = protocol->type; - } else { - FURI_LOG_E(TAG, "Unsuported Protocol"); - break; - } - - furi_string_set(sub_preset->protocaol_name, temp_str); - } else { - FURI_LOG_E(TAG, "Protocol does not support transmission"); - } - - if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - sub_preset_loaded = SubRemLoadSubStateOK; - ret = SubRemLoadMapStateNotAllOK; - -#if FURI_DEBUG - FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); -#endif - } while(false); - - // TODO: - // Load file state logic - // Label depending on the state - // Move to remote scene - - if(sub_preset_loaded != SubRemLoadSubStateOK) { - furi_string_set_str(sub_preset->label, "N/A"); - all_loaded = false; - } - - if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { - ret = SubRemLoadMapStateOK; - } - - flipper_format_file_close(fff_data_file); + flipper_format_rewind(fff_data_file); } - furi_string_free(temp_str); - return ret; } @@ -247,13 +143,13 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); ret = SubRemLoadMapStateErrorOpenError; } else { - if(!subrem_map_preset_load(app, fff_data_file)) { + if(!subrem_map_preset_load(app->map_preset, fff_data_file)) { FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); // ret = // error for popup } else if(!flipper_format_file_close(fff_data_file)) { ret = SubRemLoadMapStateErrorOpenError; } else { - ret = subrem_map_preset_check(app, fff_data_file); + ret = subrem_map_preset_check(app->map_preset, app->txrx, fff_data_file); } } @@ -272,9 +168,9 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p return ret; } -bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { +bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* sub_file_name) { furi_assert(flipper_format); - furi_assert(dev_file_name); + furi_assert(sub_file_name); Storage* storage = furi_record_open(RECORD_STORAGE); Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); @@ -283,19 +179,19 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev uint32_t repeat = 200; FuriString* file_dir = furi_string_alloc(); - path_extract_dirname(dev_file_name, file_dir); + path_extract_dirname(sub_file_name, file_dir); do { // removing additional fields flipper_format_delete_key(flipper_format, "Repeat"); // flipper_format_delete_key(flipper_format, "Manufacture"); - if(!storage_simply_remove(storage, dev_file_name)) { + if(!storage_simply_remove(storage, sub_file_name)) { break; } //ToDo check Write stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); + stream_save_to_file(flipper_format_stream, storage, sub_file_name, FSOM_CREATE_ALWAYS); if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { FURI_LOG_E(TAG, "Unable Repeat"); @@ -310,10 +206,16 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev return saved; } -bool subrem_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback) { +void subrem_save_active_sub(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; + subrem_save_protocol_to_file( + sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); +} + +bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset) { furi_assert(app); furi_assert(sub_preset); bool ret = false; @@ -321,88 +223,44 @@ bool subrem_tx_start_sub( subrem_tx_stop_sub(app, true); if(sub_preset->type == SubGhzProtocolTypeUnknown) { - return false; - } - - FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); - - subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); - keeloq_reset_original_btn(); - subghz_custom_btns_reset(); - - do { - flipper_format_rewind(sub_preset->fff_data); // - - app->transmitter = subghz_transmitter_alloc_init( - app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); + ret = false; + } else { + FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); - if(app->transmitter) { - if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) != - SubGhzProtocolStatusOk) { - FURI_LOG_E(TAG, "Deserialize error!"); - break; - } - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - furi_hal_subghz_idle(); - - furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - - if(!furi_hal_subghz_tx()) { - FURI_LOG_E(TAG, "Sending not allowed"); - break; - } + subghz_txrx_load_decoder_by_name_protocol( + app->txrx, furi_string_get_cstr(sub_preset->protocaol_name)); - if(sub_preset->type == SubGhzProtocolTypeRAW) { - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( - app->transmitter), - callback, - app); - } + subghz_txrx_set_preset( + app->txrx, + furi_string_get_cstr(sub_preset->freq_preset.name), + sub_preset->freq_preset.frequency, + NULL, + 0); - furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); + subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); + keeloq_reset_original_btn(); + subghz_custom_btns_reset(); + if(subghz_txrx_tx_start(app->txrx, sub_preset->fff_data) == SubGhzTxRxStartTxStateOk) { ret = true; } - } while(false); + } app->tx_running = ret; return ret; } -static void subghz_tx_stop(SubGhzRemoteApp* app) { - furi_assert(app); - - //Stop TX - furi_hal_subghz_stop_async_tx(); - - subghz_transmitter_stop(app->transmitter); - subghz_transmitter_free(app->transmitter); - furi_hal_subghz_idle(); -} - bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { furi_assert(app); SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { - // SubRemSubKeyTypeRawKey)) { + // XXX drop app->tx_running if(app->tx_running) { - subghz_tx_stop(app); + subghz_txrx_stop(app->txrx); if(sub_preset->type == SubGhzProtocolTypeDynamic) { - subrem_save_protocol_to_file( - sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); - keeloq_reset_mfname(); keeloq_reset_kl_type(); keeloq_reset_original_btn(); diff --git a/applications/main/subghz_remote/subghz_remote_app_i.h b/applications/main/subghz_remote/subghz_remote_app_i.h index 5d34968cdc..50e2bae9f8 100644 --- a/applications/main/subghz_remote/subghz_remote_app_i.h +++ b/applications/main/subghz_remote/subghz_remote_app_i.h @@ -3,6 +3,8 @@ #include "helpers/subrem_types.h" #include "helpers/subrem_presets.h" +#include "../subghz/helpers/subghz_txrx.h" + #include #include "views/remote.h" @@ -31,9 +33,6 @@ #define SUBREM_APP_FOLDER EXT_PATH("subghz_remote") #define SUBREM_MAX_LEN_NAME 64 -typedef struct { - SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; -} SubRemMapPreset; typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; @@ -49,10 +48,7 @@ typedef struct { SubRemMapPreset* map_preset; - SubGhzSetting* setting; - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzTransmitter* transmitter; + SubGhzTxRx* txrx; bool tx_running; @@ -61,9 +57,8 @@ typedef struct { SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); -bool subrem_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback); +bool subrem_tx_start_sub(SubGhzRemoteApp* app, SubRemSubFilePreset* sub_preset); + +bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced); -bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced); \ No newline at end of file +void subrem_save_active_sub(void* context); \ No newline at end of file diff --git a/applications/main/subghz_remote/views/remote.c b/applications/main/subghz_remote/views/remote.c index 1f867cd0b6..e062f11b1d 100644 --- a/applications/main/subghz_remote/views/remote.c +++ b/applications/main/subghz_remote/views/remote.c @@ -41,24 +41,18 @@ void subrem_view_remote_set_callback( subrem_view_remote->context = context; } -void subrem_view_remote_add_data_to_show( - SubRemViewRemote* subrem_view_remote, - const char* up_label, - const char* down_label, - const char* left_label, - const char* right_label, - const char* ok_label) { +void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels) { furi_assert(subrem_view_remote); with_view_model( subrem_view_remote->view, SubRemViewRemoteModel * model, { - strncpy(model->up_label, up_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->down_label, down_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->left_label, left_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->up_label, labels[0], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->down_label, labels[1], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->left_label, labels[2], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->right_label, labels[3], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + strncpy(model->ok_label, labels[4], SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); // furi_string_set(model->up_label, up_label); // furi_string_set(model->down_label, down_label); @@ -69,23 +63,21 @@ void subrem_view_remote_add_data_to_show( true); } -void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn) { +void subrem_view_remote_set_state( + SubRemViewRemote* subrem_view_remote, + SubRemViewRemoteState state, + uint8_t presed_btn) { furi_assert(subrem_view_remote); with_view_model( subrem_view_remote->view, SubRemViewRemoteModel * model, - { model->pressed_btn = presed_btn; }, + { + model->state = state; + model->pressed_btn = presed_btn; + }, true); } -void subrem_view_remote_set_state( - SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state) { - furi_assert(subrem_view_remote); - with_view_model( - subrem_view_remote->view, SubRemViewRemoteModel * model, { model->state = state; }, true); -} - void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { canvas_clear(canvas); canvas_set_color(canvas, ColorBlack); diff --git a/applications/main/subghz_remote/views/remote.h b/applications/main/subghz_remote/views/remote.h index 76121cf8a0..ea274fca4f 100644 --- a/applications/main/subghz_remote/views/remote.h +++ b/applications/main/subghz_remote/views/remote.h @@ -24,15 +24,9 @@ void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote); View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote); -void subrem_view_remote_add_data_to_show( - SubRemViewRemote* subrem_view_remote, - const char* up_label, - const char* down_label, - const char* left_label, - const char* right_label, - const char* ok_label); +void subrem_view_remote_add_data_to_show(SubRemViewRemote* subrem_view_remote, const char** labels); -void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn); void subrem_view_remote_set_state( SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state); \ No newline at end of file + SubRemViewRemoteState state, + uint8_t presed_btn); \ No newline at end of file From 14a12b02efc595826114f78b75e5cb6559c9938e Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 26 May 2023 17:32:52 +0300 Subject: [PATCH 14/23] drop tx --- .../helpers/subrem_custom_event.h | 1 - .../scenes/subrem_scene_config.h | 3 +- .../scenes/subrem_scene_openmapfile.c | 1 - .../scenes/subrem_scene_remote.c | 130 ------------------ .../scenes/subrem_scene_start.c | 20 +-- .../subghz_remote_new/subghz_remote_app_i.c | 109 --------------- .../subghz_remote_new/subghz_remote_app_i.h | 7 - 7 files changed, 3 insertions(+), 268 deletions(-) delete mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_remote.c diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index 46ab8ad547..b6f752ba0d 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -2,7 +2,6 @@ typedef enum { //SubmenuIndex - SubmenuIndexSubRemOpenMapFile, SubmenuIndexSubRemRemoteView, SubmenuIndexSubRemAbout, diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_config.h b/applications/external/subghz_remote_new/scenes/subrem_scene_config.h index 93d4de642e..a07b936969 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_config.h +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_config.h @@ -1,3 +1,2 @@ ADD_SCENE(subrem, start, Start) -ADD_SCENE(subrem, openmapfile, OpenMapFile) -ADD_SCENE(subrem, remote, Remote) \ No newline at end of file +ADD_SCENE(subrem, openmapfile, OpenMapFile) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c index ea5c14a0a5..8e6d9d0ddc 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c @@ -19,7 +19,6 @@ void subrem_scene_openmapfile_on_enter(void* context) { #endif } if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) { - scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); } else { // TODO: Map Preset Reset if(!scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c b/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c deleted file mode 100644 index c245832336..0000000000 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_remote.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "../subghz_remote_app_i.h" -#include "../views/remote.h" - -#include - -#define TAG "SubRemScenRemote" - -void subrem_scene_remote_callback(SubRemCustomEvent event, void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, event); -} - -void subrem_scene_remote_raw_callback_end_tx(void* context) { - furi_assert(context); - SubGhzRemoteApp* app = context; - view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewRemoteForcedStop); -} - -static uint8_t subrem_scene_remote_event_to_index(SubRemCustomEvent event_id) { - uint8_t ret = 0; - - if(event_id == SubRemCustomEventViewRemoteStartUP) { - ret = SubRemSubKeyNameUp; - } else if(event_id == SubRemCustomEventViewRemoteStartDOWN) { - ret = SubRemSubKeyNameDown; - } else if(event_id == SubRemCustomEventViewRemoteStartLEFT) { - ret = SubRemSubKeyNameLeft; - } else if(event_id == SubRemCustomEventViewRemoteStartRIGHT) { - ret = SubRemSubKeyNameRight; - } else if(event_id == SubRemCustomEventViewRemoteStartOK) { - ret = SubRemSubKeyNameOk; - } - - return ret; -} - -static bool subrem_scene_remote_update_data_show(void* context) { - SubGhzRemoteApp* app = context; - bool ret = false; - - subrem_view_remote_add_data_to_show( - app->subrem_remote_view, - furi_string_get_cstr(app->subs_preset[0]->label), - furi_string_get_cstr(app->subs_preset[1]->label), - furi_string_get_cstr(app->subs_preset[2]->label), - furi_string_get_cstr(app->subs_preset[3]->label), - furi_string_get_cstr(app->subs_preset[4]->label)); - - return ret; -} - -void subrem_scene_remote_on_enter(void* context) { - SubGhzRemoteApp* app = context; - - subrem_scene_remote_update_data_show(app); - - subrem_view_remote_set_callback(app->subrem_remote_view, subrem_scene_remote_callback, app); - - view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDRemote); -} - -bool subrem_scene_remote_on_event(void* context, SceneManagerEvent event) { - SubGhzRemoteApp* app = context; - if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubRemCustomEventViewRemoteBack) { - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SubRemSceneOpenMapFile)) { - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SubRemSceneStart)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } - } - return true; - } else if( - event.event == SubRemCustomEventViewRemoteStartUP || - event.event == SubRemCustomEventViewRemoteStartDOWN || - event.event == SubRemCustomEventViewRemoteStartLEFT || - event.event == SubRemCustomEventViewRemoteStartRIGHT || - event.event == SubRemCustomEventViewRemoteStartOK) { - // Start sending sub - subrem_tx_stop_sub(app, true); - app->chusen_sub = subrem_scene_remote_event_to_index(event.event); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateLoading); - if(subrem_tx_start_sub( - app, - app->subs_preset[app->chusen_sub], - subrem_scene_remote_raw_callback_end_tx)) { - subrem_view_remote_set_presed_btn(app->subrem_remote_view, app->chusen_sub); - subrem_view_remote_set_state( - app->subrem_remote_view, SubRemViewRemoteStateSending); - notification_message(app->notifications, &sequence_blink_start_magenta); - } else { - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); - notification_message(app->notifications, &sequence_blink_stop); - } - return true; - } else if(event.event == SubRemCustomEventViewRemoteForcedStop) { - subrem_tx_stop_sub(app, true); - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); - - notification_message(app->notifications, &sequence_blink_stop); - return true; - } else if(event.event == SubRemCustomEventViewRemoteStop) { - if(subrem_tx_stop_sub(app, false)) { - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); - - notification_message(app->notifications, &sequence_blink_stop); - } - return true; - } - } - // } else if(event.type == SceneManagerEventTypeTick) { - // } - return false; -} - -void subrem_scene_remote_on_exit(void* context) { - SubGhzRemoteApp* app = context; - - subrem_tx_stop_sub(app, true); - - subrem_view_remote_set_presed_btn(app->subrem_remote_view, 0); - subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle); - - notification_message(app->notifications, &sequence_blink_stop); -} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c index a4bfa50475..fd2d61c480 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -13,12 +13,6 @@ void subrem_scene_start_on_enter(void* context) { SubGhzRemoteApp* app = context; Submenu* submenu = app->submenu; - submenu_add_item( - submenu, - "Open Map File", - SubmenuIndexSubRemOpenMapFile, - subrem_scene_start_submenu_callback, - app); #if FURI_DEBUG submenu_add_item( submenu, @@ -37,7 +31,7 @@ void subrem_scene_start_on_enter(void* context) { // TODO: set scene state in subrem alloc // submenu_set_selected_item( // submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); - submenu_set_selected_item(submenu, SubmenuIndexSubRemOpenMapFile); + submenu_set_selected_item(submenu, 0); view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu); } @@ -47,22 +41,12 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { SubGhzRemoteApp* app = context; bool consumed = false; - + UNUSED(app); if(event.type == SceneManagerEventTypeCustom) { - if(event.event == SubmenuIndexSubRemOpenMapFile) { - scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); - consumed = true; - } // } else if(event.event == SubmenuIndexSubRemAbout) { // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); // consumed = true; // } -#if FURI_DEBUG - else if(event.event == SubmenuIndexSubRemRemoteView) { - scene_manager_next_scene(app->scene_manager, SubRemSceneRemote); - consumed = true; - } -#endif } return consumed; diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index adc2219419..aa8983951b 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -163,115 +163,6 @@ bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev return saved; } -bool subrem_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback) { - furi_assert(app); - furi_assert(sub_preset); - bool ret = false; - - subrem_tx_stop_sub(app, true); - - if(sub_preset->type == SubGhzProtocolTypeUnknown) { - return false; - } - - FURI_LOG_I(TAG, "Send %s", furi_string_get_cstr(sub_preset->label)); - - // subghz_custom_btn_set(SUBGHZ_CUSTOM_BTN_OK); - // keeloq_reset_original_btn(); - // subghz_custom_btns_reset(); - - do { - flipper_format_rewind(sub_preset->fff_data); // - - app->transmitter = subghz_transmitter_alloc_init( - app->environment, furi_string_get_cstr(sub_preset->protocaol_name)); - - if(app->transmitter) { - if(subghz_transmitter_deserialize(app->transmitter, sub_preset->fff_data) != - SubGhzProtocolStatusOk) { - FURI_LOG_E(TAG, "Deserialize error!"); - break; - } - furi_hal_subghz_reset(); - furi_hal_subghz_idle(); - furi_hal_subghz_load_custom_preset(sub_preset->freq_preset.data); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); - - furi_hal_subghz_idle(); - - furi_hal_subghz_set_frequency_and_path(sub_preset->freq_preset.frequency); - furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); - furi_hal_gpio_init( - furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - - if(!furi_hal_subghz_tx()) { - FURI_LOG_E(TAG, "Sending not allowed"); - break; - } - - if(sub_preset->type == SubGhzProtocolTypeRAW) { - subghz_protocol_raw_file_encoder_worker_set_callback_end( - (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance( - app->transmitter), - callback, - app); - } - - furi_hal_subghz_start_async_tx(subghz_transmitter_yield, app->transmitter); - - ret = true; - } - } while(false); - - app->tx_running = ret; - - return ret; -} - -static void subghz_tx_stop(SubGhzRemoteApp* app) { - furi_assert(app); - - //Stop TX - furi_hal_subghz_stop_async_tx(); - - subghz_transmitter_stop(app->transmitter); - subghz_transmitter_free(app->transmitter); - furi_hal_subghz_idle(); -} - -bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced) { - furi_assert(app); - SubRemSubFilePreset* sub_preset = app->subs_preset[app->chusen_sub]; - - if(forced || (sub_preset->type != SubGhzProtocolTypeRAW)) { - // SubRemSubKeyTypeRawKey)) { - if(app->tx_running) { - subghz_tx_stop(app); - - if(sub_preset->type == SubGhzProtocolTypeDynamic) { - subrem_save_protocol_to_file( - sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); - - // keeloq_reset_mfname(); - // keeloq_reset_kl_type(); - // keeloq_reset_original_btn(); - // subghz_custom_btns_reset(); - // star_line_reset_mfname(); - // star_line_reset_kl_type(); - } - - app->tx_running = false; - return true; - } - } - - return false; -} - static SubRemLoadMapState subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { furi_assert(app); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 06abe659cb..1bcb79d8fd 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -76,10 +76,3 @@ typedef struct { } SubGhzRemoteApp; SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); - -bool subrem_tx_start_sub( - SubGhzRemoteApp* app, - SubRemSubFilePreset* sub_preset, - SubGhzProtocolEncoderRAWCallbackEnd callback); - -bool subrem_tx_stop_sub(SubGhzRemoteApp* app, bool forced); \ No newline at end of file From c1eb968144f41319efb3e7b8cc4eea66327624fd Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 26 May 2023 17:39:43 +0300 Subject: [PATCH 15/23] Merge branch 'subrem' into subrem_configurator --- .../subghz_remote_new/application.fam | 11 +- .../helpers/subrem_custom_event.h | 39 +- .../helpers/subrem_presets.c | 180 ++++++ .../helpers/subrem_presets.h | 39 ++ .../subghz_remote_new/helpers/subrem_types.h | 17 +- .../subghz_remote_new/helpers/txrx/Readme.md | 4 + .../helpers/txrx/subghz_txrx.c | 563 ++++++++++++++++++ .../helpers/txrx/subghz_txrx.h | 318 ++++++++++ .../helpers/txrx/subghz_txrx_i.h | 29 + .../icons/DolphinNice_96x59.png | Bin 0 -> 2459 bytes .../{ => remote_scene}/ButtonDown_7x4.png | Bin .../{ => remote_scene}/ButtonLeft_4x7.png | Bin .../{ => remote_scene}/ButtonRight_4x7.png | Bin .../icons/{ => remote_scene}/ButtonUp_7x4.png | Bin .../icons/{ => remote_scene}/Ok_btn_9x9.png | Bin .../{ => remote_scene}/Pin_arrow_up_7x9.png | Bin .../{ => remote_scene}/Pin_cell_13x13.png | Bin .../icons/{ => remote_scene}/Pin_star_7x7.png | Bin .../icons/{ => remote_scene}/back_10px.png | Bin .../subghz_remote_new/icons/subrem_10px.png | Bin 0 -> 5000 bytes .../scenes/subrem_scene_config.h | 8 +- .../scenes/subrem_scene_edit_label.c | 133 +++++ .../scenes/subrem_scene_edit_menu.c | 123 ++++ .../scenes/subrem_scene_edit_preview.c | 74 +++ .../scenes/subrem_scene_edit_submenu.c | 54 ++ .../scenes/subrem_scene_enter_new_name.c | 71 +++ .../scenes/subrem_scene_open_map_file.c | 29 + .../scenes/subrem_scene_open_sub_file.c | 116 ++++ .../scenes/subrem_scene_openmapfile.c | 40 -- .../scenes/subrem_scene_start.c | 33 +- .../subghz_remote_new/subghz_remote_app.c | 87 ++- .../subghz_remote_new/subghz_remote_app_i.c | 395 +++++------- .../subghz_remote_new/subghz_remote_app_i.h | 57 +- .../subghz_remote_new/views/edit_menu.c | 290 +++++++++ .../subghz_remote_new/views/edit_menu.h | 29 + .../external/subghz_remote_new/views/remote.c | 184 +++--- .../external/subghz_remote_new/views/remote.h | 14 +- 37 files changed, 2455 insertions(+), 482 deletions(-) create mode 100644 applications/external/subghz_remote_new/helpers/subrem_presets.c create mode 100644 applications/external/subghz_remote_new/helpers/subrem_presets.h create mode 100644 applications/external/subghz_remote_new/helpers/txrx/Readme.md create mode 100644 applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c create mode 100644 applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h create mode 100644 applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h create mode 100644 applications/external/subghz_remote_new/icons/DolphinNice_96x59.png rename applications/external/subghz_remote_new/icons/{ => remote_scene}/ButtonDown_7x4.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/ButtonLeft_4x7.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/ButtonRight_4x7.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/ButtonUp_7x4.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/Ok_btn_9x9.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/Pin_arrow_up_7x9.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/Pin_cell_13x13.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/Pin_star_7x7.png (100%) rename applications/external/subghz_remote_new/icons/{ => remote_scene}/back_10px.png (100%) create mode 100644 applications/external/subghz_remote_new/icons/subrem_10px.png create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_edit_label.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c create mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c delete mode 100644 applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c create mode 100644 applications/external/subghz_remote_new/views/edit_menu.c create mode 100644 applications/external/subghz_remote_new/views/edit_menu.h diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam index f2cdd25b07..a232fb30f0 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_new/application.fam @@ -3,17 +3,14 @@ App( name="Sub-GHz Remote", apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_app", - cdefines=[ - "APP_SUBGHZREMOTE", - "SUBREM_LIGHT", - ], requires=[ "gui", "dialogs", ], - icon="A_SubGHzRemote_14", - stack_size=4 * 1024, + stack_size=3 * 1024, order=50, - fap_category="Debug", + fap_description="Remote control for transmission multiple *.sub files", + fap_category="Debug", #"Sub-Ghz" fap_icon_assets="icons", + fap_icon="icons/subrem_10px.png", ) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h index b6f752ba0d..779458c203 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h +++ b/applications/external/subghz_remote_new/helpers/subrem_custom_event.h @@ -1,11 +1,25 @@ #pragma once typedef enum { - //SubmenuIndex + SubRemEditMenuStateUP = 0, + SubRemEditMenuStateDOWN, + SubRemEditMenuStateLEFT, + SubRemEditMenuStateRIGHT, + SubRemEditMenuStateOK, +} SubRemEditMenuState; + +typedef enum { + // SubmenuIndex + SubmenuIndexSubRemEditMapFile = 0, + SubmenuIndexSubRemNewMapFile, SubmenuIndexSubRemRemoteView, SubmenuIndexSubRemAbout, - //SubRemCustomEvent + // EditSubmenuIndex + EditSubmenuIndexEditLabel, + EditSubmenuIndexEditFile, + + // SubRemCustomEvent SubRemCustomEventViewRemoteStartUP = 100, SubRemCustomEventViewRemoteStartDOWN, SubRemCustomEventViewRemoteStartLEFT, @@ -14,4 +28,25 @@ typedef enum { SubRemCustomEventViewRemoteBack, SubRemCustomEventViewRemoteStop, SubRemCustomEventViewRemoteForcedStop, + + SubRemCustomEventViewEditMenuBack, + SubRemCustomEventViewEditMenuUP, + SubRemCustomEventViewEditMenuDOWN, + SubRemCustomEventViewEditMenuEdit, + SubRemCustomEventViewEditMenuSave, + + SubRemCustomEventSceneEditsubmenu, + SubRemCustomEventSceneEditLabelInputDone, + SubRemCustomEventSceneEditLabelWidgetAcces, + SubRemCustomEventSceneEditLabelWidgetBack, + + SubRemCustomEventSceneEditOpenSubErrorPopup, + + SubRemCustomEventSceneEditPreviewSaved, + + SubRemCustomEventSceneNewName, + + // // SceneStates + // SubRemSceneOpenMapFileStateOpen, + // SubRemSceneOpenMapFileStateEdit, } SubRemCustomEvent; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/subrem_presets.c b/applications/external/subghz_remote_new/helpers/subrem_presets.c new file mode 100644 index 0000000000..dc298c069a --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/subrem_presets.c @@ -0,0 +1,180 @@ +#include "subrem_presets.h" + +#define TAG "SubRemPresets" + +SubRemSubFilePreset* subrem_sub_file_preset_alloc() { + SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); + + sub_preset->fff_data = flipper_format_string_alloc(); + sub_preset->file_path = furi_string_alloc(); + sub_preset->protocaol_name = furi_string_alloc(); + sub_preset->label = furi_string_alloc(); + + sub_preset->freq_preset.name = furi_string_alloc(); + + sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; + + return sub_preset; +} + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_free(sub_preset->label); + furi_string_free(sub_preset->protocaol_name); + furi_string_free(sub_preset->file_path); + flipper_format_free(sub_preset->fff_data); + + furi_string_free(sub_preset->freq_preset.name); + + free(sub_preset); +} + +void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { + furi_assert(sub_preset); + + furi_string_set_str(sub_preset->label, ""); + furi_string_reset(sub_preset->protocaol_name); + furi_string_reset(sub_preset->file_path); + + Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); + stream_clean(fff_data_stream); + + sub_preset->type = SubGhzProtocolTypeUnknown; + sub_preset->load_state = SubRemLoadSubStateNotSet; +} + +SubRemLoadSubState subrem_sub_preset_load( + SubRemSubFilePreset* sub_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file) { + furi_assert(sub_preset); + furi_assert(txrx); + furi_assert(fff_data_file); + + Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); + + SubRemLoadSubState ret; + FuriString* temp_str = furi_string_alloc(); + uint32_t temp_data32; + uint32_t repeat = 200; + + ret = SubRemLoadSubStateError; + + do { + stream_clean(fff_data_stream); + if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { + FURI_LOG_E(TAG, "Missing or incorrect header"); + break; + } + + if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || + (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && + temp_data32 == SUBGHZ_KEY_FILE_VERSION) { + } else { + FURI_LOG_E(TAG, "Type or version mismatch"); + break; + } + + SubGhzSetting* setting = subghz_txrx_get_setting(txrx); + + //Load frequency or using default from settings + ret = SubRemLoadSubStateErrorFreq; + if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { + FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); + sub_preset->freq_preset.frequency = subghz_setting_get_default_frequency(setting); + } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { + FURI_LOG_E(TAG, "This frequency can only be used for RX"); + break; + } + sub_preset->freq_preset.frequency = temp_data32; + + //Load preset + ret = SubRemLoadSubStateErrorMod; + if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { + FURI_LOG_E(TAG, "Missing Preset"); + break; + } + + furi_string_set_str( + temp_str, subghz_txrx_get_preset_name(txrx, furi_string_get_cstr(temp_str))); + if(!strcmp(furi_string_get_cstr(temp_str), "")) { + break; + } + + if(!strcmp(furi_string_get_cstr(temp_str), "CUSTOM")) { + FURI_LOG_E(TAG, "CUSTOM preset is not supported"); + break; + // TODO Custom preset loading logic if need + // sub_preset->freq_preset.preset_index = + // subghz_setting_get_inx_preset_by_name(setting, furi_string_get_cstr(temp_str)); + } + + furi_string_set(sub_preset->freq_preset.name, temp_str); + + // Load protocol + ret = SubRemLoadSubStateErrorProtocol; + if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + + FlipperFormat* fff_data = sub_preset->fff_data; + if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { + //if RAW + subghz_protocol_raw_gen_fff_data( + fff_data, furi_string_get_cstr(sub_preset->file_path)); + } else { + stream_copy_full( + flipper_format_get_raw_stream(fff_data_file), + flipper_format_get_raw_stream(fff_data)); + } + + if(subghz_txrx_load_decoder_by_name_protocol(txrx, furi_string_get_cstr(temp_str))) { + SubGhzProtocolStatus status = + subghz_protocol_decoder_base_deserialize(subghz_txrx_get_decoder(txrx), fff_data); + if(status != SubGhzProtocolStatusOk) { + break; + } + } else { + FURI_LOG_E(TAG, "Protocol not found"); + break; + } + + const SubGhzProtocol* protocol = subghz_txrx_get_decoder(txrx)->protocol; + + if(protocol->flag & SubGhzProtocolFlag_Send) { + if((protocol->type == SubGhzProtocolTypeStatic) || + (protocol->type == SubGhzProtocolTypeDynamic) || + // TODO: BINRAW It probably works, but checks are needed. + // (protocol->type == SubGhzProtocolTypeBinRAW) || + (protocol->type == SubGhzProtocolTypeRAW)) { + sub_preset->type = protocol->type; + } else { + FURI_LOG_E(TAG, "Unsuported Protocol"); + break; + } + + furi_string_set(sub_preset->protocaol_name, temp_str); + } else { + FURI_LOG_E(TAG, "Protocol does not support transmission"); + break; + } + + if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + + ret = SubRemLoadSubStateOK; + +#if FURI_DEBUG + FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); +#endif + } while(false); + + furi_string_free(temp_str); + sub_preset->load_state = ret; + return ret; +} diff --git a/applications/external/subghz_remote_new/helpers/subrem_presets.h b/applications/external/subghz_remote_new/helpers/subrem_presets.h new file mode 100644 index 0000000000..d66181b90d --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/subrem_presets.h @@ -0,0 +1,39 @@ +#pragma once + +#include "subrem_types.h" +#include "txrx/subghz_txrx.h" + +#include +#include + +typedef struct { + FuriString* name; + uint32_t frequency; + // size_t preset_index; // Need for custom preset +} FreqPreset; + +// Sub File preset +typedef struct { + FlipperFormat* fff_data; + FreqPreset freq_preset; + FuriString* file_path; + FuriString* protocaol_name; + FuriString* label; + SubGhzProtocolType type; + SubRemLoadSubState load_state; +} SubRemSubFilePreset; + +typedef struct { + SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; +} SubRemMapPreset; + +SubRemSubFilePreset* subrem_sub_file_preset_alloc(); + +void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); + +void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset); + +SubRemLoadSubState subrem_sub_preset_load( + SubRemSubFilePreset* sub_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file); diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_new/helpers/subrem_types.h index 13b42897f6..b43f8499d8 100644 --- a/applications/external/subghz_remote_new/helpers/subrem_types.h +++ b/applications/external/subghz_remote_new/helpers/subrem_types.h @@ -3,9 +3,8 @@ #include #include -// TODO: File version/type logic -// #define SUBREM_APP_APP_FILE_VERSION 1 -// #define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file" +#define SUBREM_APP_APP_FILE_VERSION 1 +#define SUBREM_APP_APP_FILE_TYPE "Flipper SubRem Map file" #define SUBREM_APP_EXTENSION ".txt" typedef enum { @@ -18,17 +17,19 @@ typedef enum { } SubRemSubKeyName; typedef enum { - SubRemViewSubmenu, - SubRemViewWidget, - SubRemViewPopup, - SubRemViewTextInput, + SubRemViewIDSubmenu, + SubRemViewIDWidget, + SubRemViewIDPopup, + SubRemViewIDTextInput, SubRemViewIDRemote, + SubRemViewIDEditMenu, } SubRemViewID; typedef enum { - SubRemLoadSubStateNotSet, + SubRemLoadSubStateNotSet = 0, SubRemLoadSubStatePreloaded, SubRemLoadSubStateError, + SubRemLoadSubStateErrorIncorectPath, SubRemLoadSubStateErrorNoFile, SubRemLoadSubStateErrorFreq, SubRemLoadSubStateErrorMod, diff --git a/applications/external/subghz_remote_new/helpers/txrx/Readme.md b/applications/external/subghz_remote_new/helpers/txrx/Readme.md new file mode 100644 index 0000000000..9181601980 --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/txrx/Readme.md @@ -0,0 +1,4 @@ +This is part of the official `SubGhz` app from [flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware/tree/3217f286f03da119398586daf94c0723d28b872a/applications/main/subghz) + +With changes from [unleashed-firmware +](https://github.com/DarkFlippers/unleashed-firmware/tree/3eac6ccd48a3851cf5d63bf7899b387a293e5319/applications/main/subghz) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c new file mode 100644 index 0000000000..c1f519ba0d --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c @@ -0,0 +1,563 @@ +#include "subghz_txrx_i.h" +#include + +#define TAG "SubGhz" + +SubGhzTxRx* subghz_txrx_alloc() { + SubGhzTxRx* instance = malloc(sizeof(SubGhzTxRx)); + instance->setting = subghz_setting_alloc(); + subghz_setting_load(instance->setting, EXT_PATH("subghz/assets/setting_user")); + + instance->preset = malloc(sizeof(SubGhzRadioPreset)); + instance->preset->name = furi_string_alloc(); + subghz_txrx_set_preset( + instance, "AM650", subghz_setting_get_default_frequency(instance->setting), NULL, 0); + + instance->txrx_state = SubGhzTxRxStateSleep; + + subghz_txrx_hopper_set_state(instance, SubGhzHopperStateOFF); + subghz_txrx_speaker_set_state(instance, SubGhzSpeakerStateDisable); + subghz_txrx_set_debug_pin_state(instance, false); + + instance->worker = subghz_worker_alloc(); + instance->fff_data = flipper_format_string_alloc(); + + instance->environment = subghz_environment_alloc(); + instance->is_database_loaded = subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); + subghz_environment_load_keystore( + instance->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); + subghz_environment_set_came_atomo_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/came_atomo")); + subghz_environment_set_alutech_at_4n_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/alutech_at_4n")); + subghz_environment_set_nice_flor_s_rainbow_table_file_name( + instance->environment, EXT_PATH("subghz/assets/nice_flor_s")); + subghz_environment_set_protocol_registry( + instance->environment, (void*)&subghz_protocol_registry); + instance->receiver = subghz_receiver_alloc_init(instance->environment); + + subghz_worker_set_overrun_callback( + instance->worker, (SubGhzWorkerOverrunCallback)subghz_receiver_reset); + subghz_worker_set_pair_callback( + instance->worker, (SubGhzWorkerPairCallback)subghz_receiver_decode); + subghz_worker_set_context(instance->worker, instance->receiver); + + return instance; +} + +void subghz_txrx_free(SubGhzTxRx* instance) { + furi_assert(instance); + + subghz_worker_free(instance->worker); + subghz_receiver_free(instance->receiver); + subghz_environment_free(instance->environment); + flipper_format_free(instance->fff_data); + furi_string_free(instance->preset->name); + subghz_setting_free(instance->setting); + free(instance->preset); + free(instance); +} + +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->is_database_loaded; +} + +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size) { + furi_assert(instance); + furi_string_set(instance->preset->name, preset_name); + SubGhzRadioPreset* preset = instance->preset; + preset->frequency = frequency; + preset->data = preset_data; + preset->data_size = preset_data_size; +} + +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset) { + UNUSED(instance); + const char* preset_name = ""; + if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { + preset_name = "AM270"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { + preset_name = "AM650"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { + preset_name = "FM238"; + } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { + preset_name = "FM476"; + } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { + preset_name = "CUSTOM"; + } else { + FURI_LOG_E(TAG, "Unknown preset"); + } + return preset_name; +} + +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance) { + furi_assert(instance); + return *instance->preset; +} + +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name) { + furi_assert(instance); + SubGhzRadioPreset* preset = instance->preset; + if(frequency != NULL) { + furi_string_printf( + frequency, + "%03ld.%02ld", + preset->frequency / 1000000 % 1000, + preset->frequency / 10000 % 100); + } + if(modulation != NULL) { + if(long_name) { + furi_string_printf(modulation, "%s", furi_string_get_cstr(preset->name)); + } else { + furi_string_printf(modulation, "%.2s", furi_string_get_cstr(preset->name)); + } + } +} + +static void subghz_txrx_begin(SubGhzTxRx* instance, uint8_t* preset_data) { + furi_assert(instance); + furi_hal_subghz_reset(); + furi_hal_subghz_idle(); + furi_hal_subghz_load_custom_preset(preset_data); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static uint32_t subghz_txrx_rx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect RX frequency."); + } + furi_assert( + instance->txrx_state != SubGhzTxRxStateRx && instance->txrx_state != SubGhzTxRxStateSleep); + + furi_hal_subghz_idle(); + uint32_t value = furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_init(furi_hal_subghz.cc1101_g0_pin, GpioModeInput, GpioPullNo, GpioSpeedLow); + furi_hal_subghz_flush_rx(); + subghz_txrx_speaker_on(instance); + furi_hal_subghz_rx(); + + furi_hal_subghz_start_async_rx(subghz_worker_rx_callback, instance->worker); + subghz_worker_start(instance->worker); + instance->txrx_state = SubGhzTxRxStateRx; + return value; +} + +static void subghz_txrx_idle(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +static void subghz_txrx_rx_end(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateRx); + + if(subghz_worker_is_running(instance->worker)) { + subghz_worker_stop(instance->worker); + furi_hal_subghz_stop_async_rx(); + } + furi_hal_subghz_idle(); + subghz_txrx_speaker_off(instance); + instance->txrx_state = SubGhzTxRxStateIDLE; +} + +void subghz_txrx_sleep(SubGhzTxRx* instance) { + furi_assert(instance); + furi_hal_subghz_sleep(); + instance->txrx_state = SubGhzTxRxStateSleep; +} + +static bool subghz_txrx_tx(SubGhzTxRx* instance, uint32_t frequency) { + furi_assert(instance); + if(!furi_hal_subghz_is_frequency_valid(frequency)) { + furi_crash("SubGhz: Incorrect TX frequency."); + } + furi_assert(instance->txrx_state != SubGhzTxRxStateSleep); + furi_hal_subghz_idle(); + furi_hal_subghz_set_frequency_and_path(frequency); + furi_hal_gpio_write(furi_hal_subghz.cc1101_g0_pin, false); + furi_hal_gpio_init( + furi_hal_subghz.cc1101_g0_pin, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + bool ret = furi_hal_subghz_tx(); + if(ret) { + subghz_txrx_speaker_on(instance); + instance->txrx_state = SubGhzTxRxStateTx; + } + + return ret; +} + +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format) { + furi_assert(instance); + furi_assert(flipper_format); + + subghz_txrx_stop(instance); + + SubGhzTxRxStartTxState ret = SubGhzTxRxStartTxStateErrorParserOthers; + FuriString* temp_str = furi_string_alloc(); + uint32_t repeat = 200; + do { + if(!flipper_format_rewind(flipper_format)) { + FURI_LOG_E(TAG, "Rewind error"); + break; + } + if(!flipper_format_read_string(flipper_format, "Protocol", temp_str)) { + FURI_LOG_E(TAG, "Missing Protocol"); + break; + } + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + ret = SubGhzTxRxStartTxStateOk; + + SubGhzRadioPreset* preset = instance->preset; + instance->transmitter = + subghz_transmitter_alloc_init(instance->environment, furi_string_get_cstr(temp_str)); + + if(instance->transmitter) { + if(subghz_transmitter_deserialize(instance->transmitter, flipper_format) == + SubGhzProtocolStatusOk) { + if(strcmp(furi_string_get_cstr(preset->name), "") != 0) { + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + instance->setting, furi_string_get_cstr(preset->name))); + if(preset->frequency) { + if(!subghz_txrx_tx(instance, preset->frequency)) { + FURI_LOG_E(TAG, "Only Rx"); + ret = SubGhzTxRxStartTxStateErrorOnlyRx; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + } else { + FURI_LOG_E( + TAG, "Unknown name preset \" %s \"", furi_string_get_cstr(preset->name)); + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + + if(ret == SubGhzTxRxStartTxStateOk) { + //Start TX + furi_hal_subghz_start_async_tx( + subghz_transmitter_yield, instance->transmitter); + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + } else { + ret = SubGhzTxRxStartTxStateErrorParserOthers; + } + if(ret != SubGhzTxRxStartTxStateOk) { + subghz_transmitter_free(instance->transmitter); + if(instance->txrx_state != SubGhzTxRxStateIDLE) { + subghz_txrx_idle(instance); + } + } + + } while(false); + furi_string_free(temp_str); + return ret; +} + +void subghz_txrx_rx_start(SubGhzTxRx* instance) { + furi_assert(instance); + subghz_txrx_stop(instance); + subghz_txrx_begin( + instance, + subghz_setting_get_preset_data_by_name( + subghz_txrx_get_setting(instance), furi_string_get_cstr(instance->preset->name))); + subghz_txrx_rx(instance, instance->preset->frequency); +} + +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context) { + furi_assert(instance); + instance->need_save_callback = callback; + instance->need_save_context = context; +} + +static void subghz_txrx_tx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + furi_assert(instance->txrx_state == SubGhzTxRxStateTx); + //Stop TX + furi_hal_subghz_stop_async_tx(); + subghz_transmitter_stop(instance->transmitter); + subghz_transmitter_free(instance->transmitter); + + //if protocol dynamic then we save the last upload + if(instance->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) { + if(instance->need_save_callback) { + instance->need_save_callback(instance->need_save_context); + } + } + subghz_txrx_idle(instance); + subghz_txrx_speaker_off(instance); + //Todo: Show message + // notification_message(notifications, &sequence_reset_red); +} + +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->fff_data; +} + +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->setting; +} + +void subghz_txrx_stop(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->txrx_state) { + case SubGhzTxRxStateTx: + subghz_txrx_tx_stop(instance); + subghz_txrx_speaker_unmute(instance); + break; + case SubGhzTxRxStateRx: + subghz_txrx_rx_end(instance); + subghz_txrx_speaker_mute(instance); + break; + + default: + break; + } +} + +void subghz_txrx_hopper_update(SubGhzTxRx* instance) { + furi_assert(instance); + + switch(instance->hopper_state) { + case SubGhzHopperStateOFF: + case SubGhzHopperStatePause: + return; + case SubGhzHopperStateRSSITimeOut: + if(instance->hopper_timeout != 0) { + instance->hopper_timeout--; + return; + } + break; + default: + break; + } + float rssi = -127.0f; + if(instance->hopper_state != SubGhzHopperStateRSSITimeOut) { + // See RSSI Calculation timings in CC1101 17.3 RSSI + rssi = furi_hal_subghz_get_rssi(); + + // Stay if RSSI is high enough + if(rssi > -90.0f) { + instance->hopper_timeout = 10; + instance->hopper_state = SubGhzHopperStateRSSITimeOut; + return; + } + } else { + instance->hopper_state = SubGhzHopperStateRunning; + } + // Select next frequency + if(instance->hopper_idx_frequency < + subghz_setting_get_hopper_frequency_count(instance->setting) - 1) { + instance->hopper_idx_frequency++; + } else { + instance->hopper_idx_frequency = 0; + } + + if(instance->txrx_state == SubGhzTxRxStateRx) { + subghz_txrx_rx_end(instance); + }; + if(instance->txrx_state == SubGhzTxRxStateIDLE) { + subghz_receiver_reset(instance->receiver); + instance->preset->frequency = + subghz_setting_get_hopper_frequency(instance->setting, instance->hopper_idx_frequency); + subghz_txrx_rx(instance, instance->preset->frequency); + } +} + +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->hopper_state; +} + +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state) { + furi_assert(instance); + instance->hopper_state = state; +} + +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStatePause) { + instance->hopper_state = SubGhzHopperStateRunning; + } +} + +void subghz_txrx_hopper_pause(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->hopper_state == SubGhzHopperStateRunning) { + instance->hopper_state = SubGhzHopperStatePause; + } +} + +void subghz_txrx_speaker_on(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_acquire(30)) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } else { + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_off(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state != SubGhzSpeakerStateDisable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + furi_hal_speaker_release(); + if(instance->speaker_state == SubGhzSpeakerStateShutdown) + instance->speaker_state = SubGhzSpeakerStateDisable; + } + } +} + +void subghz_txrx_speaker_mute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(NULL); + } + } + } +} + +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance) { + furi_assert(instance); + if(instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_ibutton); + } + if(instance->speaker_state == SubGhzSpeakerStateEnable) { + if(furi_hal_speaker_is_mine()) { + if(!instance->debug_pin_state) { + furi_hal_subghz_set_async_mirror_pin(&gpio_speaker); + } + } + } +} + +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state) { + furi_assert(instance); + instance->speaker_state = state; +} + +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->speaker_state; +} + +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol) { + furi_assert(instance); + furi_assert(name_protocol); + bool res = false; + instance->decoder_result = + subghz_receiver_search_decoder_base_by_name(instance->receiver, name_protocol); + if(instance->decoder_result) { + res = true; + } + return res; +} + +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->decoder_result; +} + +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance) { + furi_assert(instance); + return ( + (instance->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == + SubGhzProtocolFlag_Save); +} + +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type) { + furi_assert(instance); + const SubGhzProtocol* protocol = instance->decoder_result->protocol; + if(check_type) { + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize && protocol->type == SubGhzProtocolTypeStatic); + } + return ( + ((protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && + protocol->encoder->deserialize); +} + +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter) { + furi_assert(instance); + subghz_receiver_set_filter(instance->receiver, filter); +} + +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context) { + subghz_receiver_set_rx_callback(instance->receiver, callback, context); +} + +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context) { + subghz_protocol_raw_file_encoder_worker_set_callback_end( + (SubGhzProtocolEncoderRAW*)subghz_transmitter_get_protocol_instance(instance->transmitter), + callback, + context); +} + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state) { + furi_assert(instance); + instance->debug_pin_state = state; +} + +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->debug_pin_state; +} + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance) { + furi_assert(instance); + return instance->receiver; +} \ No newline at end of file diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h new file mode 100644 index 0000000000..b2ebcc5f30 --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h @@ -0,0 +1,318 @@ +#pragma once + +#include +#include +#include +#include +#include + +typedef struct SubGhzTxRx SubGhzTxRx; + +typedef void (*SubGhzTxRxNeedSaveCallback)(void* context); + +typedef enum { + SubGhzTxRxStartTxStateOk, + SubGhzTxRxStartTxStateErrorOnlyRx, + SubGhzTxRxStartTxStateErrorParserOthers, +} SubGhzTxRxStartTxState; + +// Type from subghz_types.h need for txrx working +/** SubGhzTxRx state */ +typedef enum { + SubGhzTxRxStateIDLE, + SubGhzTxRxStateRx, + SubGhzTxRxStateTx, + SubGhzTxRxStateSleep, +} SubGhzTxRxState; + +/** SubGhzHopperState state */ +typedef enum { + SubGhzHopperStateOFF, + SubGhzHopperStateRunning, + SubGhzHopperStatePause, + SubGhzHopperStateRSSITimeOut, +} SubGhzHopperState; + +/** SubGhzSpeakerState state */ +typedef enum { + SubGhzSpeakerStateDisable, + SubGhzSpeakerStateShutdown, + SubGhzSpeakerStateEnable, +} SubGhzSpeakerState; + +/** + * Allocate SubGhzTxRx + * + * @return SubGhzTxRx* pointer to SubGhzTxRx + */ +SubGhzTxRx* subghz_txrx_alloc(); + +/** + * Free SubGhzTxRx + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_free(SubGhzTxRx* instance); + +/** + * Check if the database is loaded + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if the database is loaded + */ +bool subghz_txrx_is_database_loaded(SubGhzTxRx* instance); + +/** + * Set preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset_name Name of preset + * @param frequency Frequency in Hz + * @param preset_data Data of preset + * @param preset_data_size Size of preset data + */ +void subghz_txrx_set_preset( + SubGhzTxRx* instance, + const char* preset_name, + uint32_t frequency, + uint8_t* preset_data, + size_t preset_data_size); + +/** + * Get name of preset + * + * @param instance Pointer to a SubGhzTxRx + * @param preset String of preset + * @return const char* Name of preset + */ +const char* subghz_txrx_get_preset_name(SubGhzTxRx* instance, const char* preset); + +/** + * Get of preset + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzRadioPreset Preset + */ +SubGhzRadioPreset subghz_txrx_get_preset(SubGhzTxRx* instance); + +/** + * Get string frequency and modulation + * + * @param instance Pointer to a SubGhzTxRx + * @param frequency Pointer to a string frequency + * @param modulation Pointer to a string modulation + */ +void subghz_txrx_get_frequency_and_modulation( + SubGhzTxRx* instance, + FuriString* frequency, + FuriString* modulation, + bool long_name); + +/** + * Start TX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + * @param flipper_format Pointer to a FlipperFormat + * @return SubGhzTxRxStartTxState + */ +SubGhzTxRxStartTxState subghz_txrx_tx_start(SubGhzTxRx* instance, FlipperFormat* flipper_format); + +/** + * Start RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_rx_start(SubGhzTxRx* instance); + +/** + * Stop TX/RX CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_stop(SubGhzTxRx* instance); + +/** + * Set sleep mode CC1101 + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_sleep(SubGhzTxRx* instance); + +/** + * Update frequency CC1101 in automatic mode (hopper) + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_update(SubGhzTxRx* instance); + +/** + * Get state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzHopperState + */ +SubGhzHopperState subghz_txrx_hopper_get_state(SubGhzTxRx* instance); + +/** + * Set state hopper + * + * @param instance Pointer to a SubGhzTxRx + * @param state State hopper + */ +void subghz_txrx_hopper_set_state(SubGhzTxRx* instance, SubGhzHopperState state); + +/** + * Unpause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_unpause(SubGhzTxRx* instance); + +/** + * Set pause hopper + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_hopper_pause(SubGhzTxRx* instance); + +/** + * Speaker on + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_on(SubGhzTxRx* instance); + +/** + * Speaker off + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_off(SubGhzTxRx* instance); + +/** + * Speaker mute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_mute(SubGhzTxRx* instance); + +/** + * Speaker unmute + * + * @param instance Pointer to a SubGhzTxRx + */ +void subghz_txrx_speaker_unmute(SubGhzTxRx* instance); + +/** + * Set state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @param state State speaker + */ +void subghz_txrx_speaker_set_state(SubGhzTxRx* instance, SubGhzSpeakerState state); + +/** + * Get state speaker + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSpeakerState + */ +SubGhzSpeakerState subghz_txrx_speaker_get_state(SubGhzTxRx* instance); + +/** + * load decoder by name protocol + * + * @param instance Pointer to a SubGhzTxRx + * @param name_protocol Name protocol + * @return bool True if the decoder is loaded + */ +bool subghz_txrx_load_decoder_by_name_protocol(SubGhzTxRx* instance, const char* name_protocol); + +/** + * Get decoder + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzProtocolDecoderBase* Pointer to a SubGhzProtocolDecoderBase + */ +SubGhzProtocolDecoderBase* subghz_txrx_get_decoder(SubGhzTxRx* instance); + +/** + * Set callback for save data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for save data + * @param context Context for callback + */ +void subghz_txrx_set_need_save_callback( + SubGhzTxRx* instance, + SubGhzTxRxNeedSaveCallback callback, + void* context); + +/** + * Get pointer to a load data key + * + * @param instance Pointer to a SubGhzTxRx + * @return FlipperFormat* + */ +FlipperFormat* subghz_txrx_get_fff_data(SubGhzTxRx* instance); + +/** + * Get pointer to a SugGhzSetting + * + * @param instance Pointer to a SubGhzTxRx + * @return SubGhzSetting* + */ +SubGhzSetting* subghz_txrx_get_setting(SubGhzTxRx* instance); + +/** + * Is it possible to save this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to save this protocol + */ +bool subghz_txrx_protocol_is_serializable(SubGhzTxRx* instance); + +/** + * Is it possible to send this protocol + * + * @param instance Pointer to a SubGhzTxRx + * @return bool True if it is possible to send this protocol + */ +bool subghz_txrx_protocol_is_transmittable(SubGhzTxRx* instance, bool check_type); + +/** + * Set filter, what types of decoder to use + * + * @param instance Pointer to a SubGhzTxRx + * @param filter Filter + */ +void subghz_txrx_receiver_set_filter(SubGhzTxRx* instance, SubGhzProtocolFlag filter); + +/** + * Set callback for receive data + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for receive data + * @param context Context for callback + */ +void subghz_txrx_set_rx_calback( + SubGhzTxRx* instance, + SubGhzReceiverCallback callback, + void* context); + +/** + * Set callback for Raw decoder, end of data transfer + * + * @param instance Pointer to a SubGhzTxRx + * @param callback Callback for Raw decoder, end of data transfer + * @param context Context for callback + */ +void subghz_txrx_set_raw_file_encoder_worker_callback_end( + SubGhzTxRx* instance, + SubGhzProtocolEncoderRAWCallbackEnd callback, + void* context); + +void subghz_txrx_set_debug_pin_state(SubGhzTxRx* instance, bool state); +bool subghz_txrx_get_debug_pin_state(SubGhzTxRx* instance); + +SubGhzReceiver* subghz_txrx_get_receiver(SubGhzTxRx* instance); // TODO use only in DecodeRaw diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h new file mode 100644 index 0000000000..680d271585 --- /dev/null +++ b/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h @@ -0,0 +1,29 @@ + +#pragma once +#include "subghz_txrx.h" + +struct SubGhzTxRx { + SubGhzWorker* worker; + + SubGhzEnvironment* environment; + SubGhzReceiver* receiver; + SubGhzTransmitter* transmitter; + SubGhzProtocolDecoderBase* decoder_result; + FlipperFormat* fff_data; + + SubGhzRadioPreset* preset; + SubGhzSetting* setting; + + uint8_t hopper_timeout; + uint8_t hopper_idx_frequency; + bool is_database_loaded; + SubGhzHopperState hopper_state; + + SubGhzTxRxState txrx_state; + SubGhzSpeakerState speaker_state; + + SubGhzTxRxNeedSaveCallback need_save_callback; + void* need_save_context; + + bool debug_pin_state; +}; \ No newline at end of file diff --git a/applications/external/subghz_remote_new/icons/DolphinNice_96x59.png b/applications/external/subghz_remote_new/icons/DolphinNice_96x59.png new file mode 100644 index 0000000000000000000000000000000000000000..a299d3630239b4486e249cc501872bed5996df3b GIT binary patch literal 2459 zcmbVO3s4i+8V(M(gEFORwSrA`4O0uPn|M|5y* zB*aMDxC&7(gP9JN;POOi-9khrC>Z9YJs2U!LnVcQEEC0fDtKo&ILlzb30%M}3J^;~ zv7RzcsilOs4Mq@tD*&R;!LMSk2A~{(`HK9|hQBqEX)3sQr9Je6SZU*F-^fD-p+~Hs; zHLkO%v?>ZoxEv+F#whudr%615FkA0DYR0tMEo}3OOY#xecLWe>xV?u5KtSmC^ z7)Fmj6gjfKstiEV-*Cxbbb+&rRWuI_rBJ)ybs_f1Rn&f2>q3pYwI^|J(hdn{j{0EZIm_F zpIyIWLsRUgOItR-dUbVd|6Zo=_BU_Tj4|{{jxO#=JH4o8er(5{!nZD_j4}MH&zh~9 zVLC~y(0-D6GO0ghZD8BYzP?o{>22~lT6^d@X{SwQ8vrNY-PPIMajIwC)`s14Ep72@ zeq7YOzM`?U{+W)ocXBr`eSOcpk?Rxc=ou5&)fWW|pD};-Z0mvk9}=&`Rb&y<77W~a z(>6YM;6Y5aIU~JKZ}mQZynKHiSTQ#Bczn@&jTiN^?vPJ(jhm7cXLx0oum5P$`TceG zU+wR;OO^)8CVlnM)5p$CO&e94KJt>HccCaHGusmW_b`T6m| z-R6V6Db1pErTot?^d22ojm+2>_)FbD`_+WbDGMx9f@hO27maS2`csiV(D&Fs`PS2& zvrq18du_&zXID(!KIxsU$)iuTYuZ?zmYiP&n&i@Be{IdbS-jA2c0QAlu5NXQv_0K< z3Hvs4eeu6B7yD&CNT~gIkMV&UkRU=V!iQ(+_(O&u^ah$+s{_yn(yBYeD40HeU{xGsIT6W Zfq!wOp!QCbE6;07#-3sX@sAxkg$U?hnu$6%_P+PX_Jv(ud zLf1xG|CwUz?7R1Up5OC4zxVgNce*W&4YheW_vK(1mglK+H=%$1JZE+m`hA@F<1zI2 zyA8fptqH{ONK}=TAjGw<2*hDRkufZBKGgVD-U({Lf_l{mhyV1gGrhn5dOvmG&rb;X|2#O* z`;Gdu`y8=lFC6>o;MdlzEhu;(gUPC_z|AEGi;B+`t?Ze5z3-kKC+@xe!rsi0?9s|K zy?-daKNrL9+N8K#jUJb4ydqS`GmmU@)cv;7aPpz%>TUZsFY*}}-;x*iZ59ty6_jpT zvujoMQ}z8jJ+AG;!%Gj}Yq-_gD;(ypTplW&z40q}pQ&N1scCq0d(~q_cR%sbwf8Sv zdVdlA`l;oI1plLZ-jYiT3faL`zr6A#=Lo=7=AJsu{N?^-b1q)%coKW)>T~u}qi^rn z-7>H`clPEJwEVR7TGqAGdqR;5OY#pr*E?^={1s1Y&f(g=vM=|qHywW9AEyugs9|9K z_qUv^T38l3y>(BG-D_BB`RVoV^}JI09`V|mBd`AW<~wBWyCXky1n0|1Nlg+*V)QGN;EdcVFdq|MubW(V_Tn9{lz<&(!Cf?0&8A zl@E$Ck9Ky~46J|Y$whnDXUy8sU3Tos>?t>Un9|+}sNpj`p?cz$4F;W6I^yu1td=)j zwphHBH{ybAO5KJiY~Ik|6F0PrHpy5~o?}l42p|MCfG0x1a7;)zj7eMpo$JG-5l@?` zHXBJXB*PHMf{1m6HIN{}u@W63h2e%VF{(r~MGfORCh)5rn!{*B^Z0mvp@`R;h7ZTa zSU`M`2@oM^6GetXP{HeN+v@{V%k5_5e+8G zkwg*(VF;PVP*i$K$XbuLG3}vK5Kuyqq!%K4ie;ot)zny<8cCZ^NiaQ~ENpU0nj%lI zJjF+!xy>BKy>oC09YBCl_0@MKq5HSOc8#H zHxrPt@G@uPXxUw}=@F^kKtO1=<+RE`fZLx72 zM^h}%PZ&K2qcJ389h0U^tT{O|!J$hHs!^{hL5Gn|PU-6=pgIxrK<@yAog7DH3a%&w z8g!!r!BMD#C>udrd^9VVErOXZqga7TC7!lcqdrv)I*fX4xSm29%!}Gu0vbreA!k;g z%|4nF%vOQs$|!0w97;_$K_%JJIG$`y z0f?!B#blXMGE;<>npEzfp3l7GX_S~MYjF^T&H&=qVRY(yC*C;TeK^CKEcntEB`m4& z*s`e!#M_|0il0b3`57vUflm0by2LgR4nVX&k8KG5wO*Mw+x#3L%ravoDAo)K9*8VK z`z@R#$`oXol=A*h>SY-g(0){rAj zX|i`eX-Qc`CULv;$ClJi>UW`W?b^xP)oq_>=<%(|iFP_&{;^5&uL6OoA}L2u$;}G@ zRN$B(Zj5Yq}83M;=f=r9w8MiVD2l{4`U z0fy0oX&k*FI5pSMi{36|`Ri-l*r@*9d2H`fXk<>LZgmX9OeOkpSK|4KPBfUUdA!xx z?`7r}mf + +typedef enum { + SubRemSceneEditLabelStateTextInput, + SubRemSceneEditLabelStateWidget, +} SubRemSceneEditLabelState; + +void subrem_scene_edit_label_text_input_callback(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event( + app->view_dispatcher, SubRemCustomEventSceneEditLabelInputDone); +} + +void subrem_scene_edit_label_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + if((result == GuiButtonTypeCenter) && (type == InputTypeShort)) { + view_dispatcher_send_custom_event( + app->view_dispatcher, SubRemCustomEventSceneEditLabelWidgetAcces); + } else if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) { + view_dispatcher_send_custom_event( + app->view_dispatcher, SubRemCustomEventSceneEditLabelWidgetBack); + } +} + +void subrem_scene_edit_label_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; + + FuriString* temp_str = furi_string_alloc(); + + if(furi_string_empty(sub_preset->label)) { + if(furi_string_empty(sub_preset->file_path)) { + path_extract_filename(sub_preset->file_path, temp_str, true); + strcpy(app->file_name_tmp, furi_string_get_cstr(temp_str)); + } else { + strcpy(app->file_name_tmp, ""); + } + } else { + strcpy(app->file_name_tmp, furi_string_get_cstr(sub_preset->label)); + } + + TextInput* text_input = app->text_input; + text_input_set_header_text(text_input, "Label name"); + text_input_set_result_callback( + text_input, + subrem_scene_edit_label_text_input_callback, + app, + app->file_name_tmp, + 25, + false); + + text_input_set_minimum_length(app->text_input, 0); + + widget_add_string_element( + app->widget, 63, 12, AlignCenter, AlignCenter, FontPrimary, "Empty Label Name"); + widget_add_string_element( + app->widget, 63, 32, AlignCenter, AlignCenter, FontSecondary, "Continue?"); + + widget_add_button_element( + app->widget, GuiButtonTypeCenter, "Ok", subrem_scene_edit_label_widget_callback, app); + widget_add_button_element( + app->widget, GuiButtonTypeLeft, "Back", subrem_scene_edit_label_widget_callback, app); + + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneEditLabel, SubRemSceneEditLabelStateTextInput); + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDTextInput); + + furi_string_free(temp_str); +} + +bool subrem_scene_edit_label_on_event(void* context, SceneManagerEvent event) { + SubGhzRemoteApp* app = context; + + FuriString* label = app->map_preset->subs_preset[app->chusen_sub]->label; + + if(event.type == SceneManagerEventTypeBack) { + if(scene_manager_get_scene_state(app->scene_manager, SubRemSceneEditLabel) == + SubRemSceneEditLabelStateWidget) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneEditLabel, SubRemSceneEditLabelStateTextInput); + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDTextInput); + return true; + } else if( + scene_manager_get_scene_state(app->scene_manager, SubRemSceneEditLabel) == + SubRemSceneEditLabelStateTextInput) { + scene_manager_previous_scene(app->scene_manager); + return true; + } + + scene_manager_previous_scene(app->scene_manager); + return true; + } else if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubRemCustomEventSceneEditLabelInputDone) { + if(strcmp(app->file_name_tmp, "") == 0) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneEditLabel, SubRemSceneEditLabelStateWidget); + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDWidget); + + } else { + furi_string_set(label, app->file_name_tmp); + app->map_not_saved = true; + scene_manager_previous_scene(app->scene_manager); + } + return true; + } else if(event.event == SubRemCustomEventSceneEditLabelWidgetAcces) { + furi_string_set(label, app->file_name_tmp); + app->map_not_saved = true; + scene_manager_previous_scene(app->scene_manager); + + return true; + } else if(event.event == SubRemCustomEventSceneEditLabelWidgetBack) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneEditLabel, SubRemSceneEditLabelStateTextInput); + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDTextInput); + + return true; + } + } + return false; +} + +void subrem_scene_edit_label_on_exit(void* context) { + SubGhzRemoteApp* app = context; + + // Clear view + text_input_reset(app->text_input); + widget_reset(app->widget); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c new file mode 100644 index 0000000000..a8882009a8 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c @@ -0,0 +1,123 @@ +#include "../subghz_remote_app_i.h" + +void subrem_scene_edit_menu_callback(SubRemCustomEvent event, void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void subrem_scene_edit_menu_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + if((result == GuiButtonTypeRight) && (type == InputTypeShort)) { + app->map_not_saved = false; + view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventViewEditMenuBack); + } else if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) { + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDEditMenu); + } +} + +static uint8_t subrem_scene_edit_menu_state_to_index(SubRemEditMenuState event_id) { + uint8_t ret = 0; + + if(event_id == SubRemEditMenuStateUP) { + ret = SubRemSubKeyNameUp; + } else if(event_id == SubRemEditMenuStateDOWN) { + ret = SubRemSubKeyNameDown; + } else if(event_id == SubRemEditMenuStateLEFT) { + ret = SubRemSubKeyNameLeft; + } else if(event_id == SubRemEditMenuStateRIGHT) { + ret = SubRemSubKeyNameRight; + } else if(event_id == SubRemEditMenuStateOK) { + ret = SubRemSubKeyNameOk; + } + + return ret; +} + +static void subrem_scene_edit_menu_update_data(SubGhzRemoteApp* app) { + furi_assert(app); + uint8_t index = subrem_scene_edit_menu_state_to_index( + scene_manager_get_scene_state(app->scene_manager, SubRemSceneEditMenu)); + + subrem_view_edit_menu_add_data_to_show( + app->subrem_edit_menu, + index, + app->map_preset->subs_preset[index]->label, + app->map_preset->subs_preset[index]->file_path, + app->map_preset->subs_preset[index]->load_state); +} + +void subrem_scene_edit_menu_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + subrem_view_edit_menu_set_callback( + app->subrem_edit_menu, subrem_scene_edit_menu_callback, app); + + subrem_scene_edit_menu_update_data(app); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDEditMenu); + + Widget* widget = app->widget; + + widget_add_string_element( + widget, 63, 12, AlignCenter, AlignBottom, FontPrimary, "Changes are not saved"); + widget_add_string_element( + widget, 63, 32, AlignCenter, AlignBottom, FontPrimary, "do you want to exit?"); + + widget_add_button_element( + widget, GuiButtonTypeRight, "Yes", subrem_scene_edit_menu_widget_callback, app); + widget_add_button_element( + widget, GuiButtonTypeLeft, "No", subrem_scene_edit_menu_widget_callback, app); +} + +bool subrem_scene_edit_menu_on_event(void* context, SceneManagerEvent event) { + SubGhzRemoteApp* app = context; + + if(event.type == SceneManagerEventTypeBack) { + // Catch widget backEvent + return true; + } + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubRemCustomEventViewEditMenuBack) { + if(app->map_not_saved) { + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDWidget); + } else if(!scene_manager_search_and_switch_to_previous_scene( + app->scene_manager, SubRemSceneStart)) { + scene_manager_stop(app->scene_manager); + view_dispatcher_stop(app->view_dispatcher); + } + + return true; + } else if( + event.event == SubRemCustomEventViewEditMenuUP || + event.event == SubRemCustomEventViewEditMenuDOWN) { + scene_manager_set_scene_state( + app->scene_manager, + SubRemSceneEditMenu, + subrem_view_edit_menu_get_index(app->subrem_edit_menu)); + subrem_scene_edit_menu_update_data(app); + + return true; + } else if(event.event == SubRemCustomEventViewEditMenuEdit) { + app->chusen_sub = subrem_view_edit_menu_get_index(app->subrem_edit_menu); + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneEditSubMenu, EditSubmenuIndexEditLabel); + scene_manager_next_scene(app->scene_manager, SubRemSceneEditSubMenu); + + return true; + } else if(event.event == SubRemCustomEventViewEditMenuSave) { + scene_manager_next_scene(app->scene_manager, SubRemSceneEditPreview); + + return true; + } + } + + return false; +} + +void subrem_scene_edit_menu_on_exit(void* context) { + SubGhzRemoteApp* app = context; + widget_reset(app->widget); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c new file mode 100644 index 0000000000..98a423202e --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c @@ -0,0 +1,74 @@ +#include "../subghz_remote_app_i.h" +#include "../views/remote.h" + +#define TAG "SubRemScenRemote" + +void subghz_scene_edit_preview_save_popup_callback(void* context) { + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event( + app->view_dispatcher, SubRemCustomEventSceneEditPreviewSaved); +} + +void subrem_scene_edit_preview_callback(SubRemCustomEvent event, void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +void subrem_scene_edit_preview_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + // Setup view + Popup* popup = app->popup; + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); + popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, app); + popup_set_callback(popup, subghz_scene_edit_preview_save_popup_callback); + popup_enable_timeout(popup); + + subrem_view_remote_update_data_labels(app->subrem_remote_view, app->map_preset->subs_preset); + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateOFF, 0); + + subrem_view_remote_set_callback( + app->subrem_remote_view, subrem_scene_edit_preview_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDRemote); +} + +bool subrem_scene_edit_preview_on_event(void* context, SceneManagerEvent event) { + SubGhzRemoteApp* app = context; + + if(event.type == SceneManagerEventTypeBack || + (event.type == SceneManagerEventTypeCustom && + (event.event == SubRemCustomEventViewRemoteStartLEFT || + event.event == SubRemCustomEventViewRemoteForcedStop))) { + scene_manager_previous_scene(app->scene_manager); + return true; + } else if( + event.type == SceneManagerEventTypeCustom && + (event.event == SubRemCustomEventViewRemoteStartRIGHT || + event.event == SubRemCustomEventViewRemoteStartOK)) { + if(subrem_save_map_to_file(app)) { + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDPopup); + app->map_not_saved = false; + return true; + } + // TODO error screen + return true; + } else if( + event.type == SceneManagerEventTypeCustom && + event.event == SubRemCustomEventSceneEditPreviewSaved) { + scene_manager_search_and_switch_to_previous_scene(app->scene_manager, SubRemSceneEditMenu); + } + // } else if(event.type == SceneManagerEventTypeTick) { + // } + return false; +} + +void subrem_scene_edit_preview_on_exit(void* context) { + SubGhzRemoteApp* app = context; + + subrem_view_remote_set_state(app->subrem_remote_view, SubRemViewRemoteStateIdle, 0); + popup_reset(app->popup); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c new file mode 100644 index 0000000000..447beb96d9 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c @@ -0,0 +1,54 @@ +#include "../subghz_remote_app_i.h" +#include "../helpers/subrem_custom_event.h" + +void subrem_scene_edit_submenu_text_input_callback(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventSceneEditsubmenu); +} + +void subrem_scene_edit_submenu_callback(void* context, uint32_t index) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void subrem_scene_edit_submenu_on_enter(void* context) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + Submenu* submenu = app->submenu; + submenu_add_item( + submenu, "Edit Label", EditSubmenuIndexEditLabel, subrem_scene_edit_submenu_callback, app); + submenu_add_item( + submenu, "Edit File", EditSubmenuIndexEditFile, subrem_scene_edit_submenu_callback, app); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDSubmenu); +} + +bool subrem_scene_edit_submenu_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == EditSubmenuIndexEditLabel) { + scene_manager_next_scene(app->scene_manager, SubRemSceneEditLabel); + consumed = true; + } else if(event.event == EditSubmenuIndexEditFile) { + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenSubFile); + consumed = true; + } + } + + return consumed; +} + +void subrem_scene_edit_submenu_on_exit(void* context) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c b/applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c new file mode 100644 index 0000000000..d33e070af5 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c @@ -0,0 +1,71 @@ +#include "../subghz_remote_app_i.h" +#include "../helpers/subrem_custom_event.h" + +#include + +void subrem_scene_enter_new_name_text_input_callback(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, SubRemCustomEventSceneNewName); +} + +void subrem_scene_enter_new_name_on_enter(void* context) { + SubGhzRemoteApp* app = context; + + // Setup view + TextInput* text_input = app->text_input; + bool dev_name_empty = false; + + strncpy(app->file_name_tmp, "subrem_", SUBREM_MAX_LEN_NAME); + text_input_set_header_text(text_input, "Map file Name"); + text_input_set_result_callback( + text_input, + subrem_scene_enter_new_name_text_input_callback, + app, + app->file_name_tmp, + 25, + dev_name_empty); + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + furi_string_get_cstr(app->file_path), SUBREM_APP_EXTENSION, ""); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDTextInput); +} + +bool subrem_scene_enter_new_name_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubRemCustomEventSceneNewName) { + if(strcmp(app->file_name_tmp, "") != 0) { + furi_string_set(app->file_path, SUBREM_APP_FOLDER); + furi_string_cat_printf( + app->file_path, "/%s%s", app->file_name_tmp, SUBREM_APP_EXTENSION); + + subrem_map_preset_reset(app->map_preset); + scene_manager_next_scene(app->scene_manager, SubRemSceneEditMenu); + } else { //error + } + consumed = true; + } + } + + return consumed; +} + +void subrem_scene_enter_new_name_on_exit(void* context) { + furi_assert(context); + + SubGhzRemoteApp* app = context; + submenu_reset(app->submenu); + + // Clear validator & view + void* validator_context = text_input_get_validator_callback_context(app->text_input); + text_input_set_validator(app->text_input, NULL, NULL); + validator_is_file_free(validator_context); + text_input_reset(app->text_input); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c b/applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c new file mode 100644 index 0000000000..77f2d2d561 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c @@ -0,0 +1,29 @@ +#include "../subghz_remote_app_i.h" + +void subrem_scene_open_map_file_on_enter(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + SubRemLoadMapState load_state = subrem_load_from_file(app); + uint32_t start_scene_state = + scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart); + + // TODO if optimization + + if(load_state == SubRemLoadMapStateBack) { + scene_manager_previous_scene(app->scene_manager); + } else if(start_scene_state == SubmenuIndexSubRemEditMapFile) { + scene_manager_set_scene_state(app->scene_manager, SubRemSceneEditMenu, SubRemSubKeyNameUp); + scene_manager_next_scene(app->scene_manager, SubRemSceneEditMenu); + } +} + +bool subrem_scene_open_map_file_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void subrem_scene_open_map_file_on_exit(void* context) { + UNUSED(context); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c b/applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c new file mode 100644 index 0000000000..75dc216704 --- /dev/null +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c @@ -0,0 +1,116 @@ +#include "../subghz_remote_app_i.h" + +void subrem_scene_open_sub_file_error_popup_callback(void* context) { + SubGhzRemoteApp* app = context; + view_dispatcher_send_custom_event( + app->view_dispatcher, SubRemCustomEventSceneEditOpenSubErrorPopup); +} + +SubRemLoadSubState subrem_scene_open_sub_file_dialog(SubGhzRemoteApp* app) { + furi_assert(app); + + SubRemSubFilePreset* sub = app->map_preset->subs_preset[app->chusen_sub]; + + FuriString* temp_file_path = furi_string_alloc_set(sub->file_path); + + SubRemLoadSubState ret = SubRemLoadSubStateNotSet; + + DialogsFileBrowserOptions browser_options; + + dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); + browser_options.base_path = SUBGHZ_APP_FOLDER; + + // Input events and views are managed by file_select + if(!dialog_file_browser_show( + app->dialogs, + temp_file_path, + furi_string_empty(temp_file_path) ? NULL : temp_file_path, + &browser_options)) { + } else { + // Check sub file + SubRemSubFilePreset* sub_candidate = subrem_sub_file_preset_alloc(); + furi_string_set(sub_candidate->label, sub->label); + furi_string_set(sub_candidate->file_path, temp_file_path); + + Storage* storage = furi_record_open(RECORD_STORAGE); + FlipperFormat* fff_file = flipper_format_file_alloc(storage); + + if(flipper_format_file_open_existing( + fff_file, furi_string_get_cstr(sub_candidate->file_path))) { + ret = subrem_sub_preset_load(sub_candidate, app->txrx, fff_file); + } + + flipper_format_file_close(fff_file); + flipper_format_free(fff_file); + furi_record_close(RECORD_STORAGE); + + if(ret == SubRemLoadSubStateOK) { + subrem_sub_file_preset_free(app->map_preset->subs_preset[app->chusen_sub]); + app->map_preset->subs_preset[app->chusen_sub] = sub_candidate; + app->map_not_saved = true; + } else { + subrem_sub_file_preset_free(sub_candidate); + } + } + + furi_string_free(temp_file_path); + + return ret; +} + +void subrem_scene_open_sub_file_on_enter(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + SubRemLoadSubState load_state = subrem_scene_open_sub_file_dialog(app); + + Popup* popup = app->popup; + // popup_set_icon(); + popup_set_header(popup, "ERROR", 63, 16, AlignCenter, AlignBottom); + popup_set_timeout(popup, 1500); + popup_set_context(popup, app); + popup_set_callback(popup, subrem_scene_open_sub_file_error_popup_callback); + popup_enable_timeout(popup); + + if(load_state == SubRemLoadSubStateOK) { + scene_manager_previous_scene(app->scene_manager); + } else if(load_state == SubRemLoadSubStateNotSet) { + scene_manager_previous_scene(app->scene_manager); + } else { + switch(load_state) { + case SubRemLoadSubStateErrorFreq: + + popup_set_text(popup, "Bad frequency", 63, 30, AlignCenter, AlignBottom); + break; + case SubRemLoadSubStateErrorMod: + + popup_set_text(popup, "Bad modulation", 63, 30, AlignCenter, AlignBottom); + break; + case SubRemLoadSubStateErrorProtocol: + + popup_set_text(popup, "Unsupported protocol", 63, 30, AlignCenter, AlignBottom); + break; + + default: + break; + } + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDPopup); + } +} + +bool subrem_scene_open_sub_file_on_event(void* context, SceneManagerEvent event) { + SubGhzRemoteApp* app = context; + + if(event.type == SceneManagerEventTypeCustom && + event.event == SubRemCustomEventSceneEditOpenSubErrorPopup) { + scene_manager_previous_scene(app->scene_manager); + return true; + } + return false; +} + +void subrem_scene_open_sub_file_on_exit(void* context) { + SubGhzRemoteApp* app = context; + + popup_reset(app->popup); +} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c b/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c deleted file mode 100644 index 8e6d9d0ddc..0000000000 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_openmapfile.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "../subghz_remote_app_i.h" - -void subrem_scene_openmapfile_on_enter(void* context) { - SubGhzRemoteApp* app = context; - SubRemLoadMapState load_state = subrem_load_from_file(app); - - if(load_state == SubRemLoadMapStateError) { -#ifdef SUBREM_LIGHT - dialog_message_show_storage_error(app->dialogs, "Can't load\nMap file"); -#else - DialogMessage* message = dialog_message_alloc(); - - dialog_message_set_header(message, "Map File Error", 64, 8, AlignCenter, AlignCenter); - dialog_message_set_text(message, "Can't load\nMap file", 64, 32, AlignCenter, AlignCenter); - dialog_message_set_buttons(message, "Back", NULL, NULL); - dialog_message_show(app->dialogs, message); - - dialog_message_free(message); -#endif - } - if(load_state == SubRemLoadMapStateOK || load_state == SubRemLoadMapStateNotAllOK) { - } else { - // TODO: Map Preset Reset - if(!scene_manager_search_and_switch_to_previous_scene( - app->scene_manager, SubRemSceneStart)) { - scene_manager_stop(app->scene_manager); - view_dispatcher_stop(app->view_dispatcher); - } - } -} - -bool subrem_scene_openmapfile_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; -} - -void subrem_scene_openmapfile_on_exit(void* context) { - UNUSED(context); -} diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c index fd2d61c480..e5a254111d 100644 --- a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c +++ b/applications/external/subghz_remote_new/scenes/subrem_scene_start.c @@ -13,14 +13,18 @@ void subrem_scene_start_on_enter(void* context) { SubGhzRemoteApp* app = context; Submenu* submenu = app->submenu; -#if FURI_DEBUG submenu_add_item( submenu, - "Remote_Debug", - SubmenuIndexSubRemRemoteView, + "Edit Map File", + SubmenuIndexSubRemEditMapFile, + subrem_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "New Map File", + SubmenuIndexSubRemNewMapFile, subrem_scene_start_submenu_callback, app); -#endif // submenu_add_item( // submenu, // "About", @@ -28,12 +32,10 @@ void subrem_scene_start_on_enter(void* context) { // subrem_scene_start_submenu_callback, // app); - // TODO: set scene state in subrem alloc - // submenu_set_selected_item( - // submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); - submenu_set_selected_item(submenu, 0); + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, SubRemSceneStart)); - view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewSubmenu); + view_dispatcher_switch_to_view(app->view_dispatcher, SubRemViewIDSubmenu); } bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { @@ -41,8 +43,19 @@ bool subrem_scene_start_on_event(void* context, SceneManagerEvent event) { SubGhzRemoteApp* app = context; bool consumed = false; - UNUSED(app); + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSubRemEditMapFile) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemEditMapFile); + scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); + consumed = true; + } else if(event.event == SubmenuIndexSubRemNewMapFile) { + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemNewMapFile); + scene_manager_next_scene(app->scene_manager, SubRemSceneEnterNewName); + consumed = true; + } // } else if(event.event == SubmenuIndexSubRemAbout) { // scene_manager_next_scene(app->scene_manager, SubRemSceneAbout); // consumed = true; diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_new/subghz_remote_app.c index b957fb8bcb..e026fe4dea 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_new/subghz_remote_app.c @@ -1,7 +1,5 @@ #include "subghz_remote_app_i.h" -#include - static bool subghz_remote_app_custom_event_callback(void* context, uint32_t event) { furi_assert(context); SubGhzRemoteApp* app = context; @@ -23,6 +21,14 @@ static void subghz_remote_app_tick_event_callback(void* context) { SubGhzRemoteApp* subghz_remote_app_alloc() { SubGhzRemoteApp* app = malloc(sizeof(SubGhzRemoteApp)); + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_migrate(storage, EXT_PATH("unirf"), SUBREM_APP_FOLDER); + + if(!storage_simply_mkdir(storage, SUBREM_APP_FOLDER)) { + //FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER); + } + furi_record_close(RECORD_STORAGE); + // Enable power for External CC1101 if it is connected furi_hal_subghz_enable_ext_power(); // Auto switch to internal radio if external radio is not available @@ -62,11 +68,25 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { // SubMenu app->submenu = submenu_alloc(); view_dispatcher_add_view( - app->view_dispatcher, SubRemViewSubmenu, submenu_get_view(app->submenu)); + app->view_dispatcher, SubRemViewIDSubmenu, submenu_get_view(app->submenu)); - //Dialog + // Dialog app->dialogs = furi_record_open(RECORD_DIALOGS); + // TextInput + app->text_input = text_input_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewIDTextInput, text_input_get_view(app->text_input)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, SubRemViewIDWidget, widget_get_view(app->widget)); + + // Popup + app->popup = popup_alloc(); + view_dispatcher_add_view(app->view_dispatcher, SubRemViewIDPopup, popup_get_view(app->popup)); + // Remote view app->subrem_remote_view = subrem_view_remote_alloc(); view_dispatcher_add_view( @@ -74,34 +94,30 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { SubRemViewIDRemote, subrem_view_remote_get_view(app->subrem_remote_view)); + // Edit Menu view + app->subrem_edit_menu = subrem_view_edit_menu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + SubRemViewIDEditMenu, + subrem_view_edit_menu_get_view(app->subrem_edit_menu)); + + app->map_preset = malloc(sizeof(SubRemMapPreset)); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - app->subs_preset[i] = subrem_sub_file_preset_alloc(); + app->map_preset->subs_preset[i] = subrem_sub_file_preset_alloc(); } - app->setting = subghz_setting_alloc(); - subghz_setting_load(app->setting, EXT_PATH("subghz/assets/setting_user")); - - app->environment = subghz_environment_alloc(); - - subghz_environment_load_keystore(app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes")); - subghz_environment_load_keystore( - app->environment, EXT_PATH("subghz/assets/keeloq_mfcodes_user")); - subghz_environment_set_came_atomo_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/came_atomo")); - subghz_environment_set_alutech_at_4n_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/alutech_at_4n")); - subghz_environment_set_nice_flor_s_rainbow_table_file_name( - app->environment, EXT_PATH("subghz/assets/nice_flor_s")); - subghz_environment_set_protocol_registry(app->environment, (void*)&subghz_protocol_registry); + app->txrx = subghz_txrx_alloc(); - app->receiver = subghz_receiver_alloc_init(app->environment); + subghz_txrx_set_need_save_callback(app->txrx, subrem_save_active_sub, app); - app->tx_running = false; + app->map_not_saved = false; #ifdef SUBREM_LIGHT scene_manager_next_scene(app->scene_manager, SubRemSceneOpenMapFile); #else scene_manager_next_scene(app->scene_manager, SubRemSceneStart); + scene_manager_set_scene_state( + app->scene_manager, SubRemSceneStart, SubmenuIndexSubRemEditMapFile); #endif return app; @@ -118,26 +134,41 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { furi_hal_subghz_init_radio_type(SubGhzRadioInternal); // Submenu - view_dispatcher_remove_view(app->view_dispatcher, SubRemViewSubmenu); + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDSubmenu); submenu_free(app->submenu); - //Dialog + // Dialog furi_record_close(RECORD_DIALOGS); + // TextInput + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDTextInput); + text_input_free(app->text_input); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDWidget); + widget_free(app->widget); + + // Popup + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDPopup); + popup_free(app->popup); + // Remote view view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDRemote); subrem_view_remote_free(app->subrem_remote_view); + // Edit view + view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDEditMenu); + subrem_view_edit_menu_free(app->subrem_edit_menu); + scene_manager_free(app->scene_manager); view_dispatcher_free(app->view_dispatcher); - subghz_receiver_free(app->receiver); - subghz_environment_free(app->environment); - subghz_setting_free(app->setting); + subghz_txrx_free(app->txrx); for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_free(app->subs_preset[i]); + subrem_sub_file_preset_free(app->map_preset->subs_preset[i]); } + free(app->map_preset); // Notifications furi_record_close(RECORD_NOTIFICATION); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_new/subghz_remote_app_i.c index aa8983951b..1eb64541ff 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.c +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.c @@ -2,12 +2,13 @@ #include #include -#include +#include "helpers/txrx/subghz_txrx.h" // #include // #include -#include +// #include +// #include #define TAG "SubGhzRemote" @@ -19,88 +20,73 @@ static const char* map_file_labels[SubRemSubKeyNameMaxCount][2] = { [SubRemSubKeyNameOk] = {"OK", "OKLABEL"}, }; -static bool - subrem_set_preset_data(SubGhzSetting* setting, FreqPreset* freq_preset, const char* preset) { - const char* preset_name = ""; - if(!strcmp(preset, "FuriHalSubGhzPresetOok270Async")) { - preset_name = "AM270"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetOok650Async")) { - preset_name = "AM650"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev238Async")) { - preset_name = "FM238"; - } else if(!strcmp(preset, "FuriHalSubGhzPreset2FSKDev476Async")) { - preset_name = "FM476"; - } else if(!strcmp(preset, "FuriHalSubGhzPresetCustom")) { - // preset_name = "CUSTOM"; - return false; - } else { - FURI_LOG_E(TAG, "Unknown preset"); - return false; - } - size_t preset_index = subghz_setting_get_inx_preset_by_name(setting, preset_name); - freq_preset->data = subghz_setting_get_preset_data(setting, preset_index); - return true; -} - -SubRemSubFilePreset* subrem_sub_file_preset_alloc() { - SubRemSubFilePreset* sub_preset = malloc(sizeof(SubRemSubFilePreset)); - - sub_preset->fff_data = flipper_format_string_alloc(); - sub_preset->file_path = furi_string_alloc(); - sub_preset->protocaol_name = furi_string_alloc(); - sub_preset->label = furi_string_alloc_set_str("N/A"); - - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; +void subrem_map_preset_reset(SubRemMapPreset* map_preset) { + furi_assert(map_preset); - return sub_preset; + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + subrem_sub_file_preset_reset(map_preset->subs_preset[i]); + } } -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); +static SubRemLoadMapState subrem_map_preset_check( + SubRemMapPreset* map_preset, + SubGhzTxRx* txrx, + FlipperFormat* fff_data_file) { + furi_assert(map_preset); + furi_assert(txrx); - furi_string_free(sub_preset->label); - furi_string_free(sub_preset->protocaol_name); - furi_string_free(sub_preset->file_path); - flipper_format_free(sub_preset->fff_data); + bool all_loaded = true; + SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; - free(sub_preset); -} + SubRemLoadSubState sub_loadig_state; + SubRemSubFilePreset* sub_preset; -static void subrem_sub_file_preset_reset(SubRemSubFilePreset* sub_preset) { - furi_assert(sub_preset); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = map_preset->subs_preset[i]; - furi_string_set_str(sub_preset->label, "N/A"); - furi_string_reset(sub_preset->protocaol_name); - furi_string_reset(sub_preset->file_path); + sub_loadig_state = SubRemLoadSubStateErrorNoFile; - Stream* fff_data_stream = flipper_format_get_raw_stream(sub_preset->fff_data); - stream_clean(fff_data_stream); + if(furi_string_empty(sub_preset->file_path)) { + // FURI_LOG_I(TAG, "Empty file path"); + } else if(!flipper_format_file_open_existing( + fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { + sub_preset->load_state = SubRemLoadSubStateErrorNoFile; + FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); + } else { + sub_loadig_state = subrem_sub_preset_load(sub_preset, txrx, fff_data_file); + } - sub_preset->type = SubGhzProtocolTypeUnknown; - sub_preset->load_state = SubRemLoadSubStateNotSet; -} + if(sub_loadig_state != SubRemLoadSubStateOK) { + all_loaded = false; + } else { + ret = SubRemLoadMapStateNotAllOK; + } -void subrem_map_preset_reset(SubGhzRemoteApp* app) { - furi_assert(app); + if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { + ret = SubRemLoadMapStateOK; + } - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - subrem_sub_file_preset_reset(app->subs_preset[i]); + flipper_format_file_close(fff_data_file); } + + return ret; } -static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { - furi_assert(app); +static bool subrem_map_preset_load(SubRemMapPreset* map_preset, FlipperFormat* fff_data_file) { + furi_assert(map_preset); bool ret = false; SubRemSubFilePreset* sub_preset; for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->subs_preset[i]; + sub_preset = map_preset->subs_preset[i]; if(!flipper_format_read_string( fff_data_file, map_file_labels[i][0], sub_preset->file_path)) { #if FURI_DEBUG FURI_LOG_W(TAG, "No file patch for %s", map_file_labels[i][0]); #endif sub_preset->type = SubGhzProtocolTypeUnknown; + } else if(!path_contains_only_ascii(furi_string_get_cstr(sub_preset->file_path))) { + FURI_LOG_E(TAG, "Incorrect characters in [%s] file path", map_file_labels[i][0]); + sub_preset->type = SubGhzProtocolTypeUnknown; } else if(!flipper_format_rewind(fff_data_file)) { // Rewind error } else if(!flipper_format_read_string( @@ -108,8 +94,11 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data #if FURI_DEBUG FURI_LOG_W(TAG, "No Label for %s", map_file_labels[i][0]); #endif - path_extract_filename(sub_preset->file_path, sub_preset->label, true); + ret = true; } else { + ret = true; + } + if(ret) { // Preload seccesful FURI_LOG_I( TAG, @@ -117,192 +106,11 @@ static bool subrem_map_preset_load(SubGhzRemoteApp* app, FlipperFormat* fff_data map_file_labels[i][0], furi_string_get_cstr(sub_preset->label), furi_string_get_cstr(sub_preset->file_path)); - ret = true; sub_preset->load_state = SubRemLoadSubStatePreloaded; } - flipper_format_rewind(fff_data_file); - } - return ret; -} - -bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* dev_file_name) { - furi_assert(flipper_format); - furi_assert(dev_file_name); - - Storage* storage = furi_record_open(RECORD_STORAGE); - Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); - - bool saved = false; - uint32_t repeat = 200; - FuriString* file_dir = furi_string_alloc(); - - path_extract_dirname(dev_file_name, file_dir); - do { - // removing additional fields - flipper_format_delete_key(flipper_format, "Repeat"); - // flipper_format_delete_key(flipper_format, "Manufacture"); - - if(!storage_simply_remove(storage, dev_file_name)) { - break; - } - //ToDo check Write - stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); - stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS); - - if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - saved = true; - } while(0); - - furi_string_free(file_dir); - furi_record_close(RECORD_STORAGE); - return saved; -} - -static SubRemLoadMapState - subrem_map_preset_check(SubGhzRemoteApp* app, FlipperFormat* fff_data_file) { - furi_assert(app); - FuriString* temp_str = furi_string_alloc(); - uint32_t temp_data32; - bool all_loaded = true; - SubRemLoadMapState ret = SubRemLoadMapStateErrorBrokenFile; - SubRemLoadSubState sub_preset_loaded; - SubRemSubFilePreset* sub_preset; - uint32_t repeat = 200; - for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { - sub_preset = app->subs_preset[i]; - if(furi_string_empty(sub_preset->file_path)) { - // FURI_LOG_I(TAG, "Empty file path"); - continue; - } - - sub_preset_loaded = SubRemLoadSubStateErrorNoFile; - - repeat = 200; - do { - if(!flipper_format_file_open_existing( - fff_data_file, furi_string_get_cstr(sub_preset->file_path))) { - FURI_LOG_W(TAG, "Error open file %s", furi_string_get_cstr(sub_preset->file_path)); - break; - } - - if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { - FURI_LOG_E(TAG, "Missing or incorrect header"); - break; - } - - if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) || - (!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) && - temp_data32 == SUBGHZ_KEY_FILE_VERSION) { - } else { - FURI_LOG_E(TAG, "Type or version mismatch"); - break; - } - - //Load frequency - sub_preset_loaded = SubRemLoadSubStateErrorFreq; - if(!flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) { - FURI_LOG_W(TAG, "Cannot read frequency. Set default frequency"); - sub_preset->freq_preset.frequency = - subghz_setting_get_default_frequency(app->setting); - } else if(!furi_hal_subghz_is_tx_allowed(temp_data32)) { - FURI_LOG_E(TAG, "This frequency can only be used for RX"); - break; - } else { - sub_preset->freq_preset.frequency = temp_data32; - } - - //Load preset - sub_preset_loaded = SubRemLoadSubStateErrorMod; - if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) { - FURI_LOG_E(TAG, "Missing Preset"); - break; - } - - if(!subrem_set_preset_data( - app->setting, &sub_preset->freq_preset, furi_string_get_cstr(temp_str))) { - FURI_LOG_E(TAG, "Cannot load preset."); - break; - } - - //Load protocol - sub_preset_loaded = SubRemLoadSubStateErrorProtocol; - if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) { - FURI_LOG_E(TAG, "Missing Protocol"); - break; - } - - FlipperFormat* fff_data = sub_preset->fff_data; - if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { - //if RAW - subghz_protocol_raw_gen_fff_data( - fff_data, furi_string_get_cstr(sub_preset->file_path)); - } else { - stream_copy_full( - flipper_format_get_raw_stream(fff_data_file), - flipper_format_get_raw_stream(fff_data)); - } - - const SubGhzProtocolRegistry* protocol_registry_items = - subghz_environment_get_protocol_registry(app->environment); - - const SubGhzProtocol* protocol = subghz_protocol_registry_get_by_name( - protocol_registry_items, furi_string_get_cstr(temp_str)); - - if(!protocol) { - FURI_LOG_E(TAG, "Protocol not found"); - break; - } else if(protocol->flag & SubGhzProtocolFlag_Send) { - if((protocol->type == SubGhzProtocolTypeStatic) || - (protocol->type == SubGhzProtocolTypeDynamic) || - // (protocol->type == SubGhzProtocolTypeBinRAW) || // TODO: BINRAW - (protocol->type == SubGhzProtocolTypeRAW)) { - sub_preset->type = protocol->type; - } else { - FURI_LOG_E(TAG, "Unsuported Protocol"); - break; - } - - furi_string_set(sub_preset->protocaol_name, temp_str); - } else { - FURI_LOG_E(TAG, "Protocol does not support transmission"); - } - - if(!flipper_format_insert_or_update_uint32(fff_data, "Repeat", &repeat, 1)) { - FURI_LOG_E(TAG, "Unable Repeat"); - break; - } - - sub_preset_loaded = SubRemLoadSubStateOK; - ret = SubRemLoadMapStateNotAllOK; - -#if FURI_DEBUG - FURI_LOG_I(TAG, "%-16s - protocol Loaded", furi_string_get_cstr(sub_preset->label)); -#endif - } while(false); - - // TODO: - // Load file state logic - // Label depending on the state - // Move to remote scene - - if(sub_preset_loaded != SubRemLoadSubStateOK) { - furi_string_set_str(sub_preset->label, "N/A"); - all_loaded = false; - } - - if(ret != SubRemLoadMapStateErrorBrokenFile && all_loaded) { - ret = SubRemLoadMapStateOK; - } - - flipper_format_file_close(fff_data_file); + flipper_format_rewind(fff_data_file); } - furi_string_free(temp_str); - return ret; } @@ -318,19 +126,19 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p #if FURI_DEBUG FURI_LOG_I(TAG, "Open Map File.."); #endif - subrem_map_preset_reset(app); + subrem_map_preset_reset(app->map_preset); if(!flipper_format_file_open_existing(fff_data_file, file_path)) { FURI_LOG_E(TAG, "Could not open MAP file %s", file_path); ret = SubRemLoadMapStateErrorOpenError; } else { - if(!subrem_map_preset_load(app, fff_data_file)) { + if(!subrem_map_preset_load(app->map_preset, fff_data_file)) { FURI_LOG_E(TAG, "Could no Sub file path in MAP file"); // ret = // error for popup } else if(!flipper_format_file_close(fff_data_file)) { ret = SubRemLoadMapStateErrorOpenError; } else { - ret = subrem_map_preset_check(app, fff_data_file); + ret = subrem_map_preset_check(app->map_preset, app->txrx, fff_data_file); } } @@ -349,6 +157,53 @@ SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_p return ret; } +bool subrem_save_protocol_to_file(FlipperFormat* flipper_format, const char* sub_file_name) { + furi_assert(flipper_format); + furi_assert(sub_file_name); + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* flipper_format_stream = flipper_format_get_raw_stream(flipper_format); + + bool saved = false; + uint32_t repeat = 200; + FuriString* file_dir = furi_string_alloc(); + + path_extract_dirname(sub_file_name, file_dir); + do { + // removing additional fields + flipper_format_delete_key(flipper_format, "Repeat"); + // flipper_format_delete_key(flipper_format, "Manufacture"); + + if(!storage_simply_remove(storage, sub_file_name)) { + break; + } + + //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); + stream_save_to_file(flipper_format_stream, storage, sub_file_name, FSOM_CREATE_ALWAYS); + + if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { + FURI_LOG_E(TAG, "Unable Repeat"); + break; + } + + saved = true; + } while(0); + + furi_string_free(file_dir); + furi_record_close(RECORD_STORAGE); + return saved; +} + +void subrem_save_active_sub(void* context) { + furi_assert(context); + SubGhzRemoteApp* app = context; + + SubRemSubFilePreset* sub_preset = app->map_preset->subs_preset[app->chusen_sub]; + subrem_save_protocol_to_file( + sub_preset->fff_data, furi_string_get_cstr(sub_preset->file_path)); +} + SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { furi_assert(app); @@ -356,7 +211,7 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { SubRemLoadMapState ret = SubRemLoadMapStateBack; DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_sub1_10px); + dialog_file_browser_set_basic_options(&browser_options, SUBREM_APP_EXTENSION, &I_subrem_10px); browser_options.base_path = SUBREM_APP_FOLDER; // Input events and views are managed by file_select @@ -369,3 +224,47 @@ SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app) { return ret; } + +bool subrem_save_map_to_file(SubGhzRemoteApp* app) { + furi_assert(app); + + const char* file_name = furi_string_get_cstr(app->file_path); + bool saved = false; + FlipperFormat* fff_data = flipper_format_string_alloc(); + + SubRemSubFilePreset* sub_preset; + + flipper_format_write_header_cstr( + fff_data, SUBREM_APP_APP_FILE_TYPE, SUBREM_APP_APP_FILE_VERSION); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = app->map_preset->subs_preset[i]; + if(!furi_string_empty(sub_preset->file_path)) { + flipper_format_write_string(fff_data, map_file_labels[i][0], sub_preset->file_path); + } + } + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = app->map_preset->subs_preset[i]; + if(!furi_string_empty(sub_preset->file_path)) { + flipper_format_write_string(fff_data, map_file_labels[i][1], sub_preset->label); + } + } + + Storage* storage = furi_record_open(RECORD_STORAGE); + Stream* flipper_format_stream = flipper_format_get_raw_stream(fff_data); + + do { + if(!storage_simply_remove(storage, file_name)) { + break; + } + //ToDo check Write + stream_seek(flipper_format_stream, 0, StreamOffsetFromStart); + stream_save_to_file(flipper_format_stream, storage, file_name, FSOM_CREATE_ALWAYS); + + saved = true; + } while(0); + + furi_record_close(RECORD_STORAGE); + flipper_format_free(fff_data); + + return saved; +} \ No newline at end of file diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 1bcb79d8fd..7a07d768a7 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -1,29 +1,28 @@ #pragma once #include "helpers/subrem_types.h" -#include +#include "helpers/subrem_presets.h" +#include "scenes/subrem_scene.h" -// #include +#include "helpers/txrx/subghz_txrx.h" +#include #include "views/remote.h" - -#include "scenes/subrem_scene.h" +#include "views/edit_menu.h" #include #include #include #include #include -#include #include +#include #include +#include #include -#include #include -#include - #include #include #include @@ -31,48 +30,38 @@ #define SUBREM_APP_FOLDER EXT_PATH("subghz_remote") #define SUBREM_MAX_LEN_NAME 64 -typedef struct { - uint32_t frequency; - uint8_t* data; -} FreqPreset; - -// Sub File preset -typedef struct { - FlipperFormat* fff_data; - FreqPreset freq_preset; - FuriString* file_path; - FuriString* protocaol_name; - FuriString* label; - SubGhzProtocolType type; - SubRemLoadSubState load_state; -} SubRemSubFilePreset; - -SubRemSubFilePreset* subrem_sub_file_preset_alloc(); - -void subrem_sub_file_preset_free(SubRemSubFilePreset* sub_preset); - typedef struct { Gui* gui; ViewDispatcher* view_dispatcher; SceneManager* scene_manager; NotificationApp* notifications; DialogsApp* dialogs; + Widget* widget; + Popup* popup; + TextInput* text_input; Submenu* submenu; + FuriString* file_path; char file_name_tmp[SUBREM_MAX_LEN_NAME]; SubRemViewRemote* subrem_remote_view; + SubRemViewEditMenu* subrem_edit_menu; - SubRemSubFilePreset* subs_preset[SubRemSubKeyNameMaxCount]; + SubRemMapPreset* map_preset; - SubGhzSetting* setting; - SubGhzEnvironment* environment; - SubGhzReceiver* receiver; - SubGhzTransmitter* transmitter; + SubGhzTxRx* txrx; - bool tx_running; + bool map_not_saved; uint8_t chusen_sub; } SubGhzRemoteApp; SubRemLoadMapState subrem_load_from_file(SubGhzRemoteApp* app); + +SubRemLoadMapState subrem_map_file_load(SubGhzRemoteApp* app, const char* file_path); + +void subrem_map_preset_reset(SubRemMapPreset* map_preset); + +bool subrem_save_map_to_file(SubGhzRemoteApp* app); + +void subrem_save_active_sub(void* context); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/edit_menu.c b/applications/external/subghz_remote_new/views/edit_menu.c new file mode 100644 index 0000000000..9b88182b51 --- /dev/null +++ b/applications/external/subghz_remote_new/views/edit_menu.c @@ -0,0 +1,290 @@ +#include "edit_menu.h" +#include "../subghz_remote_app_i.h" + +#include +#include + +#define subrem_view_edit_menu_MAX_LABEL_LENGTH 12 + +#define FRAME_HEIGHT 12 + +struct SubRemViewEditMenu { + View* view; + SubRemViewEditMenuCallback callback; + void* context; +}; + +typedef struct { + FuriString* label; + FuriString* file_path; + SubRemLoadSubState sub_state; + + uint8_t chusen; +} SubRemViewEditMenuModel; + +void subrem_view_edit_menu_set_callback( + SubRemViewEditMenu* subrem_view_edit_menu, + SubRemViewEditMenuCallback callback, + void* context) { + furi_assert(subrem_view_edit_menu); + + subrem_view_edit_menu->callback = callback; + subrem_view_edit_menu->context = context; +} + +void subrem_view_edit_menu_add_data_to_show( + SubRemViewEditMenu* subrem_view_edit_remote, + uint8_t index, + FuriString* label, + FuriString* path, + SubRemLoadSubState state) { + furi_assert(subrem_view_edit_remote); + + with_view_model( + subrem_view_edit_remote->view, + SubRemViewEditMenuModel * model, + { + model->chusen = index; + if(!furi_string_empty(label)) { + furi_string_set(model->label, label); + } else { + furi_string_set(model->label, "Empty label"); + } + furi_string_set(model->file_path, path); + model->sub_state = state; + }, + true); +} + +uint8_t subrem_view_edit_menu_get_index(SubRemViewEditMenu* subrem_view_edit_remote) { + furi_assert(subrem_view_edit_remote); + uint8_t index; + + with_view_model( + subrem_view_edit_remote->view, + SubRemViewEditMenuModel * model, + { index = model->chusen; }, + true); + return index; +} + +void subrem_view_edit_menu_draw(Canvas* canvas, SubRemViewEditMenuModel* model) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + canvas_clear(canvas); + + // Draw bottom btn + canvas_set_font(canvas, FontSecondary); + elements_button_left(canvas, "Back"); + elements_button_center(canvas, "Edit"); + elements_button_right(canvas, "Save"); + + // Draw top frame + canvas_draw_line(canvas, 1, 0, 125, 0); + canvas_draw_box(canvas, 0, 1, 127, FRAME_HEIGHT - 2); + canvas_draw_line(canvas, 1, FRAME_HEIGHT - 1, 125, FRAME_HEIGHT - 1); + + canvas_set_color(canvas, ColorWhite); + + // Draw btn name + canvas_set_font(canvas, FontPrimary); + switch(model->chusen) { + case SubRemSubKeyNameUp: + canvas_draw_str(canvas, 3, FRAME_HEIGHT - 2, "UP"); + break; + + case SubRemSubKeyNameDown: + canvas_draw_str(canvas, 3, FRAME_HEIGHT - 2, "DOWN"); + break; + + case SubRemSubKeyNameLeft: + canvas_draw_str(canvas, 3, FRAME_HEIGHT - 2, "LEFT"); + break; + + case SubRemSubKeyNameRight: + canvas_draw_str(canvas, 3, FRAME_HEIGHT - 2, "RIGHT"); + break; + + case SubRemSubKeyNameOk: + canvas_draw_str(canvas, 3, FRAME_HEIGHT - 2, "OK"); + break; + + default: + break; + } + + // Draw Label + canvas_set_font(canvas, FontSecondary); + elements_text_box( + canvas, + 38, + 2, + 127 - 38, + FRAME_HEIGHT, + AlignCenter, + AlignBottom, + furi_string_empty(model->label) ? "Empty label" : furi_string_get_cstr(model->label), + true); + + // Draw arrow + canvas_set_color(canvas, ColorBlack); + if(model->chusen != 0) { + canvas_draw_icon(canvas, 119, 13, &I_Pin_arrow_up_7x9); + } + if(model->chusen != 4) { + canvas_draw_icon_ex(canvas, 119, 42, &I_Pin_arrow_up_7x9, IconRotation180); + } + + // Draw file_path + if(model->sub_state == SubRemLoadSubStateOK) { + canvas_set_font(canvas, FontSecondary); + elements_text_box( + canvas, + 1, + FRAME_HEIGHT + 1, + 118, + (63 - FRAME_HEIGHT * 2), + AlignLeft, + AlignTop, + furi_string_get_cstr(model->file_path), + false); + } else if(furi_string_empty(model->file_path)) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 1, FRAME_HEIGHT * 2 - 2, "Button not set"); + } else { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 1, FRAME_HEIGHT * 2 - 2, "ERR:"); + canvas_set_font(canvas, FontSecondary); + switch(model->sub_state) { + case SubRemLoadSubStateErrorNoFile: + canvas_draw_str(canvas, 26, FRAME_HEIGHT * 2 - 2, "File not found"); + break; + case SubRemLoadSubStateErrorFreq: + canvas_draw_str(canvas, 26, FRAME_HEIGHT * 2 - 2, "Bad frequency"); + break; + case SubRemLoadSubStateErrorMod: + canvas_draw_str(canvas, 26, FRAME_HEIGHT * 2 - 2, "Bad modulation"); + break; + case SubRemLoadSubStateErrorProtocol: + canvas_draw_str(canvas, 26, FRAME_HEIGHT * 2 - 2, "Unsupported protocol"); + break; + + default: + break; + } + elements_text_box( + canvas, + 1, + FRAME_HEIGHT * 2, + 118, + 30, + AlignLeft, + AlignTop, + furi_string_get_cstr(model->file_path), + false); + } +} + +bool subrem_view_edit_menu_input(InputEvent* event, void* context) { + furi_assert(context); + SubRemViewEditMenu* subrem_view_edit_menu = context; + + if((event->key == InputKeyBack || event->key == InputKeyLeft) && + event->type == InputTypeShort) { + subrem_view_edit_menu->callback( + SubRemCustomEventViewEditMenuBack, subrem_view_edit_menu->context); + return true; + } else if(event->key == InputKeyUp && event->type == InputTypeShort) { + with_view_model( + subrem_view_edit_menu->view, + SubRemViewEditMenuModel * model, + { + if(model->chusen > 0) { + model->chusen -= 1; + }; + }, + true); + subrem_view_edit_menu->callback( + SubRemCustomEventViewEditMenuUP, subrem_view_edit_menu->context); + return true; + } else if(event->key == InputKeyDown && event->type == InputTypeShort) { + with_view_model( + subrem_view_edit_menu->view, + SubRemViewEditMenuModel * model, + { + if(model->chusen < 4) { + model->chusen += 1; + }; + }, + true); + subrem_view_edit_menu->callback( + SubRemCustomEventViewEditMenuDOWN, subrem_view_edit_menu->context); + return true; + } else if(event->key == InputKeyOk && event->type == InputTypeShort) { + subrem_view_edit_menu->callback( + SubRemCustomEventViewEditMenuEdit, subrem_view_edit_menu->context); + return true; + } else if(event->key == InputKeyRight && event->type == InputTypeShort) { + subrem_view_edit_menu->callback( + SubRemCustomEventViewEditMenuSave, subrem_view_edit_menu->context); + return true; + } + + return true; +} + +void subrem_view_edit_menu_enter(void* context) { + furi_assert(context); +} + +void subrem_view_edit_menu_exit(void* context) { + furi_assert(context); +} + +SubRemViewEditMenu* subrem_view_edit_menu_alloc() { + SubRemViewEditMenu* subrem_view_edit_menu = malloc(sizeof(SubRemViewEditMenu)); + + // View allocation and configuration + subrem_view_edit_menu->view = view_alloc(); + view_allocate_model( + subrem_view_edit_menu->view, ViewModelTypeLocking, sizeof(SubRemViewEditMenuModel)); + view_set_context(subrem_view_edit_menu->view, subrem_view_edit_menu); + view_set_draw_callback( + subrem_view_edit_menu->view, (ViewDrawCallback)subrem_view_edit_menu_draw); + view_set_input_callback(subrem_view_edit_menu->view, subrem_view_edit_menu_input); + view_set_enter_callback(subrem_view_edit_menu->view, subrem_view_edit_menu_enter); + view_set_exit_callback(subrem_view_edit_menu->view, subrem_view_edit_menu_exit); + + with_view_model( + subrem_view_edit_menu->view, + SubRemViewEditMenuModel * model, + { + model->label = furi_string_alloc(); // furi_string_alloc_set_str("LABEL"); + model->file_path = furi_string_alloc(); // furi_string_alloc_set_str("FILE_PATH"); + + model->chusen = 0; + }, + true); + return subrem_view_edit_menu; +} + +void subrem_view_edit_menu_free(SubRemViewEditMenu* subghz_edit_menu) { + furi_assert(subghz_edit_menu); + + with_view_model( + subghz_edit_menu->view, + SubRemViewEditMenuModel * model, + { + furi_string_free(model->label); + furi_string_free(model->file_path); + }, + true); + view_free(subghz_edit_menu->view); + free(subghz_edit_menu); +} + +View* subrem_view_edit_menu_get_view(SubRemViewEditMenu* subrem_view_edit_menu) { + furi_assert(subrem_view_edit_menu); + return subrem_view_edit_menu->view; +} \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/edit_menu.h b/applications/external/subghz_remote_new/views/edit_menu.h new file mode 100644 index 0000000000..7ceb7fac04 --- /dev/null +++ b/applications/external/subghz_remote_new/views/edit_menu.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include "../helpers/subrem_custom_event.h" +#include "../helpers/subrem_presets.h" + +typedef struct SubRemViewEditMenu SubRemViewEditMenu; + +typedef void (*SubRemViewEditMenuCallback)(SubRemCustomEvent event, void* context); + +void subrem_view_edit_menu_set_callback( + SubRemViewEditMenu* subrem_view_edit_menu, + SubRemViewEditMenuCallback callback, + void* context); + +SubRemViewEditMenu* subrem_view_edit_menu_alloc(); + +void subrem_view_edit_menu_free(SubRemViewEditMenu* subrem_view_edit_menu); + +View* subrem_view_edit_menu_get_view(SubRemViewEditMenu* subrem_view_edit_menu); + +void subrem_view_edit_menu_add_data_to_show( + SubRemViewEditMenu* subrem_view_edit_remote, + uint8_t index, + FuriString* label, + FuriString* path, + SubRemLoadSubState state); + +uint8_t subrem_view_edit_menu_get_index(SubRemViewEditMenu* subrem_view_edit_remote); \ No newline at end of file diff --git a/applications/external/subghz_remote_new/views/remote.c b/applications/external/subghz_remote_new/views/remote.c index 1f867cd0b6..c2b41cfd68 100644 --- a/applications/external/subghz_remote_new/views/remote.c +++ b/applications/external/subghz_remote_new/views/remote.c @@ -4,7 +4,11 @@ #include #include -#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 12 +#include + +#define SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH 30 +#define SUBREM_VIEW_REMOTE_LEFT_OFFSET 10 +#define SUBREM_VIEW_REMOTE_RIGHT_OFFSET 22 struct SubRemViewRemote { View* view; @@ -12,19 +16,8 @@ struct SubRemViewRemote { void* context; }; -// TODO: model typedef struct { - // FuriString* up_label; - // FuriString* down_label; - // FuriString* left_label; - // FuriString* right_label; - // FuriString* ok_label; - - char* up_label; - char* down_label; - char* left_label; - char* right_label; - char* ok_label; + char* labels[SubRemSubKeyNameMaxCount]; SubRemViewRemoteState state; @@ -41,49 +34,76 @@ void subrem_view_remote_set_callback( subrem_view_remote->context = context; } -void subrem_view_remote_add_data_to_show( +void subrem_view_remote_update_data_labels( SubRemViewRemote* subrem_view_remote, - const char* up_label, - const char* down_label, - const char* left_label, - const char* right_label, - const char* ok_label) { + SubRemSubFilePreset** subs_presets) { furi_assert(subrem_view_remote); + furi_assert(subs_presets); + + FuriString* labels[SubRemSubKeyNameMaxCount]; + SubRemSubFilePreset* sub_preset; + + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + sub_preset = subs_presets[i]; + switch(sub_preset->load_state) { + case SubRemLoadSubStateOK: + if(!furi_string_empty(sub_preset->label)) { + labels[i] = furi_string_alloc_set(sub_preset->label); + } else if(!furi_string_empty(sub_preset->file_path)) { + labels[i] = furi_string_alloc(); + path_extract_filename(sub_preset->file_path, labels[i], true); + } else { + labels[i] = furi_string_alloc_set("Empty Label"); + } + break; + + case SubRemLoadSubStateErrorNoFile: + labels[i] = furi_string_alloc_set("[X] Can't open file"); + break; + + case SubRemLoadSubStateErrorFreq: + case SubRemLoadSubStateErrorMod: + case SubRemLoadSubStateErrorProtocol: + labels[i] = furi_string_alloc_set("[X] Error in .sub file"); + break; + + default: + labels[i] = furi_string_alloc_set(""); + break; + } + } with_view_model( subrem_view_remote->view, SubRemViewRemoteModel * model, { - strncpy(model->up_label, up_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->down_label, down_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->left_label, left_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->right_label, right_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - strncpy(model->ok_label, ok_label, SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); - - // furi_string_set(model->up_label, up_label); - // furi_string_set(model->down_label, down_label); - // furi_string_set(model->left_label, left_label); - // furi_string_set(model->right_label, right_label); - // furi_string_set(model->ok_label, ok_label); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + strncpy( + model->labels[i], + furi_string_get_cstr(labels[i]), + SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH); + } }, true); -} -void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn) { - furi_assert(subrem_view_remote); - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { model->pressed_btn = presed_btn; }, - true); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + furi_string_free(labels[i]); + } } void subrem_view_remote_set_state( SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state) { + SubRemViewRemoteState state, + uint8_t presed_btn) { furi_assert(subrem_view_remote); with_view_model( - subrem_view_remote->view, SubRemViewRemoteModel * model, { model->state = state; }, true); + subrem_view_remote->view, + SubRemViewRemoteModel * model, + { + model->state = state; + model->pressed_btn = presed_btn; + }, + true); } void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { @@ -103,24 +123,32 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { //Labels canvas_set_font(canvas, FontSecondary); - canvas_draw_str(canvas, 10, 10, model->up_label); - canvas_draw_str(canvas, 10, 20, model->down_label); - canvas_draw_str(canvas, 10, 30, model->left_label); - canvas_draw_str(canvas, 10, 40, model->right_label); - canvas_draw_str(canvas, 10, 50, model->ok_label); - - // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); - // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); - // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); - // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); - // canvas_draw_str(canvas, 10, 10, furi_string_get_cstr(model->up_label)); + uint8_t y = 0; + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + elements_text_box( + canvas, + SUBREM_VIEW_REMOTE_LEFT_OFFSET, + y + 2, + 126 - SUBREM_VIEW_REMOTE_LEFT_OFFSET - SUBREM_VIEW_REMOTE_RIGHT_OFFSET, + 12, + AlignLeft, + AlignBottom, + model->labels[i], + false); + y += 10; + } - canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); + if(model->state == SubRemViewRemoteStateOFF) { + elements_button_left(canvas, "Back"); + elements_button_right(canvas, "Save"); + } else { + canvas_draw_str_aligned(canvas, 11, 62, AlignLeft, AlignBottom, "Hold=Exit."); + } //Status text and indicator canvas_draw_icon(canvas, 113, 15, &I_Pin_cell_13x13); - if(model->state == SubRemViewRemoteStateIdle) { + if(model->state == SubRemViewRemoteStateIdle || model->state == SubRemViewRemoteStateOFF) { canvas_draw_str_aligned(canvas, 126, 10, AlignRight, AlignBottom, "Idle"); } else { switch(model->state) { @@ -155,10 +183,6 @@ void subrem_view_remote_draw(Canvas* canvas, SubRemViewRemoteModel* model) { break; } } - //Repeat indicator - //canvas_draw_str_aligned(canvas, 125, 40, AlignRight, AlignBottom, "Repeat:"); - //canvas_draw_icon(canvas, 115, 39, &I_SubGHzRemote_Repeat_12x14); - //canvas_draw_str_aligned(canvas, 125, 62, AlignRight, AlignBottom, int_to_char(app->repeat)); } bool subrem_view_remote_input(InputEvent* event, void* context) { @@ -166,17 +190,6 @@ bool subrem_view_remote_input(InputEvent* event, void* context) { SubRemViewRemote* subrem_view_remote = context; if(event->key == InputKeyBack && event->type == InputTypeLong) { - with_view_model( - subrem_view_remote->view, - SubRemViewRemoteModel * model, - { - strcpy(model->up_label, "N/A"); - strcpy(model->down_label, "N/A"); - strcpy(model->left_label, "N/A"); - strcpy(model->right_label, "N/A"); - strcpy(model->ok_label, "N/A"); - }, - false); subrem_view_remote->callback(SubRemCustomEventViewRemoteBack, subrem_view_remote->context); return true; } else if(event->key == InputKeyBack && event->type == InputTypeShort) { @@ -248,23 +261,10 @@ SubRemViewRemote* subrem_view_remote_alloc() { { model->state = SubRemViewRemoteStateIdle; - model->up_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - model->down_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - model->left_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - model->right_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - model->ok_label = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); - - strcpy(model->up_label, "N/A"); - strcpy(model->down_label, "N/A"); - strcpy(model->left_label, "N/A"); - strcpy(model->right_label, "N/A"); - strcpy(model->ok_label, "N/A"); - - // model->up_label = furi_string_alloc_set_str("N/A"); - // model->down_label = furi_string_alloc_set_str("N/A"); - // model->left_label = furi_string_alloc_set_str("N/A"); - // model->right_label = furi_string_alloc_set_str("N/A"); - // model->ok_label = furi_string_alloc_set_str("N/A"); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + model->labels[i] = malloc(sizeof(char) * SUBREM_VIEW_REMOTE_MAX_LABEL_LENGTH + 1); + strcpy(model->labels[i], ""); + } model->pressed_btn = 0; }, @@ -279,17 +279,9 @@ void subrem_view_remote_free(SubRemViewRemote* subghz_remote) { subghz_remote->view, SubRemViewRemoteModel * model, { - free(model->up_label); - free(model->down_label); - free(model->left_label); - free(model->right_label); - free(model->ok_label); - - // furi_string_free(model->up_label); - // furi_string_free(model->down_label); - // furi_string_free(model->left_label); - // furi_string_free(model->right_label); - // furi_string_free(model->ok_label); + for(uint8_t i = 0; i < SubRemSubKeyNameMaxCount; i++) { + free(model->labels[i]); + } }, true); view_free(subghz_remote->view); diff --git a/applications/external/subghz_remote_new/views/remote.h b/applications/external/subghz_remote_new/views/remote.h index 76121cf8a0..5b1e8153ae 100644 --- a/applications/external/subghz_remote_new/views/remote.h +++ b/applications/external/subghz_remote_new/views/remote.h @@ -2,11 +2,13 @@ #include #include "../helpers/subrem_custom_event.h" +#include "../helpers/subrem_presets.h" typedef enum { SubRemViewRemoteStateIdle, SubRemViewRemoteStateLoading, SubRemViewRemoteStateSending, + SubRemViewRemoteStateOFF, } SubRemViewRemoteState; typedef struct SubRemViewRemote SubRemViewRemote; @@ -24,15 +26,11 @@ void subrem_view_remote_free(SubRemViewRemote* subrem_view_remote); View* subrem_view_remote_get_view(SubRemViewRemote* subrem_view_remote); -void subrem_view_remote_add_data_to_show( +void subrem_view_remote_update_data_labels( SubRemViewRemote* subrem_view_remote, - const char* up_label, - const char* down_label, - const char* left_label, - const char* right_label, - const char* ok_label); + SubRemSubFilePreset** subs_presets); -void subrem_view_remote_set_presed_btn(SubRemViewRemote* subrem_view_remote, uint8_t presed_btn); void subrem_view_remote_set_state( SubRemViewRemote* subrem_view_remote, - SubRemViewRemoteState state); \ No newline at end of file + SubRemViewRemoteState state, + uint8_t presed_btn); \ No newline at end of file From 3e09793b54439065d77a01a5bd74cad1138bc605 Mon Sep 17 00:00:00 2001 From: gid9798 <30450294+gid9798@users.noreply.github.com> Date: Fri, 26 May 2023 18:14:15 +0300 Subject: [PATCH 16/23] Rename --- .../external/subghz_remote_new/application.fam | 10 +++++----- .../external/subghz_remote_new/subghz_remote_app_i.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_new/application.fam index a232fb30f0..7590e46a59 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_new/application.fam @@ -1,16 +1,16 @@ App( - appid="subrem_remote_fap", - name="Sub-GHz Remote", + appid="subrem_configurator", + name="SubRem Configurator", apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_app", requires=[ "gui", "dialogs", ], - stack_size=3 * 1024, + stack_size=2 * 1024, order=50, - fap_description="Remote control for transmission multiple *.sub files", - fap_category="Debug", #"Sub-Ghz" + fap_description="File Editor for the SubGhz Remote app", + fap_category="Sub-Ghz", fap_icon_assets="icons", fap_icon="icons/subrem_10px.png", ) \ No newline at end of file diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_new/subghz_remote_app_i.h index 7a07d768a7..ce5f31009a 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app_i.h +++ b/applications/external/subghz_remote_new/subghz_remote_app_i.h @@ -5,7 +5,7 @@ #include "scenes/subrem_scene.h" #include "helpers/txrx/subghz_txrx.h" -#include +#include #include "views/remote.h" #include "views/edit_menu.h" From 9c520c518837ef96c57e3a14e63de553672de658 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:06:26 +0300 Subject: [PATCH 17/23] Rename + don't touch power and module type on start --- .../application.fam | 4 ++-- .../helpers/subrem_custom_event.h | 0 .../helpers/subrem_presets.c | 0 .../helpers/subrem_presets.h | 0 .../helpers/subrem_types.h | 0 .../helpers/txrx/Readme.md | 0 .../helpers/txrx/subghz_txrx.c | 0 .../helpers/txrx/subghz_txrx.h | 0 .../helpers/txrx/subghz_txrx_i.h | 0 .../icons/DolphinNice_96x59.png | Bin .../icons/remote_scene/ButtonDown_7x4.png | Bin .../icons/remote_scene/ButtonLeft_4x7.png | Bin .../icons/remote_scene/ButtonRight_4x7.png | Bin .../icons/remote_scene/ButtonUp_7x4.png | Bin .../icons/remote_scene/Ok_btn_9x9.png | Bin .../icons/remote_scene/Pin_arrow_up_7x9.png | Bin .../icons/remote_scene/Pin_cell_13x13.png | Bin .../icons/remote_scene/Pin_star_7x7.png | Bin .../icons/remote_scene/back_10px.png | Bin .../icons/sub1_10px.png | Bin .../icons/subrem_10px.png | Bin .../scenes/subrem_scene.c | 0 .../scenes/subrem_scene.h | 0 .../scenes/subrem_scene_config.h | 0 .../scenes/subrem_scene_edit_label.c | 0 .../scenes/subrem_scene_edit_menu.c | 0 .../scenes/subrem_scene_edit_preview.c | 0 .../scenes/subrem_scene_edit_submenu.c | 0 .../scenes/subrem_scene_enter_new_name.c | 0 .../scenes/subrem_scene_open_map_file.c | 0 .../scenes/subrem_scene_open_sub_file.c | 0 .../scenes/subrem_scene_start.c | 0 .../subghz_remote_app.c | 10 +++++----- .../subghz_remote_app_i.c | 0 .../subghz_remote_app_i.h | 0 .../views/edit_menu.c | 0 .../views/edit_menu.h | 0 .../views/remote.c | 0 .../views/remote.h | 0 39 files changed, 7 insertions(+), 7 deletions(-) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/application.fam (79%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/subrem_custom_event.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/subrem_presets.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/subrem_presets.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/subrem_types.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/txrx/Readme.md (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/txrx/subghz_txrx.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/txrx/subghz_txrx.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/helpers/txrx/subghz_txrx_i.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/DolphinNice_96x59.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/ButtonDown_7x4.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/ButtonLeft_4x7.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/ButtonRight_4x7.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/ButtonUp_7x4.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/Ok_btn_9x9.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/Pin_arrow_up_7x9.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/Pin_cell_13x13.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/Pin_star_7x7.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/remote_scene/back_10px.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/sub1_10px.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/icons/subrem_10px.png (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_config.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_edit_label.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_edit_menu.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_edit_preview.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_edit_submenu.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_enter_new_name.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_open_map_file.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_open_sub_file.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/scenes/subrem_scene_start.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/subghz_remote_app.c (98%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/subghz_remote_app_i.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/subghz_remote_app_i.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/views/edit_menu.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/views/edit_menu.h (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/views/remote.c (100%) rename applications/external/{subghz_remote_new => subghz_remote_configurator}/views/remote.h (100%) diff --git a/applications/external/subghz_remote_new/application.fam b/applications/external/subghz_remote_configurator/application.fam similarity index 79% rename from applications/external/subghz_remote_new/application.fam rename to applications/external/subghz_remote_configurator/application.fam index 7590e46a59..9b164a0939 100644 --- a/applications/external/subghz_remote_new/application.fam +++ b/applications/external/subghz_remote_configurator/application.fam @@ -1,8 +1,8 @@ App( appid="subrem_configurator", - name="SubRem Configurator", + name="SubGHz Remote Configurator", apptype=FlipperAppType.EXTERNAL, - entry_point="subghz_remote_app", + entry_point="subghz_remote_config_app", requires=[ "gui", "dialogs", diff --git a/applications/external/subghz_remote_new/helpers/subrem_custom_event.h b/applications/external/subghz_remote_configurator/helpers/subrem_custom_event.h similarity index 100% rename from applications/external/subghz_remote_new/helpers/subrem_custom_event.h rename to applications/external/subghz_remote_configurator/helpers/subrem_custom_event.h diff --git a/applications/external/subghz_remote_new/helpers/subrem_presets.c b/applications/external/subghz_remote_configurator/helpers/subrem_presets.c similarity index 100% rename from applications/external/subghz_remote_new/helpers/subrem_presets.c rename to applications/external/subghz_remote_configurator/helpers/subrem_presets.c diff --git a/applications/external/subghz_remote_new/helpers/subrem_presets.h b/applications/external/subghz_remote_configurator/helpers/subrem_presets.h similarity index 100% rename from applications/external/subghz_remote_new/helpers/subrem_presets.h rename to applications/external/subghz_remote_configurator/helpers/subrem_presets.h diff --git a/applications/external/subghz_remote_new/helpers/subrem_types.h b/applications/external/subghz_remote_configurator/helpers/subrem_types.h similarity index 100% rename from applications/external/subghz_remote_new/helpers/subrem_types.h rename to applications/external/subghz_remote_configurator/helpers/subrem_types.h diff --git a/applications/external/subghz_remote_new/helpers/txrx/Readme.md b/applications/external/subghz_remote_configurator/helpers/txrx/Readme.md similarity index 100% rename from applications/external/subghz_remote_new/helpers/txrx/Readme.md rename to applications/external/subghz_remote_configurator/helpers/txrx/Readme.md diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.c similarity index 100% rename from applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.c rename to applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.c diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.h similarity index 100% rename from applications/external/subghz_remote_new/helpers/txrx/subghz_txrx.h rename to applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx.h diff --git a/applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h b/applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx_i.h similarity index 100% rename from applications/external/subghz_remote_new/helpers/txrx/subghz_txrx_i.h rename to applications/external/subghz_remote_configurator/helpers/txrx/subghz_txrx_i.h diff --git a/applications/external/subghz_remote_new/icons/DolphinNice_96x59.png b/applications/external/subghz_remote_configurator/icons/DolphinNice_96x59.png similarity index 100% rename from applications/external/subghz_remote_new/icons/DolphinNice_96x59.png rename to applications/external/subghz_remote_configurator/icons/DolphinNice_96x59.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/ButtonDown_7x4.png b/applications/external/subghz_remote_configurator/icons/remote_scene/ButtonDown_7x4.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/ButtonDown_7x4.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/ButtonDown_7x4.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/ButtonLeft_4x7.png b/applications/external/subghz_remote_configurator/icons/remote_scene/ButtonLeft_4x7.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/ButtonLeft_4x7.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/ButtonLeft_4x7.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/ButtonRight_4x7.png b/applications/external/subghz_remote_configurator/icons/remote_scene/ButtonRight_4x7.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/ButtonRight_4x7.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/ButtonRight_4x7.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/ButtonUp_7x4.png b/applications/external/subghz_remote_configurator/icons/remote_scene/ButtonUp_7x4.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/ButtonUp_7x4.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/ButtonUp_7x4.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/Ok_btn_9x9.png b/applications/external/subghz_remote_configurator/icons/remote_scene/Ok_btn_9x9.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/Ok_btn_9x9.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/Ok_btn_9x9.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/Pin_arrow_up_7x9.png b/applications/external/subghz_remote_configurator/icons/remote_scene/Pin_arrow_up_7x9.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/Pin_arrow_up_7x9.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/Pin_arrow_up_7x9.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/Pin_cell_13x13.png b/applications/external/subghz_remote_configurator/icons/remote_scene/Pin_cell_13x13.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/Pin_cell_13x13.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/Pin_cell_13x13.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/Pin_star_7x7.png b/applications/external/subghz_remote_configurator/icons/remote_scene/Pin_star_7x7.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/Pin_star_7x7.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/Pin_star_7x7.png diff --git a/applications/external/subghz_remote_new/icons/remote_scene/back_10px.png b/applications/external/subghz_remote_configurator/icons/remote_scene/back_10px.png similarity index 100% rename from applications/external/subghz_remote_new/icons/remote_scene/back_10px.png rename to applications/external/subghz_remote_configurator/icons/remote_scene/back_10px.png diff --git a/applications/external/subghz_remote_new/icons/sub1_10px.png b/applications/external/subghz_remote_configurator/icons/sub1_10px.png similarity index 100% rename from applications/external/subghz_remote_new/icons/sub1_10px.png rename to applications/external/subghz_remote_configurator/icons/sub1_10px.png diff --git a/applications/external/subghz_remote_new/icons/subrem_10px.png b/applications/external/subghz_remote_configurator/icons/subrem_10px.png similarity index 100% rename from applications/external/subghz_remote_new/icons/subrem_10px.png rename to applications/external/subghz_remote_configurator/icons/subrem_10px.png diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene.h b/applications/external/subghz_remote_configurator/scenes/subrem_scene.h similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene.h rename to applications/external/subghz_remote_configurator/scenes/subrem_scene.h diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_config.h b/applications/external/subghz_remote_configurator/scenes/subrem_scene_config.h similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_config.h rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_config.h diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_label.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_label.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_edit_label.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_label.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_menu.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_edit_menu.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_menu.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_preview.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_edit_preview.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_preview.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_submenu.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_edit_submenu.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_edit_submenu.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_enter_new_name.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_map_file.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_open_map_file.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_open_map_file.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_open_sub_file.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c diff --git a/applications/external/subghz_remote_new/scenes/subrem_scene_start.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_start.c similarity index 100% rename from applications/external/subghz_remote_new/scenes/subrem_scene_start.c rename to applications/external/subghz_remote_configurator/scenes/subrem_scene_start.c diff --git a/applications/external/subghz_remote_new/subghz_remote_app.c b/applications/external/subghz_remote_configurator/subghz_remote_app.c similarity index 98% rename from applications/external/subghz_remote_new/subghz_remote_app.c rename to applications/external/subghz_remote_configurator/subghz_remote_app.c index e026fe4dea..84100a2339 100644 --- a/applications/external/subghz_remote_new/subghz_remote_app.c +++ b/applications/external/subghz_remote_configurator/subghz_remote_app.c @@ -28,7 +28,7 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { //FURI_LOG_E(TAG, "Could not create folder %s", SUBREM_APP_FOLDER); } furi_record_close(RECORD_STORAGE); - + /* // Enable power for External CC1101 if it is connected furi_hal_subghz_enable_ext_power(); // Auto switch to internal radio if external radio is not available @@ -39,7 +39,7 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { } furi_hal_power_suppress_charge_enter(); - +*/ app->file_path = furi_string_alloc(); furi_string_set(app->file_path, SUBREM_APP_FOLDER); @@ -125,14 +125,14 @@ SubGhzRemoteApp* subghz_remote_app_alloc() { void subghz_remote_app_free(SubGhzRemoteApp* app) { furi_assert(app); - + /* furi_hal_power_suppress_charge_exit(); // Disable power for External CC1101 if it was enabled and module is connected furi_hal_subghz_disable_ext_power(); // Reinit SPI handles for internal radio / nfc furi_hal_subghz_init_radio_type(SubGhzRadioInternal); - +*/ // Submenu view_dispatcher_remove_view(app->view_dispatcher, SubRemViewIDSubmenu); submenu_free(app->submenu); @@ -183,7 +183,7 @@ void subghz_remote_app_free(SubGhzRemoteApp* app) { free(app); } -int32_t subghz_remote_app(void* p) { +int32_t subghz_remote_config_app(void* p) { UNUSED(p); SubGhzRemoteApp* subghz_remote_app = subghz_remote_app_alloc(); diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.c b/applications/external/subghz_remote_configurator/subghz_remote_app_i.c similarity index 100% rename from applications/external/subghz_remote_new/subghz_remote_app_i.c rename to applications/external/subghz_remote_configurator/subghz_remote_app_i.c diff --git a/applications/external/subghz_remote_new/subghz_remote_app_i.h b/applications/external/subghz_remote_configurator/subghz_remote_app_i.h similarity index 100% rename from applications/external/subghz_remote_new/subghz_remote_app_i.h rename to applications/external/subghz_remote_configurator/subghz_remote_app_i.h diff --git a/applications/external/subghz_remote_new/views/edit_menu.c b/applications/external/subghz_remote_configurator/views/edit_menu.c similarity index 100% rename from applications/external/subghz_remote_new/views/edit_menu.c rename to applications/external/subghz_remote_configurator/views/edit_menu.c diff --git a/applications/external/subghz_remote_new/views/edit_menu.h b/applications/external/subghz_remote_configurator/views/edit_menu.h similarity index 100% rename from applications/external/subghz_remote_new/views/edit_menu.h rename to applications/external/subghz_remote_configurator/views/edit_menu.h diff --git a/applications/external/subghz_remote_new/views/remote.c b/applications/external/subghz_remote_configurator/views/remote.c similarity index 100% rename from applications/external/subghz_remote_new/views/remote.c rename to applications/external/subghz_remote_configurator/views/remote.c diff --git a/applications/external/subghz_remote_new/views/remote.h b/applications/external/subghz_remote_configurator/views/remote.h similarity index 100% rename from applications/external/subghz_remote_new/views/remote.h rename to applications/external/subghz_remote_configurator/views/remote.h From 6dc1a0b6e8e8fcc3a35aefbec6277b6586fdb387 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:11:06 +0300 Subject: [PATCH 18/23] rename again --- .../external/subghz_remote_configurator/application.fam | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/external/subghz_remote_configurator/application.fam b/applications/external/subghz_remote_configurator/application.fam index 9b164a0939..00dc026971 100644 --- a/applications/external/subghz_remote_configurator/application.fam +++ b/applications/external/subghz_remote_configurator/application.fam @@ -1,6 +1,6 @@ App( appid="subrem_configurator", - name="SubGHz Remote Configurator", + name="Remote Configurator", apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_config_app", requires=[ From e6790e50c67b267d2c88aeddf20572db709dfa4f Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:17:27 +0300 Subject: [PATCH 19/23] fix crash --- .../scenes/subrem_scene_open_sub_file.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c index 75dc216704..fa74705949 100644 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c +++ b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c @@ -11,21 +11,23 @@ SubRemLoadSubState subrem_scene_open_sub_file_dialog(SubGhzRemoteApp* app) { SubRemSubFilePreset* sub = app->map_preset->subs_preset[app->chusen_sub]; - FuriString* temp_file_path = furi_string_alloc_set(sub->file_path); + FuriString* temp_file_path = furi_string_alloc(); + + if(furi_string_empty(sub->file_path)) { + furi_string_set(temp_file_path, SUBGHZ_RAW_FOLDER); + } else { + furi_string_set(sub->file_path, SUBGHZ_RAW_FOLDER); + } SubRemLoadSubState ret = SubRemLoadSubStateNotSet; DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sub1_10px); - browser_options.base_path = SUBGHZ_APP_FOLDER; + browser_options.base_path = SUBGHZ_RAW_FOLDER; // Input events and views are managed by file_select - if(!dialog_file_browser_show( - app->dialogs, - temp_file_path, - furi_string_empty(temp_file_path) ? NULL : temp_file_path, - &browser_options)) { + if(!dialog_file_browser_show(app->dialogs, temp_file_path, temp_file_path, &browser_options)) { } else { // Check sub file SubRemSubFilePreset* sub_candidate = subrem_sub_file_preset_alloc(); From c4cba38559e03b85ee6a4b510a74309ae9ad5678 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:18:08 +0300 Subject: [PATCH 20/23] oops --- .../scenes/subrem_scene_open_sub_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c index fa74705949..eb438cb928 100644 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c +++ b/applications/external/subghz_remote_configurator/scenes/subrem_scene_open_sub_file.c @@ -16,7 +16,7 @@ SubRemLoadSubState subrem_scene_open_sub_file_dialog(SubGhzRemoteApp* app) { if(furi_string_empty(sub->file_path)) { furi_string_set(temp_file_path, SUBGHZ_RAW_FOLDER); } else { - furi_string_set(sub->file_path, SUBGHZ_RAW_FOLDER); + furi_string_set(temp_file_path, sub->file_path); } SubRemLoadSubState ret = SubRemLoadSubStateNotSet; From 858ab99cecf11cbf3d662b423b9d3f05406eb2d3 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:21:26 +0300 Subject: [PATCH 21/23] don't put subrem_ in name by default --- .../scenes/subrem_scene_enter_new_name.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c b/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c index d33e070af5..b829723a3a 100644 --- a/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c +++ b/applications/external/subghz_remote_configurator/scenes/subrem_scene_enter_new_name.c @@ -14,9 +14,8 @@ void subrem_scene_enter_new_name_on_enter(void* context) { // Setup view TextInput* text_input = app->text_input; - bool dev_name_empty = false; - strncpy(app->file_name_tmp, "subrem_", SUBREM_MAX_LEN_NAME); + //strncpy(app->file_name_tmp, "subrem_", SUBREM_MAX_LEN_NAME); text_input_set_header_text(text_input, "Map file Name"); text_input_set_result_callback( text_input, @@ -24,7 +23,7 @@ void subrem_scene_enter_new_name_on_enter(void* context) { app, app->file_name_tmp, 25, - dev_name_empty); + false); ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( furi_string_get_cstr(app->file_path), SUBREM_APP_EXTENSION, ""); From 71a2d56ad35236416cb3cf9ce49428962f70fc19 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:29:08 +0300 Subject: [PATCH 22/23] update docs --- documentation/SubGHzRemotePlugin.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/documentation/SubGHzRemotePlugin.md b/documentation/SubGHzRemotePlugin.md index fd48eeca2b..948d8389da 100644 --- a/documentation/SubGHzRemotePlugin.md +++ b/documentation/SubGHzRemotePlugin.md @@ -1,11 +1,21 @@ # Sub-GHz Remote + +# UPDATE!!!!!! +## Now you can create and edit map files directly on flipper, go into Applications->Sub-GHz->Remote Configurator + +
+
+
+ + ### The SubGHz Remote Tool *requires* the creation of custom user map with `.txt` extension in the `subghz_remote` folder on the sdcard. #### If these files are not exist or not configured properly, **you will receive an error each time you try to select wrong file in the UniRF Tool**. ## You can add as many `.txt` map files as you want, file name doesn't matter! + ## Incorrect or unconfigured file error If the `.txt` file has not been properly configured, the following error will be thrown when trying to run the UniRF Remix app: From 2f35e980ef18b40723151baf4d302758f0080cc0 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 26 May 2023 19:52:43 +0300 Subject: [PATCH 23/23] rename rename --- .../external/subghz_remote_configurator/application.fam | 2 +- documentation/SubGHzRemotePlugin.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/applications/external/subghz_remote_configurator/application.fam b/applications/external/subghz_remote_configurator/application.fam index 00dc026971..f43dbcbd8e 100644 --- a/applications/external/subghz_remote_configurator/application.fam +++ b/applications/external/subghz_remote_configurator/application.fam @@ -1,6 +1,6 @@ App( appid="subrem_configurator", - name="Remote Configurator", + name="Remote Maker", apptype=FlipperAppType.EXTERNAL, entry_point="subghz_remote_config_app", requires=[ diff --git a/documentation/SubGHzRemotePlugin.md b/documentation/SubGHzRemotePlugin.md index 948d8389da..cbdc0995b5 100644 --- a/documentation/SubGHzRemotePlugin.md +++ b/documentation/SubGHzRemotePlugin.md @@ -2,7 +2,7 @@ # UPDATE!!!!!! -## Now you can create and edit map files directly on flipper, go into Applications->Sub-GHz->Remote Configurator +## Now you can create and edit map files directly on flipper, go into Applications->Sub-GHz->Remote Maker