Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki

KURS HOME ASSISTANT

Chcesz zautomatyzować swój dom bez skomplikowanego kodowania?
Zastanawiasz się nad wyborem sprzętu, oprogramowania i aplikacji?
Od czego zacząć przygodę z HA w 2025? Co będzie najlepsze na start?

Nasz kurs Home Assistant nauczy Cię krok po kroku, jak łatwo zautomatyzować swój dom i oszczędzić na rachunkach za prąd i ogrzewanie. Bez chmur, bez zbędnych abonamentów. Twoja przygoda z Home Assistant zaczyna się tutaj!

↓↓↓

    Szanujemy Twoją prywatność. Możesz wypisać się w dowolnym momencie.




    Teraz jest 11 maja 2025, o 20:31


    Strefa czasowa: UTC + 1





    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 75 ]  Przejdź na stronę 1, 2, 3  Następna strona
    Autor Wiadomość
    PostNapisane: 4 lis 2017, o 21:02 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Witam,

    Chciałbym stworzyć aplikację, która łączyć będzie się z procesorem za pośrednictwem Bluetooth.
    Po kliknięciu przycisku "Połącz" wysyłana będzie komenda z aktualnym czasem do synchronizacji.
    Czy ktoś może ma jakieś przydatne materiały albo jest w stanie mnie jakoś na kierunkować ?

    Oraz chciałbym zrobić dopasowanie aplikacji do różnych wielkości wyświetlaczy.
    Jeśli ktoś miałbym przydatne informację proszę o pomoc.

    Pozdrawiam
    Marcin



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 4 lis 2017, o 21:21 
    Offline
    Użytkownik

    Dołączył(a): 19 lip 2013
    Posty: 771
    Pomógł: 40

    Nie wiem jak Ty to widzisz ,ale ja to robie tak:
    Po polaczeniu z prockiem wysyłam komendę z telefonu żeby przesłał dane na wyświetlacz i procek na koniec wysyła prośbę o podanie czasu aktualnego. Jak odbiorę znak przez telefon to wysyłam aktualny czas i tyle. Pisze w Bascom wiec kod pewnie Ci się nie przyda a odczytanie czasu przez b4a jest banalnie proste.
    Co do scalowania to masz w poradnikach Mirkowych dokładnie to pokazane i omówione.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 4 lis 2017, o 21:58 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    [quote="grzeniu 73] odczytanie czasu przez b4a jest banalnie proste.
    Co do scalowania to masz w poradnikach Mirkowych dokładnie to pokazane i omówione.[/quote]

    Właśnie o to mi chodzi. O ten banalny kod w b4a :D
    A czy pamiętasz w którym poradniki Pan Mirek o tym ?:)



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 4 lis 2017, o 22:04 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27383
    Lokalizacja: Szczecin
    Pomógł: 1043

    Ja zawsze zachodzę w głowę - o co może chodzić początkującym gdy zadają takie pytania. Po samym pytaniu można się spodziewać, że chodzi o jakąś mroczną, ciemną, mega tajną procedurę synchronizacji do której potrzebny jest najtajnieszy z poradników świata ;)

    Ludzie, panowie, ... no Panowie - proszę o litość ....

    ileż razy można tłumaczyć i wyjaśniać o tak banalnej rzeczy jak komunikacja ASCII ... no na prawdę aż gdzieś tam w kręgosłupie słyszę metaliczny zgrzyt...

    czy to problem do procka wysłać string z czasem ??????

    "12:24:37"

    ?????? sparsować go i ustawić godzinę w procku ? nawet można osobno po przecinku i to komendą jakąś AT własną np

    AT+TIME=12,24,37

    no gdzie tu szukać problemu? jak tu doszukiwać się tajnych sposobów ?

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 5 lis 2017, o 08:58 
    Offline
    Użytkownik

    Dołączył(a): 19 lip 2013
    Posty: 771
    Pomógł: 40

    Składnia: [ Pobierz ] [ Ukryj ]
    język basic4gl
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

    Ja to tak robię, ale można tez prościej i najpierw ustawić format w jakim b4a ci to wyświetli. Wtedy masz to sformatowane w jednej linijce.
    A poradniki dotyczące drugiego problemu to chyba 2-3-4 odcinek o b4a. Zresztą chyba w większości się to przewija.


    Autor postu otrzymał pochwałę


    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 5 lis 2017, o 17:13 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Dziękuję wielkie za kod.
    Właśnie o to mi chodziło :)

    Panie Mirku problemem nie jest odbieranie kodu ze strony procka ani skonstruowania komendy "AT+TIME=12,24,37"
    Problemem jest zdobycie tego czasu poprzez B4A i dodanie jej do tej komendy :)

    Ale kolega Grzeniu bardzo ładnie to pokazał.

    Dziękuje bardzo
    Pozdrawiam i życzę miłego wieczoru.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 8 lis 2017, o 09:29 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Mam pytanie, jak przelac/udostepnic komus nasza aplikacje ? (oczywiscie osobie, ktora nie ma b4a)



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 8 lis 2017, o 09:40 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27383
    Lokalizacja: Szczecin
    Pomógł: 1043

    no tak jak wszystkie aplikacje na androida ... toż po to masz kompilator żeby wygenerował ci APliKację czyli plik *.apk To jest instalka


    Autor postu otrzymał pochwałę

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 14:41 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Mam jeszcze jedno pytanie. Moja aplikacja ma dwa layouty w mainie wszystko działa poprawnie chodzi mi o wysyłanie znaków do uC natomiast jeśli dodam do layout1 funkcje do wysyłania to nie widzi jej.. Czy w b4a można zrobić funkcje globalna ? albo muzę podłącza się ten layout1 do maina żeby funkcje były dostępne ?

    tak mam w main

    Składnia: [ Pobierz ] [ Ukryj ]
    język basic4gl
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    w layout wstawiam
    Składnia: [ Pobierz ] [ Ukryj ]
    język basic4gl
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



    Ostatnio edytowano 9 lis 2017, o 15:20 przez Morcinek92, łącznie edytowano 1 raz

    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 15:15 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Zlituj się i używaj interpunkcji, bo trzeba się domyślać o co Ci chodzi :/
    Czego nie widzi - suba czy flagi, bo to duża różnica.

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 15:24 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Wybacz.
    Mam dwa Layouty (1. Main, 2.Layout1)

    W drugim mam seekBara

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Natomiast funkcję do wysyłania w Main
    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    No i nie jestem w stanie w Layout1 wpisać sobie "Rozkaz( "MOC=" & SeekBarMoc.Value & Chr(13) & Chr(10) ) bo nie widzi funkcji "Rozkaz"

    Nie bardzo wiem, jak to zrobić...



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 15:28 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    a spróbuj Main.Rozkaz

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 15:49 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Pròbowałem, ale tak to nie działa. Nie jest dostępna funkcja "Rozkaz".



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 9 lis 2017, o 20:42 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    A zobacz Callsub(main, "rozkaz (....)"), sprawdź w dokumentacji bo o ile pamiętam to tych Callsub jest kilka wariantów.

    Wysłane ze srajfona

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 11:33 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Sprawdzałem, w funkcji Callsub też nie mam dostępu do funkcji ROZKAZ..

    Nawet kiedy odbieram dane z uC to w layout MAIN nie ma problemu wszystko łądnie się odbiera, ale jeśli chce te wartość przekazać do drugiej wartstwy w tedy dostaję ERROR.

    Składnia: [ Pobierz ] [ Ukryj ] [ Zaznacz wszystko ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    Obrazek



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 16:15 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Jedno podstawowe pytanie -czy drugi layout, ten na który przekazujesz dane był wcześniej załadowany?
    Operujesz na dwóch layoutach czy na dwóch activity?

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 16:59 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    na dwóch activity

    Dodałem poprzez PROJECT > ADD NEW MODULE > ACTIVITY MODULE



    chyba rozumiem swój błąd... powinem mieć dwa layouty a jeden activity..
    spróbuję teraz tak zrobić z tym, że już widzę, że jeden na drugi się nakłada ale pewnie jest jakaś funkcja na zamknięcie 1 i otwarcie drugiego. Już szukam



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:11 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Może być, a czy jak pytałem wcześniej, czy przed próbą skorzystania z funkcji ładujesz wcześniej Activity?
    Nie musi być widoczne, ale załadowane już tak.

    Nie muszą być to być layouty, osobiście preferuje osobne activity - pamięć.

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:30 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Żeby przejść do następnego layoutu klikam przycisk

    Składnia: [ Pobierz ] [ Ukryj ]
    język basic4gl
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    a w Layout1

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    I później w funkcji seekBar'a wywoływałem Callsub czy np. Main.Rozkaz

    Składnia: [ Pobierz ] [ Ukryj ]
    język basic4gl
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:40 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27383
    Lokalizacja: Szczecin
    Pomógł: 1043

    zmienne globalne mogą służyć do przekazywania danych

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:43 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Layout to tylko widok, więc Sub powinien odpalić się bez żadnych "dopisków", zaś Activity to tak jakby osobny podprogram(niewiem jak to się zwie w b4a, w vb6 było łatwiej) .
    Jeśli nie działa w ten sposób, to dodaj jakiegoś osobnego suba (tylko do testów), np z alertem, wtedy będzie wiadomo czy sub się nie odpala, czy to co próbujesz zrobić mu nie pasi(komunikaty w javie są chyba tylko dla programistów javy ;))

    ------------------------ [ Dodano po: 4 minutach ]

    Mirku, jakto do przekazania?
    Masz na myśli wyświetlenie zmiennej, to jest jasne jak słońce ;)
    Teraz dopiero zwróciłem uwagę że kolega chyba próbuje wywołać zdarzenie(a nie własnego suba), to ten numer nie przejdzie "zdalnie".

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:54 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27383
    Lokalizacja: Szczecin
    Pomógł: 1043

    Cytuj:
    Mirku, jakto do przekazania?

    No do przekazania - toż żeby przekazać jakieś wartości suche nie trzeba zaraz funkcji wołać tylko zapisać do zmiennych, odpalić lajałta drugiego i proszę - ma gotowe wartości

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 17:59 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Przekazanie samej wartości to akurat nie problem, równie dobrze można ustawić bezpośrednio(bez zmiennej), jak kto woli.

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:01 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Tak , mogę zrobić w ten sposób, że w Layout1:

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    wartość seekBar'a podam do zmiennej globalnej w tym przypadku "xyz", a w Layout1 wyślę

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    z tym, że on zostanie zrealizowany dopiero po wejściu w Layout1 bo umieściłem go w sekcji Activite_Resume bo nie bardzo wiem, w której miałby się innej znaleźć..
    Rozkaz ma być wysłany dopiero gdy ktoś zmieni wartość na suwaku.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:02 
    Offline
    Moderator
    Avatar użytkownika

    Dołączył(a): 03 paź 2011
    Posty: 27383
    Lokalizacja: Szczecin
    Pomógł: 1043

    Harry napisał(a):
    Przekazanie samej wartości to akurat nie problem

    dla ciebie nie problem ale jak ktoś nie wie - jak np autor wątku, że tak można to urasta do rangi dużego problemu, więc nie ma co mówić że to problem czy nie problem. Jest możliwość również taka i warto o tym wiedzieć - bo czasem proste rozwiązania bywają bardzo potrzebne.

    _________________
    zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:05 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Przekazanie wartości to nie jest problem.. bo jak pokazałem w przykładzie wyżej to jest proste , ale jak wysłać w tym samym momencie te wartości nie przechodząc do layoutu głównego ? bo to jest dla mnie problem



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:07 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Wiem, ale już wcześniej odpalał z wartością wpisaną z palca.

    Wysłane ze srajfona

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:33 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Nadal nie rozumiem, gdzie mam błąd.. możecie mi to jaśniej wyjaśnić?



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:49 
    Offline
    Użytkownik

    Dołączył(a): 14 sie 2016
    Posty: 905
    Pomógł: 39

    Bo robisz odwrotnie ;)
    Masz:
    Składnia: [ Pobierz ] [ Ukryj ]
    język vb
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

    czyli ustawiasz wartość seekbara wartością globalnej xyz
    a powinno być:
    Składnia: [ Pobierz ] [ Ukryj ]
    język vb
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

    Czyli masz podać aktualną wartość seekbara do zmiennej.

    _________________
    Moje porady są błędne,nie czytać,zbanować od razu.



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    PostNapisane: 10 lis 2017, o 18:59 
    Offline
    Użytkownik
    Avatar użytkownika

    Dołączył(a): 31 sty 2013
    Posty: 435
    Lokalizacja: Rybnik
    Pomógł: 6

    Z tym się zgadzam. Już wcześniej miałem to poprawione.
    Ale teraz powiedz mi jak to wysłać w czasie kiedy zmieniam wartości na sekBarze ?

    Bo jeśli mam w Layout Main:

    Składnia: [ Pobierz ] [ Ukryj ]
    język c
    Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


    to zostanie to wysłane dopiero kiedy przejdę na activiti MAIN

    a ja chcę żeby wartość seekbara została wysłana od razu po jego zmianie ..



    Góra
     Zobacz profil  
    cytowanie selektywne  Cytuj  
    Wyświetl posty nie starsze niż:  Sortuj wg  
    Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 75 ]  Przejdź na stronę 1, 2, 3  Następna strona

    Strefa czasowa: UTC + 1


    Kto przegląda forum

    Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 0 gości


    Nie możesz rozpoczynać nowych wątków
    Nie możesz odpowiadać w wątkach
    Nie możesz edytować swoich postów
    Nie możesz usuwać swoich postów
    Nie możesz dodawać załączników

    Szukaj:
    Skocz do:  
    Sitemap
    Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
    phpBB SEO