<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Yazılım Sörf Müzik]]></title><description><![CDATA[Profesyonel yazılımcı, amatör müzisyenin sörf günlüğü]]></description><link>http://cuneyt.aliustaoglu.biz/tr/</link><image><url>http://cuneyt.aliustaoglu.biz/tr/favicon.png</url><title>Yazılım Sörf Müzik</title><link>http://cuneyt.aliustaoglu.biz/tr/</link></image><generator>Ghost 2.1</generator><lastBuildDate>Sat, 12 Sep 2020 12:28:50 GMT</lastBuildDate><atom:link href="http://cuneyt.aliustaoglu.biz/tr/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Android ViewModel kullanım amacı ve basit bir örnek]]></title><description><![CDATA[Google, Android için MVVM mimarisini öneriyor. ViewModel ise bu mimarinin 3 ayağından birisi. Bu yazıda genel anlamıyla MVVM'den ziyade ViewModel'e neden ihtiyaç duyarız sorusuna cevap arayacağız.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/android-viewmodel-kullanim-amaci-ve-basit-bir-ornek/</link><guid isPermaLink="false">5e3e57dd74c8b85546e3561f</guid><category><![CDATA[Android]]></category><category><![CDATA[MVVM]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Tue, 11 Feb 2020 08:45:49 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Banner-1.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Banner-1.png" alt="Android ViewModel kullanım amacı ve basit bir örnek"><p>Google, Android için MVVM mimarisini öneriyor. ViewModel ise bu mimarinin 3 ayağından birisi. Bu yazıda genel anlamıyla MVVM'den ziyade ViewModel'e neden ihtiyaç duyarız sorusuna cevap arayacağız.</p><p>Konu ile ilgili örnekler genelde çok detaylı olunca; ben, ya sıkılıyorum ya da konuyu anlayamıyorum. O yüzden eğer size de benim gibiyseniz, bana ViewModel'i en iyi anlatan çok basit bir örneği paylaşmak istiyorum.</p><p>State yönetimi, gerek ön yüz gerekse de arka yüz olsun hemen her uygulamanın beynini oluşturur. Activity ise Android'in ön yüzünün önemli bir bileşeni. Eğer state yönetimini Activity üzerinde eski yöntemlerle tutmaya kalkacak olursak Activity'nin durumuna göre state'i kaybedebiliriz. State'i kaybettiğimizde yeniden oluşturmamız gerekecek. Bu hem kaynak hem de zaman kaybı demek. Hatta duruma göre veriyi tamamıyla bile kaybedebiliriz.</p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Activity-Events.png" class="kg-image" alt="Android ViewModel kullanım amacı ve basit bir örnek"><figcaption>Activity değişiklikleri</figcaption></figure><p>Yukarıdaki şemada basitçe Activity'nin durumlarını göstermeye çalıştım. Uygulamayı ilk açtığımızda Activity onCreate, onStart ve onResume durumlarından geçerek normal çalışma şeklini alıyor. Ekranı yan çevirdiğinizde, Activity onPause durumuna geçiyor ve Activity sonlandırılıyor. Çünkü Activity, Android ön yüzünün bir bileşeni. Ekran yan çevrildiğinde haliyle ön yüz ve nesnelerin şekli oldukça değişecek. Android'in Activity'i sonlandırıp tekrar oluşturması gerekiyor. Ancak bu değişikliklerin sadece görsellikte olması gerekiyor. Ekranın tuttuğu verinin aynen saklanması gerekir haliyle.</p><p>Telefon ekranı çevrildiğinde kullanıcı için aslında değişen bir şey yok. O, sadece ekranı çevirdiğini zannetse de arka planda Android, Activity'yi önce durduruyor daha sonra yeniden oluşturuyor. Bu durumda eğer Activity'nin kullandığı veriyi örneğin <code>onCreate</code> yordamında oluşturduysanız bu veri tekrardan oluşturulacak. </p><p>Çok çok basit bir örnek yapalım:</p><p>Empty Activity şablonunu kullanarak yeni bir Android projesi oluşturun. activity_main.xml dosyasındaki TextView kontrolüne bir <code>id</code> ekleyin:</p><pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;androidx.constraintlayout.widget.ConstraintLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.MainActivity&quot;&gt;

    &lt;TextView
        android:id=&quot;@+id/myTw&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:text=&quot;Hello World!&quot;
        app:layout_constraintBottom_toBottomOf=&quot;parent&quot;
        app:layout_constraintLeft_toLeftOf=&quot;parent&quot;
        app:layout_constraintRight_toRightOf=&quot;parent&quot;
        app:layout_constraintTop_toTopOf=&quot;parent&quot; /&gt;

&lt;/androidx.constraintlayout.widget.ConstraintLayout&gt;
</code></pre>
<p>Yukarıda ben <code>android:id="@+id/myTw"</code> satırını ekledim.</p><p>Yeni bir Java sınıfı oluşturun. Herhangi bir isim olabilir.</p><pre><code class="language-java">package com.example.basicviewmodelex;

import androidx.lifecycle.ViewModel;

import java.text.SimpleDateFormat;
import java.util.Date;

public class MyDataGenerator {

    private String tarihSaat = null;

    public String getData(){
        if (tarihSaat == null){
            createData();
        }
        return tarihSaat;
    }

    public void createData(){
        SimpleDateFormat formatter = new SimpleDateFormat(&quot;dd/MM/yyyy HH:mm:ss&quot;);
        Date date = new Date();
        tarihSaat = formatter.format(date);
    }


}

</code></pre>
<p>Bu sınıf, bir örneği (instance) oluşturulduğunda oluşturulduğu tarihi <code>tarihSaat</code> değişkenine atıyor. Tek yaptığı bu.</p><p>Şimdi de MainActivity.class dosyasında bu sınıfın bir örneğini oluşturalım:</p><pre><code class="language-java">public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        MyDataGenerator myDataGenerator = new MyDataGenerator();
        String data = myDataGenerator.getData();

        TextView tw = findViewById(R.id.myTw);
        tw.setText(data);
    }
}
</code></pre>
<p>Şimdi projeyi çalıştırın ve metin kutusuna tarih ve saatin yazılmış olduğunu görün. </p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Screenshot_1581197649.png" class="kg-image" alt="Android ViewModel kullanım amacı ve basit bir örnek"><figcaption>Activity ilk kez oluşturuldu</figcaption></figure><p>Buraya kadar her şey çok normal. Bu tarihi not alın ve telefonu yatay hale getirin. </p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Activity-yatay.png" class="kg-image" alt="Android ViewModel kullanım amacı ve basit bir örnek"><figcaption>Activity yatay hale getirildi</figcaption></figure><p>Tarihe dikkat edin. Activity yatay hale getirildiğinde ben aslında tarihi tekrar oluşturmak istemiyorum. ViewModel bileşeni bu noktada önemli hale geliyor. Uygulamalarımızın kullanıcıları için Activity bir şey ifade etmiyor. Onlar ekranı çevirseler de, uygulamayı geçici olarak kapatsalar da tekrar doğru veriyi görmek istiyorlar. </p><p>Şimdi kodumuzda 2 ufak değişiklik yapalım. MyDataGenerator sınıfını ViewModel sınıfını kullanarak oluşturalım. Kalan kısımlar aynen kalsın.</p><pre><code>public class MyDataGenerator extends ViewModel
</code></pre>
<p>MainActivity dosyasında ise MyDataGenerator sınıfını çağırdığımız yeri aşağıdaki gibi güncelleyelim:</p><pre><code class="language-java">// MyDataGenerator myDataGenerator = new MyDataGenerator();
MyDataGenerator myDataGenerator = new ViewModelProvider(this).get(MyDataGenerator.class);
</code></pre>
<p>Hepsi bu kadar. Bu değişikliklerden sonra ekranı ters de çevirsek metin kutusunda hep aynı tarihi görüyoruz. </p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Activity-ViewModel-dik.png" class="kg-image" alt="Android ViewModel kullanım amacı ve basit bir örnek"><figcaption>Activity dik konumda</figcaption></figure><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Activity-ViewMode-yatay.png" class="kg-image" alt="Android ViewModel kullanım amacı ve basit bir örnek"><figcaption>Activity yatay konumda</figcaption></figure><p>ViewModel, Activity'nin onStop durumundan hiç etkilenmeden değerini korumayı başardı. ViewModel, Activity tamamen sonlana dek durumunu korumayı başaracak. </p><p>Örneği ekranı yan çevirme ile ilgili verdik. Bu en kolay gözlemlenebilir örnek olduğu için. Aslında Android'in Activity'i sonlandırabileceği tek yer yan çevirme değildir. Özellikle uygulama arka planda çalışırken Activity Android tarafından onPause konumuna geçebilir. Yani stabil bir state yapısına ihtiyacımız her durumda vardır.</p>]]></content:encoded></item><item><title><![CDATA[Android - Jetpack Navigation ile ekranlar arası geçiş]]></title><description><![CDATA[Navigation (bazen routing) olarak bilinen sayfa/ekran arası geçişler; web, masaüstü, veya mobil farketmeksizin her türlü ön yüz (front-end) geliştiriciliğinin bel kemiğini oluşturur. Android üzerinde bu işler Jetpack ile beraber çok daha kolay hale geldi. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/android-jetpack-navigation-ile-ekranlar-arasi-gecis/</link><guid isPermaLink="false">5e3b913274c8b85546e35617</guid><category><![CDATA[Android]]></category><category><![CDATA[Jetpack]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Thu, 06 Feb 2020 05:30:05 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Banner.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/Banner.png" alt="Android - Jetpack Navigation ile ekranlar arası geçiş"><p>Navigation (bazen routing) olarak bilinen sayfa/ekran arası geçişler; web, masaüstü, veya mobil farketmeksizin her türlü ön yüz (front-end) geliştiriciliğinin bel kemiğini oluşturur. Android üzerinde bu işler Jetpack ile beraber çok daha kolay hale geldi. Bu yazıda basit bir örnekle fragmentler arası geçişlerin Jetpack kütüphaneleri kullanılarak nasıl yapılacağına bakalım.</p><p>Vereceğimiz örneğin omurgasını kısaca listelemek gerekirse:</p><ul><li>activity_main üzerinde NavHostFragment bileşeni</li><li>NavHostFragment üzerinde 2 tane fragment ve bu fragmentler arası geçişler (action)</li><li>Fragment içerisinde action'ı çağıracak düğme kontrolü</li><li>Ekranın üst kısmındaki geri tuşu</li></ul><p>Şimdi de adım adım bu bileşenleri ekleyelim:</p><ul><li>Öncelikle yeni bir Android projesi yaratın ve şablon kısmında "Empty Activity"'e tıklayın. </li><li><code>app</code> kısmına sağ tıklayarak "New &gt; Android Resource File" seçin. </li><li><code>File name</code> kısmına istediğiniz bir ismi verip <code>Resource type</code> kısmına ise <code>Navigation</code> diyerek devam edin. OK tuşuna bastığınızda Android Studio gradle bağımlılıklarını eklemenizi isteyecek. Ona da tamam diyerek devam edin. </li></ul><p>build.gradle (Module:app) dosyasına bakacak olursanız aşağıdaki satırların (versiyon numaraları farklı olabilir elbet) eklenmiş olduğunu göreceksiniz. Eğer bir şekilde Android Studio eklemeyi başaramamış ise dependencies kısmına siz ekleyin.</p><pre><code>implementation 'androidx.navigation:navigation-fragment:2.2.0'
implementation 'androidx.navigation:navigation-ui:2.2.0'
</code></pre>
<ul><li>Daha sonra <code>New &gt; Fragment &gt; Fragment (Blank)</code> kullanarak 2 adet fragment ekleyin. Birine ListeFragment öbürüne DetayFragment diyebilirsiniz. Burada "Include fragment factory methods" ve "Include interface callbacks" seçeneklerinin seçili durumunu kaldırın.</li><li>Android Studio her fragment için biri java öbürü xml olmak üzere 2 dosya oluşturacak. (ör. ListeFragment.java ve fragment_liste.xml)</li><li>fragment_liste.xml içerisindeki metin kontrolünü silin ve yerine bir tane düğme ekleyin. Ben FloatingActionButton ekledim. Verdiğimiz basit örnek için hangi kontrol olduğunun çok önemi yok. Benim fragment_liste.xml dosyam aşağıdaki gibi oldu:</li></ul><pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;FrameLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    xmlns:app=&quot;http://schemas.android.com/apk/res-auto&quot;
    xmlns:tools=&quot;http://schemas.android.com/tools&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;
    tools:context=&quot;.ListFragment&quot;&gt;

    &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id=&quot;@+id/fab_list&quot;
        android:layout_width=&quot;wrap_content&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:clickable=&quot;true&quot;
        android:src=&quot;@android:drawable/btn_star_big_on&quot;
        android:focusable=&quot;true&quot;
        android:layout_gravity=&quot;bottom|right&quot;
        android:layout_margin=&quot;10dp&quot;
        /&gt;
&lt;/FrameLayout&gt;
</code></pre>
<ul><li>activity_main.xml dosyasını açın ve içerisindeki metin bileşenini silin ve bir NavHostFragment ekleyin. Eklerken bu hostun hangi resource dosyasından geleceğini soran bir pencere açılacak. Bu örnekte sadece 1 navigation kontrolü olduğu için listedeki tek elemanı seçin ve devam edin.</li><li>Şimdi ise <code>app &gt; res &gt; navigation</code> içerisindeki xml dosyasını açın ve yeşil artı ikonu bulunan "New Destination" tuşuna basarak 2 fragmenti ekleyin. Liste fragmentinden detay fragmentine sürükle bırakla bir action ekleyin. Aşağıdaki gibi bir görüntü oluşması gerekiyor.</li></ul><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/NavHostFragment.png" class="kg-image" alt="Android - Jetpack Navigation ile ekranlar arası geçiş"><figcaption>Nav Host Fragment</figcaption></figure><p>Artık kodlamaya geçebiliriz. Öncelikle FloatingActionButton'ın işlemini gerçekleştirelim. Tuşa bastığımızda yukarıda okla gösterilen action'ı çağıracağız ve liste fragmentinden detay fragmentine geçiş yapacağız. Çoğu işlemi Android arka planda gerçekleştiriyor. Bize sadece action'ı çağırmak düşüyor. Benim kodum aşağıdaki gibi oldu. İsimlendirmelerimiz farklı olacağı için olduğu gibi yapıştırırsanız hata alabilirsiniz. </p><pre><code class="language-java">public class ListFragment extends Fragment implements View.OnClickListener {


    public ListFragment() {

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View vw = inflater.inflate(R.layout.fragment_list, container, false);
        FloatingActionButton fab = vw.findViewById(R.id.fab_list);
        fab.setOnClickListener(this);
        return vw;
    }

    @Override
    public void onClick(View v) {

        NavDirections action = new ActionOnlyNavDirections(R.id.action_listFragment_to_detailFragment);
        Navigation.findNavController(v).navigate(action);
    }
}
</code></pre>
<p>FloatingActionButton'ın ID'sini kullanarak referansına eriştik ve OnClickListener yardımıyla ekran geçişini tanımlayan action'ı çağırdık.</p><p>Şimdi de MainActivity.java'yı aşağıdaki gibi değiştirerek geri tuşunu aktif hale getirelim.</p><pre><code class="language-java">public class MainActivity extends AppCompatActivity {

    private NavController navController;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        navController = Navigation.findNavController(this, R.id.fragment);
        NavigationUI.setupActionBarWithNavController(this, navController);

    }

    @Override
    public boolean onSupportNavigateUp() {
        return NavigationUI.navigateUp(navController, (DrawerLayout) null);
    }
}
</code></pre>
<p>Sonuç aşağıdaki gibi:</p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2020/02/JetpackNavigationDemo.gif" class="kg-image" alt="Android - Jetpack Navigation ile ekranlar arası geçiş"><figcaption>Jetpack Navigation</figcaption></figure><p>Sonuç olarak Jetpack Navigation, standart işlemleri çok kolaylaştırıyor. En güzel yanı da neredeyse her yazılım geliştirici bunu benzer şekilde kullanıyor ve başkasının yazdığı kodu okumayı da oldukça kolay hale getiriyor.</p>]]></content:encoded></item><item><title><![CDATA[Dalga Sörfüne başlamak ve sörf tahtası seçimi]]></title><description><![CDATA[Dalga sörfü Türkiye'de çok yaygın bir spor değil. Yine de Türkiye'de dalga bulmak imkansız değildir. Karadeniz ve Akdeniz'de pek çok noktada dalga sörfü yapılmaktadır; ama, pek istikrarlı olmadığından bir kültür halini alması pek mümkün gözükmüyor. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/dalga-sorfune-baslamak-ve-sorf-tahtasi-secimi/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb3e</guid><category><![CDATA[Sörf]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sat, 17 Aug 2019 08:24:26 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/surfboards.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/surfboards.jpg" alt="Dalga Sörfüne başlamak ve sörf tahtası seçimi"><p>Blog yazmaya başlamadan önce hobilerim ve mesleğim hakkında yazılar yazmak istemiştim ancak 1 yılın sonunda sadece meslek hakkında yazdığımı görüyorum. Biraz da sörf hakkında yazalım.</p><p>Dalga sörfü Türkiye'de çok yaygın bir spor değil. Elbette, bunun en büyük sebebi; Türk sularının iç deniz olması sebebiyle dalgalı olmamasıdır. Yine de Türkiye'de dalga bulmak imkansız değildir. Karadeniz ve Akdeniz'de pek çok noktada dalga sörfü yapılmaktadır; ama, pek istikrarlı olmadığından bir kültür halini alması pek mümkün gözükmüyor. Elbette bu bizim başlamamamız için bir sebep değil.</p><p>Dalga sörfüne nasıl başlarız? Nasıl bir sörf tahtası almamız gerekir? Boy, kilo önemli mi? Tehlikeli bir spor mu? Şimdi bunları inceleyelim.</p><p>Yeni Zelanda'ya ilk taşındığımda, denize gittiğimde biraz hayal kırıklığına uğramıştım. Büyük Okyanus, bizim Akdeniz ve Karadeniz'e göre çok daha dalgalı. Yüzmek pek mümkün değildi. Zaten denize baktığınızda da yüzen(ya da yüzmeye çalışan) insan sayısı pek fazla değildi. İnsanlar ya sörf yapıyor ya da denize girmeden plajda oturuyorlardı. İlk gözlemlerim sonunda kendimi sörf fikrine alıştırmaya başlamıştım.</p><h3 id="motivasyon">Motivasyon</h3><p>Sörf biraz futbola benziyor. Hemen herkes futbol oynayabilir. İyi ya da kötü. Mesela basketbol böyle değil. Kötü basketbol oynayan birisi zaten ya kendisi oynamak istemez ya da oynatmazlar. Sörf böyle değil. Profesyonel sörf çok zor bir spordur. Fakat; amatör olarak yüzmeyi bilen herkes, sörf tahtasını satın alıp denize girdiği anda sörfçüdür. Amaç eğlenmek. Ünlü bir laf var:</p><p><em>&quot;En iyi sörfçü, dalgaların içinde eğlenmesini en iyi bilendir&quot;</em></p>
<p>Denizi ve suyu seven birisi, denge konusunda çok kötü de olsa; pek dalga yakalayamasa da sörften çok keyif alabilir. Müzik aleti öğrenmek mesela, oldukça zordur. Yetenekten ziyade sabır ister. Çalamadığınız zaman sıkılırsınız. Sıkıldığınız için de kendinizi geliştiremezsiniz. Sörf böyle değil. En başta pek beceremeseniz de sıkılmazsınız. Ertesi gün tekrar gitmek istersiniz. En sonunda iyi ya da kötü sörf yapar hale gelirsiniz.</p><h3 id="s-rf-tahtas-se-imi">Sörf Tahtası seçimi</h3><p>Sörfe başlamak için ihtiyacınız olan ilk şey elbette ki sörf tahtası. Sörf tahtaları genel olarak ikiye ayrılıyor:</p><ol><li>Longboard</li><li>Shortboard</li></ol><p>Ancak tanım konusu biraz karışık. Genellikle 8-foot (2.43m) ve üzeri longboard, 7 foot(2.13m) ve aşağısı ise shortboard olarak kabul edilir. 7-8 foot ise ne shortboard ne de longboard adlandırılır. Bunlara da <code>mini mal</code> ya da <code>funboard</code> denilir. Pratikte 8 foot oldukça uzun bir tahta olmasına rağmen resmi longboard turnuvalarına genellikle 9 foot altında bir tahta ile katılamazsınız. Bu yüzden resmi olarak longboard boyutu 9ft ve üzeridir ancak pratikte 8ft ve üzerine longboard derler.</p><table>
<thead>
<tr>
<th>Surf Tahtası</th>
<th>Boyut</th>
</tr>
</thead>
<tbody>
<tr>
<td>Shortboard</td>
<td>7ft ve altı</td>
</tr>
<tr>
<td>Funboard (mini mal)</td>
<td>7ft-8ft</td>
</tr>
<tr>
<td>Longboard (pratikte)</td>
<td>8ft ve üstü</td>
</tr>
<tr>
<td>Longboard (resmi)</td>
<td>9ft ve üstü</td>
</tr>
</tbody>
</table>
<figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/shortboards.jpeg" class="kg-image" alt="Dalga Sörfüne başlamak ve sörf tahtası seçimi"><figcaption>Shortboard</figcaption></figure><p>İnsanlar genellikle, boy ile kullanılacak sörf tahtasının uzunluğu arasında bir ilişki olması gerektiğini düşünürler, özellikle de kayak yapanlar. Sörfte böyle bir ilişki yoktur. Ya da hem vardır hem yoktur diyebiliriz. Ancak uzun boylular uzun tahta, kısa boylular kısa tahta kullanır düşüncesi yanlıştır. Boydan ziyade kilo ve deneyim daha önemlidir.</p><p>Başlangıç aşamasında shortboard ile dalga yakalamak oldukça zordur. Shortboard çeviktir ancak hacminin düşük olması sebebiyle ayağa kalktığınız anda tahta suya gömülmeye başlayacaktır. Ayağa ne kadar erken kalkarsanız tahtayı dalganın akışına daha etkili bir şekilde yönlendirirsiniz. Ayrıca dalganın henüz kırılmadan sahip olduğu potansiyel enerjiyi tümüyle kullanabilirsiniz. Ayağa kalkma, dengeyi sağlama, sörf tahtasını gereken konuma getirme gibi eylemler deneyimsiz birisi için biraz zor olacağından shortboard yeni başlayanlar için önerilmez.</p><p>Longboard, yüksek hacmi sebebiyle kolay kolay batmaz. Bu da size dalgayı yakalayıp kontrol etme konusunda kolaylık sağlar. O yüzden başlangıç seviyesi için longboard veya funboard oldukça idealdir. Ancak bu da demek değildir ki her longboard kullanan sörfçü deneyimsizdir. Bu biraz da tercih meselesidir. Kimileri çok deneyimli olsa da uzun tahtadan daha çok hoşlanmaktadır. Kariyerini longboarder olarak sürdüren pek çok profesyonel sörfçü vardır.</p><p>Gerçek anlamda başlangıç sörf tahtası 7 ile 9 ft arası değişen ve yumuşak maddeden yapılmış olandır. Sörf tahtaları genellikle sert maddelerden yapılır. Çarptığı zaman acı verebilir. Sörf yaparken elbet başkasının da size çarpma ihtimali vardır ama çoğunlukla size kendi sörf tahtanız çarpar. Bu sebeple hiç sörf yapmadıysanız yumuşak sörf tahtalarını öneririm</p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/foamie.jpg" class="kg-image" alt="Dalga Sörfüne başlamak ve sörf tahtası seçimi"><figcaption>8 ft yumuşak sörf tahtası</figcaption></figure><p>Bu tahtalara foamie de denilir. Oldukça yumuşaktır ve hacmi de oldukça geniştir. Bu yüzden oldukça stabildir ve beyaz dalga üzerinde bile kolaylıkla hareket imkanı sağlar. Bu tahta üzerine düştüğünüzde veya tahta size çarptığında canınız çok yanmaz. </p><p>Başlangıç için tavsiyem yukarıdaki gibi bir sörf tahtası bulmanızdır. 1 sene sonunda daha küçük tahtalarla devam edebilirsiniz. Ancak longboard ile sörf yapmanın tadı da başkadır. Ayrıca küçük dalgalarda shortboard ile dalga yakalamanız imkansıza yakındır. Yakalasanız bile çok kısa sürede yavaşlar. </p><p>İlerleyen zamanlarda dalga sörfü ile ilgili daha fazla bilgi vermeye çalışacağım.</p>]]></content:encoded></item><item><title><![CDATA[Espruino: JavaScript kullanarak ESP8266 ve ESP32 programlama]]></title><description><![CDATA[JavaScript gerçek anlamda "fullstack" bir dil. Kolaylıkla hem önyüz hem de arkayüz programları yazabiliyoruz. Peki JavaScript kullanarak çip programlamayı düşündünüz mü? Espruino buna imkan veren bir platform. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/espruino-javascript-kullanarak-esp8266-ve-esp32-programlama/</link><guid isPermaLink="false">5d5787e174c8b85546e35601</guid><category><![CDATA[ESP8266]]></category><category><![CDATA[ESP32]]></category><category><![CDATA[ESP-12E]]></category><category><![CDATA[Espruino]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sat, 17 Aug 2019 07:04:35 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/banner-espruino.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/banner-espruino.jpg" alt="Espruino: JavaScript kullanarak ESP8266 ve ESP32 programlama"><p>JavaScript gerçek anlamda "fullstack" bir dil. Kolaylıkla hem önyüz hem de arkayüz programları yazabiliyoruz. Peki JavaScript kullanarak çip programlamayı düşündünüz mü? Espruino buna imkan veren bir platform. </p><p><a href="https://www.espruino.com/">https://www.espruino.com/</a></p><p>Espruino ücretsiz bir firmware ve ESP8266 ve ESP32'nin yanında pek çok çipi de destekliyor. Aslında bu firmware'i (aygıt yazılımı) oluşturanların resmi olarak destekledikleri kendi donanımları da var. Ancak bunlar biraz daha pahalı. Biz fiyatı 2-5 dolar civarı olan ESP8266 ve ESP32 çiplerini kullanacağız.</p><p>Çip içerisinde JavaScript dilini kullanabilmek için öncelikle çipe bu dili tanıtmamız gerekiyor. Yani firmware kurmamız gerekiyor. Firmware (aygıt yazılımı), bir nevi çipin işletim sistemi. Tüm bu işlemleri yapmak için de sistemimizde NodeJS ve NPM'in kurulu olması gerekiyor. Eğer kurulu değilse aşağıdaki adresten son sürümünü indirip kurabilirsiniz</p><p><a href="https://nodejs.org">https://nodejs.org</a></p><p>Tüm kurulumu terminal üzerinden gerçekleştireceğiz. Kurulumu tamamladıktan sonra hem node hem de npm kurulumunun sorunsuz geçtiğini anlamak için aşağıdaki komutları kullanalım. npm, Nodejs'in resmi paket yöneticisi olduğu için node ile birlikte sisteme yüklenecektir.</p><pre><code class="language-sh">node -v
npm -v
</code></pre>
<p>Şimdi ise Espruino'nun resmi sayfasına giderek seçtiğimiz çipe firmware'i yükleyebiliriz.</p><p><a href="https://www.espruino.com/Download">https://www.espruino.com/Download</a></p><p>Ancak bu işlemler oldukça karmaşık. Ben bu karmaşayı azaltmak amacıyla aşağıdaki paketi oluşturdum.</p><p><a href="https://www.npmjs.com/package/espruino-create-project">https://www.npmjs.com/package/espruino-create-project</a></p><pre><code class="language-sh">npm install -g espruino-create-project
</code></pre>
<p>Bu paket global olarak (-g parametresi ile) sisteme yükledim.</p><p>Daha sonra bu paketi kullanarak yeni bir proje oluşturalım:</p><pre><code class="language-sh">espruino-create-project init my-esp8266-project --chip esp8266 --baud 115200 --port PORT1 --author 'Cuneyt Aliustaoglu'
</code></pre>
<p>Buradaki bazı parametreler sisteminize ve isteğinize göre değişebilir. chip parametresini çipinizi seçin. Şimdilik sadece esp8266 veya esp32 desteklenmekte. Port, Windows üzerinde genellike PORT1, PORT2 vs. şeklindedir. Ben mac kullandığım için portun adı cu.SLAB_USBtoUART şeklinde oldu. </p><img src="https://raw.githubusercontent.com/aliustaoglu/espruino-create-project/master/help/demo.gif" alt="Espruino: JavaScript kullanarak ESP8266 ve ESP32 programlama"><p>Bu işlem biraz zaman almakta. Aygıt yazılımı indiriliyor ve klasör oluşturuluyor. Klasör oluşturulduktan sonra `cd my-esp8266-project` komutu ile klasörün içine girelim. Şimdi aygıt yazlımı kuruluma hazır.</p><p>Öncelikle çip içindeki aygıt yazılımını silelim. </p><pre><code>npm run erase
</code></pre>
<p>Şimdi de Espruino'yu yükleyelim:</p><pre><code>npm run flash
</code></pre>
<p>Bu işlemler sırasında hata alırsanız büyük ihtimal yanlış port numarası kullanıyorsunuz. Portu değiştirmek için aşağıdaki komutu kullanabilirsiniz:</p><pre><code class="language-sh">espruino-create-project update --port PORT2
</code></pre>
<p>Artık programımızı yazmaya hazırız. Arduino IDE'ye ihtiyacımız olmayacak. vscode, atom hatta notepad veya sevdiğiniz bir editörü kullanabilirsiniz.</p><figure class="kg-card kg-image-card"><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2019/08/espruino-yanip-sonen-led-1.png" class="kg-image" alt="Espruino: JavaScript kullanarak ESP8266 ve ESP32 programlama"><figcaption>JavaScript ile ESP8266 için yanıp sönen LED uygulaması</figcaption></figure><p>Şimdi src klasörü içerisindeki main.js dosyasını aşağıdaki gibi düzenleyin:</p><pre><code class="language-js">E.on('init', function () {
  var led = 0
  setInterval(function () {
    digitalWrite(2, led)
    led = !led
  }, 1000)
})

</code></pre>
<p>Ve bu dosyayı ESP8266 üzerinde yükleyelim:</p><pre><code class="language-sh">npm run upload
</code></pre>
<center><img src="https://raw.githubusercontent.com/aliustaoglu/blog-assets/master/2019-08-18%20Espruino%20led/yanip-sonen-led.gif?token=ADYPZYHGF5FKJY4PRD3SEP25K6RUA" alt="Espruino: JavaScript kullanarak ESP8266 ve ESP32 programlama"></center><p>Espruino'da Arduino'daki gibi setup() ve main() fonksiyonları bulunmuyor. Çipe yalnızca tek bir dosya gönderiyoruz. Ancak geliştirme aşamasında çok sayıda dosya kullanabiliriz. npm run upload dediğimiz zaman, tüm dosyalar tek bir dosya içerisine sıkıştırılıyor ve tek bir dosya olarak gönderiliyor. JavaScript olaya dayalı (event-driven) bir dil. Dolayısıyla Arduino'daki loop görevini eventler ya da zamanlayıcılar ile yapmamız gerekiyor.</p><p>Yukarıdaki çok basit bir program. Bu yazıda sadece Espruino aygıt yazılımını nasıl kuracağımızı ve JavaScript'i ESP8266 ile nasıl kullanacağımızı anlatmak istedim. Gelecek yazılarda JavaScript ve ESP8266 veya ESP32 ile sensörden nasıl veri okunur, OLED ekranlara nasıl yazı yazılır gibi örnekleri vermeyi düşünüyorum.</p>]]></content:encoded></item><item><title><![CDATA[React içerisinde Google Maps Kullanımı]]></title><description><![CDATA[Google Haritalar servisinin, React için özelleştirilmiş resmi bir kütüphanesi yok. JS kütüphanesi mevcut. Ancak bu kütüphaneyi direkt React içerisinde React bileşeni gibi kullanabilmek için bazı yöntemlere başvurmamız gerekiyor.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/react-icerisinde-google-maps-kullanimi/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb3c</guid><category><![CDATA[React]]></category><category><![CDATA[Google]]></category><category><![CDATA[Maps]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Mon, 04 Jun 2018 08:44:09 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/react-js-google-maps.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/react-js-google-maps.png" alt="React içerisinde Google Maps Kullanımı"><p>Google Haritalar servisinin, React için özelleştirilmiş resmi bir kütüphanesi yok. JS kütüphanesi mevcut. Ancak bu kütüphaneyi direkt React içerisinde React bileşeni gibi kullanabilmek için bazı yöntemlere başvurmamız gerekiyor. Yani direk <code>import { GoogleMap } from 'google-maps'</code> gibi bir kullanım yok. Bu işi yapan bazı resmi olmayan kütüphaneler var, fakat bu yazıda harici kütüphanelere başvurmadan bu işlemleri gerçekleştireceğiz.</p>
<p>Şimdi nedir bu yöntemler onlara bakalım. 2 temel adım var:</p>
<ol>
<li>Tembel yükleme (lazy loading): <a href="https://stackblitz.com/edit/react-67pggp?file=index.js" target="_blank">DEMO</a></li>
<li>React bileşenlerini harita içersine entegre etmek: <a href="https://stackblitz.com/edit/react-rdevxo?file=InfoWindow.js" target="_blank">DEMO</a></li>
</ol>
<h2 id="1tembelykleme">1. Tembel yükleme</h2>
<p>Aslında eğer javascript dosyalarınızı senkron olarak yüklüyorsanız bu yönteme ihtiyacınız yok. Google kütüphanesini &lt;head&gt; içerisine dahil ederseniz React kodunuz yüklenmeden önce Haritalar kütüphanesi erişebilir durumda olacaktır. Ancak tüm kütüphaneleri senkron olarak yüklerseniz sayfanızın ilk açılışı biraz uzun sürebilir. Bu süre React gibi tek sayfa uygulamaları için pek de problem değildir aslında.</p>
<p>Senkron yüklemek:</p>
<pre><code class="language-html">&lt;head&gt;
  &lt;script src=&quot;https://maps.googleapis.com/maps/api/js?key=YOUR_API_KEY&quot; /&gt;
&lt;/head&gt;
</code></pre>
<p>daha sonra ise React bileşeninden kütüphaneyi çağırmanız yeterli:</p>
<pre><code class="language-js">class Map extends Component {
  componentDidMount() {
    const map = new window.google.maps.Map(document.getElementById('map'), {
      center: { lat: 41.0082, lng: 28.9784 },
      zoom: 8
    });
  }

  render() {
    return (
      &lt;div style={{ width: 500, height: 500 }} id=&quot;map&quot; /&gt;
    );
  }
}
</code></pre>
<p>Ancak eğer kütüphaneyi tembel olarak yüklemek isterseniz çalışma anında script'i kod içerisine gömmemiz gerekecek:</p>
<p>Şimdi, Map adında bir React bileşeni oluşturalım ve bu bileşenin görevi, eğer Google Maps yüklü değilse önce yüklemek; daha sonra da props değerlerine göre haritayı oluşturmak olsun. Eğer başka bir bileşen kütüphaneyi zaten yüklemiş ise tekrar yüklemesin.</p>
<pre><code class="language-js">import React, { Component } from 'react';
import { render } from 'react-dom';

class Harita extends Component {
  constructor(props) {
    super(props);
    this.onScriptLoad = this.onScriptLoad.bind(this)
  }

  onScriptLoad() {
    const map = new window.google.maps.Map(
      document.getElementById(this.props.id),
      this.props.options);
    this.props.onMapLoad(map)
  }

  componentDidMount() {
    if (!window.google) {
      var s = document.createElement('script');
      s.type = 'text/javascript';
      s.src = `https://maps.google.com/maps/api/js?key=YOUR_API_KEY`;
      var x = document.getElementsByTagName('script')[0];
      x.parentNode.insertBefore(s, x);
      // Below is important. 
      //We cannot access google.maps until it's finished loading
      s.addEventListener('load', e =&gt; {
        this.onScriptLoad()
      })
    } else {
      this.onScriptLoad()
    }
  }

  render() {
    return (
      &lt;div style={{ width: 500, height: 500 }} id={this.props.id} /&gt;
    );
  }
}

export default Harita
</code></pre>
<br>
Şimdi de bir üst bileşenden bu Harita bileşenini çağıralım:
<pre><code class="language-js">render() {
    return (
      &lt;Harita
        id=&quot;myMap&quot;
        options={{
          center: { lat: 41.0082, lng: 28.9784 },
          zoom: 8
        }}
        onMapLoad={map =&gt; {
          var marker = new window.google.maps.Marker({
            position: { lat: 41.0082, lng: 28.9784 },
            map: map,
            title: 'Merhaba İstanbul!'
          });
        }}
      /&gt;
    );
  }
</code></pre>
<p>Şimdi de bu ana dek neler yaptık açıklayalım:</p>
<p>Harita bileşeni bir <code>div</code> etiketi oluşturuyor. Bu etiketin ID'si üst bileşenden geliyor. React, Harita bileşenini oluşturduktan sonra öncelikle <code>window.google</code> objesinin ulaşılabilir olup olmadığını kontrol ediyor. Eğer ulaşılır durumda ise tekrardan yüklemeye çalışmıyor. Ancak kütüphane yüklenmemişse script etiketi oluşturup bu etiketi kod içerisine enjekte ediyor. Bu işlem senkron gerçekleşemez. Yani, bu koddan sonra gelen satırda <code>window.google.maps</code>'e erişmeye çalışırsanız hata alırsınız. Bu yüzden bir dinleyici yani <code>listener</code> eklememiz gerekiyor. Bu dinleyici script eklendikten sonra aktif hale gelecek. Ancak bu durumda google.maps API erişilebilir duruma gelecektir.</p>
<p>Google maps API erişilebilir durumda ancak üst bileşenin bundan haberi yok. Üst bileşeni haberdar etmek için props kullanacağız. onMapLoad'u bu sebeple tanımladık. Harita, onScriptLoad'ı, o da onMapLoad'u çağırıyor ve oluşturulan map nesnesini parametre olarak gönderiyor. onMapLoad çağırıldığında da artık haritaya her işi yaptırabiliriz. Burada örnek olarak Marker oluşturduk. Ancak aklınıza gelebilecek her harita nesnesi oluşturulabilir.</p>
<h2 id="2reactbileenleriniharitaiersineentegreetmek">2. React bileşenlerini harita içersine entegre etmek</h2>
<p>Google kütüphanesi InfoWindow ve Özel bileşen oluşturmaya izin veriyor ancak bu nesneler HTML metni olarak tanımlı. Yani her türlü HTML markup kullanabilirsiniz ancak oluşturacağınız nesneler React tarafından tanınmayacaktır. Örneğin bir InfoWindow oluşturdunuz. İçerisine bir düğme eklediniz bu düğmeye basıldığında bir Redux fonksiyonunu çalıştırmak istiyorsunuz. Bu pek mümkün gözükmüyor. Ancak çözümü basit. HTML markup ile oluşturulan nesneyi react-dom yardımıyla React bileşenine dönüştürebiliriz. Bu &lt;div id=&quot;root&quot; /&gt; etiketine yaptığımız dönüşümden farksız.</p>
<pre><code class="language-js">createInfoWindow(e, map) {
    const infoWindow = new window.google.maps.InfoWindow({
        content: '&lt;div id=&quot;infoWindow&quot; /&gt;',
        position: { lat: e.latLng.lat(), lng: e.latLng.lng() }
    })
    infoWindow.addListener('domready', e =&gt; {
      render(&lt;InfoWindow /&gt;, document.getElementById('infoWindow'))
    })
    infoWindow.open(map)
  }

  render() {
    return (
      &lt;Harita
        id=&quot;myMap&quot;
        options={{
          center: { lat: 41.0082, lng: 28.9784 },
          zoom: 8
        }}
        onMapLoad={map =&gt; {
          const marker = new window.google.maps.Marker({
            position: { lat: 41.0082, lng: 28.9784 },
            map: map,
            title: 'Merhaba Istanbul!'
          });
          marker.addListener('click', e =&gt; {
            this.createInfoWindow(e, map)
          })
        }}
      /&gt;
    );
  }
</code></pre>
<p>InfoWindow React bileşeni:</p>
<pre><code class="language-js">import React from 'react';
import { withStyles } from 'material-ui/styles';
import Card, { CardActions, CardContent, CardMedia } from 'material-ui/Card';
import Button from 'material-ui/Button';
import Typography from 'material-ui/Typography';

const styles = {
card: {
  maxWidth: 345,
},
media: {
  height: 0,
  paddingTop: '56.25%',
},
};

function InfoWindow(props) {
const { classes } = props;
return (
  &lt;div&gt;
    &lt;Card className={classes.card}&gt;
      &lt;CardMedia
        className={classes.media}
image=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Bosphorus.jpg/397px-Bosphorus.jpg&quot;
        title=&quot;Contemplative Reptile&quot;
      /&gt;
      &lt;CardContent&gt;
        &lt;Typography gutterBottom variant=&quot;headline&quot; component=&quot;h2&quot;&gt;
          Istanbul
        &lt;/Typography&gt;
        &lt;Typography component=&quot;p&quot;&gt;
          Istanbul is a major city in Turkey that straddles Europe and Asia across the Bosphorus Strait. Its Old City reflects cultural influences of the many empires that once ruled here.

        &lt;/Typography&gt;
      &lt;/CardContent&gt;
      &lt;CardActions&gt;
        &lt;Button size=&quot;small&quot; color=&quot;primary&quot;&gt;
          Share
        &lt;/Button&gt;
        &lt;Button size=&quot;small&quot; color=&quot;primary&quot;&gt;
          Learn More
        &lt;/Button&gt;
      &lt;/CardActions&gt;
    &lt;/Card&gt;
  &lt;/div&gt;
);
}


export default withStyles(styles)(InfoWindow);
</code></pre>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/en/content/images/2018/06/InfoWindow.png" alt="React içerisinde Google Maps Kullanımı"></p>
<p>Bu örneğin çalışabilir haline aşağıdan ulaşabilirsiniz.</p>
<p><a href="https://stackblitz.com/edit/react-rdevxo?file=InfoWindow.js">https://stackblitz.com/edit/react-rdevxo?file=InfoWindow.js</a></p>
<p>Sonuç olarak, harita içerisine gömmek istediğimiz her React bileşenini benzer şekilde oluşturup Google Maps'i Reactlaştırabiliriz :) NPM üzerinde bu işlemleri sizin için yapan kütüphaneler var. Projenize göre bu tip bir kütüphane kullanmak faydalı olabilir, ancak bu durumda Google API dökümantasyonunu direk olarak kullanamıyorsunuz ve kütüphaneye bağımlı hale geliyorsunuz. Zaten bu kütüphanelerin kaynak kodlarını alıp incelerseniz bu iki temel adımı kullandıklarını göreceksiniz.</p>
]]></content:encoded></item><item><title><![CDATA[ESP-12E programlama]]></title><description><![CDATA[ESP-12E, ilk ESP versiyonuna göre daha çok I/O portu bulundurduğundan büyük projeler için daha elverişli. Ancak programlanması ESP-01'e göre daha zahmetli.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/esp8266-12e-programlama/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb3d</guid><category><![CDATA[ESP8266]]></category><category><![CDATA[ESP-12E]]></category><category><![CDATA[FTDI]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sun, 03 Jun 2018 23:57:21 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/Title.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/Title.png" alt="ESP-12E programlama"><p>ESP8266-12E ya da kısaca ESP-12E, ESP-01'e göre daha giriş portu bulundurduğundan daha büyük projeler için daha elverişli. Ancak, ESP-12E breadboard dostu bir bileşen değil. Ayak aralıkları daha dar ve dolayısıyla bir adaptör olmadan kullanmak zor. ESP-01 de direk olarak breadboard üzerine konulamıyordu ancak ayak aralıkları standard olduğundan pinleri kablo yardımıyla bağlamak oldukça kolaydı. Ancak, ESP-01'ler uzun süreli kullanımlarda pek stabil değil. Neyse, FTDI yardımıyla ESP8266-12E'yi nasıl programlayacağımıza bir bakalım:</p>
<p>Kullanacağımız bileşenler:</p>
<ol>
<li>ESP8266 12-E<br>
<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/ESP8266-12-E.png" alt="ESP-12E programlama"></li>
<li>YP-05 FTDI<br>
<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/USB-TTL-FTD1232-Pinout.png" alt="ESP-12E programlama"></li>
<li>ESP ayakları için tabaka (kendiniz de benzer bir şey yapabilirsiniz)<br>
<img style="height: 400px" src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/ESP-Plate.jpg" alt="ESP-12E programlama"></li>
</ol>
<p>Tabaka, Aliexpress'ye tanesi 50-60 kuruş gibi bir fiyata satılıyor. Elinizin altında bir tane yoksa kendiniz de lehimleyerek oluşturabilirsiniz elbet.</p>
<p>ESP'ler 3.3 Volt ile çalışıyor. Bu yüzden harici kaynak kullanmakta fayda var. FTDI'ın VCC'sini kullanmıyoruz, sadece GND'yi tüm devrenin GND'sine bağlıyoruz. FTDI'ın RX ve TX'ini ESP'nin TX ve RX'ine çapraz olarak bağlıyoruz. ESP'nin CH_PD ayağını 5-10K direnç yardımıyla 3.3 Volt'a çekiyoruz. ESP'nin GPIO-0 ve GPIO-15 ayaklarını da gene 5-10K direnç yardımıyla toprağa bağladıktan sonra ESP-12E programlama moduna geçiyor.</p>
<table>
    <tr>
        <th>ESP-12E Pin</th>
        <th>Bağlantı</th>
    </tr>
    <tr>
        <td>CH_PD</td>
        <td>4.7 K direnç ile 3.3 Volt'a</td>
    </tr>
    <tr>
        <td>VCC</td>
        <td>3.3 Volt</td>
    </tr>
    <tr>
        <td>GND</td>
        <td>Gnd</td>
    </tr>
    <tr>
        <td>TX</td>
        <td>FTDI (RX)</td>
    </tr>
   <tr>
        <td>RX</td>
        <td>FTDI (TX)</td>
    </tr>
    <tr>
        <td>GPIO-0</td>
        <td>4.7 K direnç ile Gnd'ye</td>
    </tr>
    <tr>
        <td>GPIO-15</td>
        <td>Gnd'ye</td>
    </tr>
</table>
<table>
    <tr>
        <th>FTDI Pin</th>
        <th>Bağlantı</th>
    </tr>
    <tr>
        <td>RX</td>
        <td>ESP-12E (TX)</td>
    </tr>
    <tr>
        <td>TX</td>
        <td>ESP-12E (RX)</td>
    </tr>
    <tr>
        <td>GND</td>
        <td>Gnd</td>
    </tr>
</table>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/ESP12E_bb.png" alt="ESP-12E programlama"></p>
<p>Devremiz hazır.</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/Devre-1.jpg" alt="ESP-12E programlama"></p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/Devre-2.jpg" alt="ESP-12E programlama"></p>
<p>Şimdi ESP8266'yı programlayabiliriz. Arduino IDE'yi ESP-01'i programlarken kullandığımız ayarlarla kullanıyoruz. Eğer Arduino IDE ayarları yapılmamışsa:</p>
<p><code>Dosya&gt;Tercihler&gt;Ek Devre Kartları Yöneticisi URL'leri</code> kısmına aşağıdaki adresi ekleyelim</p>
<pre><code>http://arduino.esp8266.com/stable/package_esp8266com_index.json
</code></pre>
<p>Daha sonra <code>Araçlar&gt;Kart&gt;Kart Yöneticisi</code>nden ESP8266'yı bulup kuralım:</p>
<p><img src="http://cuneyt-aliustaoglu.s3.amazonaws.com/blog.tr/2017-09-02%20ESP8266WebServer/KartYoneticisi.png" alt="ESP-12E programlama"></p>
<p>Şimdi ESP-12E programlanmaya hem donanımsal hem de yazılımsal olarak hazır durumda. Bu yazıda yalnızca ESP-12'nin nasıl programlandığını göstermek istedim. O yüzden karmaşık bir program yazmayacağız. Klasik LED yak-söndür uygulamasını yükleyelim. Burada LED_BUILTIN, ESP üzerinde bulunan LED olduğundan harici bir LED ve direnç bağlamamıza gerek yok.</p>
<pre><code class="language-clike">void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}
</code></pre>
<p><strong>ÖNEMLİ</strong> Programlama bittikten sonra ESP'yi çalıştırma moduna almanız gerekiyor. Bu da GPIO-0 ayağını VCC'ye GPIO-15 bacağını da toprağa bağlayarak gerçekleştiriliyor.</p>
<p>Bu yöntemleri kullanarak kendime de oldukça amatör bir programlama kartı oluşturdum. Böylece her seferinde breadboard, kablo ve dirençlerle uğraşmak durumunda kalmayacağım. ESP-12 ile gerçek uygulamalar yapmaya devam edeceğim.</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/06/Devre-3.jpg" alt="ESP-12E programlama"></p>
]]></content:encoded></item><item><title><![CDATA[Digispark ATtiny-85 ile Arduino projelerini küçültmek]]></title><description><![CDATA[Digistump'ın ufacık ATtiny modülü ile Arduino'nun yaptığı pek çok işi daha az enerji ile küçük bir devrede yapmak mümkün. Hatta Nano bile ATtiny yanında tam donanımlı bilgisayar gibi duruyor. ATtiny'nin kullanımı Arduino'dan çok farksız değil ancak programlanması biraz ayar gerektiriyor.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/digispark-attiny-85-ile-arduino-projelerini-kucultmek/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb39</guid><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sat, 14 Apr 2018 00:53:44 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/ATtiny-85-Header.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/ATtiny-85-Header.png" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"><p>Digistump'ın ufacık ATtiny modülü ile Arduino'nun yaptığı pek çok işi daha az enerji ile küçük bir devrede yapmak mümkün. Hatta Nano bile ATtiny yanında tam donanımlı bilgisayar gibi duruyor. ATtiny'nin kullanımı Arduino'dan çok farksız değil ancak programlanması biraz ayar gerektiriyor. Şimdi bu ayarları inceleyelim.</p>
<p>Öncelikle Windows için aşağıdaki sürücüyü yüklemek gerekiyor:<br>
<a href="https://github.com/digistump/DigistumpArduino/releases/download/1.6.7/Digistump.Drivers.zip">https://github.com/digistump/DigistumpArduino/releases/download/1.6.7/Digistump.Drivers.zip</a></p>
<p>Daha sonra DigiSpark kartını Arduino'ya tanıtmamız gerekiyor. Ayarlardan <code>Ek Devre Kartları Yöneticisi URL'leri</code> kısmından aşağıdaki adresi eklemek gerekiyor:</p>
<p><a href="http://digistump.com/package_digistump_index.json">http://digistump.com/package_digistump_index.json</a></p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/ek-devre-kartlari-yoneticisi.png" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"></p>
<p>Bu kart daha sonra Kart Yöneticisinde erişebilir olacak. <code>Araçlar&gt;Kart&gt;Kart Yöneticisi</code> menüsünden <code>Digistump</code> araması yaparak ilgili kartı bulup yükleyelim.</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/kart-yoneticisi.png" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"></p>
<p>Daha sonra <code>Araçlar&gt;Kart</code> menüsünden <code>Digistump AVR Boards</code> bölümünün aktif olduğunu göreceksiniz. Buradan <code>Digispark (Default 16.5 Mhz)</code> seçimini yapalım.</p>
<p>Artık ilk programımızı yüklemeye hazırız. Öncelikle test etmek için çok basit bir uygulama hazırlayalım. Klasik yanıp sönen LED uygulaması:</p>
<pre><code class="language-clike">void setup() {                
  pinMode(0, OUTPUT);
  pinMode(1, OUTPUT);
}

void loop() {
  digitalWrite(0, HIGH);
  digitalWrite(1, LOW);
  delay(1000);
  digitalWrite(0, LOW);
  digitalWrite(1, HIGH); 
  delay(1000);
}
</code></pre>
<p><em>!!DİKKAT!!</em>: Bu kısım önemli. Arduino'dan farklı olarak ATtiny-85'i USB'ye (henüz) bağlamıyoruz. Eğer USB girişini takar ve Yükle düğmesine basarsanız yükleme işlemi başarısız olacaktır. Önce Yükle düğmesine basalım ve daha sonra Arduino konsolunda aşağıdaki uyarıyı göreceksiniz.</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/plug-the-device.png" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"></p>
<p>Bu uyarıdan sonra Arduino, sizden Digistump ATtiny-85'i bağlamanızı bekleyecek. Bağladığınız anda programlama işlemi başlayacak ve her şey başarılı olursa aşağıdaki gibi bir mesaj alacaksınız.</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/yukleme-basarili.png" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"></p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/attiny85-led-blink.gif" alt="Digispark ATtiny-85 ile Arduino projelerini küçültmek"></p>
<p>Şimdi biraz daha yararlı bir uygulama yapalım. 0.96 OLED ekranında sensörden gelen analog veriyi işleyelim.</p>
]]></content:encoded></item><item><title><![CDATA[Arduino Nano ve u8glib ile Nokia 5110 ekranının kullanımı]]></title><description><![CDATA[Nokia 5110 ekranı; Arduino, ESP vs. ile yapacağınız hemen her uygulamada kullanabileceğiniz, kullanımı kolay ve oldukça da ucuz bir donanım. Nokia 5110 ekranı; Arduino, ESP vs. ile yapacağınız hemen her uygulamada kullanabileceğiniz, kullanımı kolay ve oldukça da ucuz bir donanım. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/arduino-nano-ve-u8glib-ile-nokia-5110-ekraninin-kullanimi/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb38</guid><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sun, 08 Apr 2018 06:48:58 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/Nano5110MerhabaDunya-1.jpeg" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/Nano5110MerhabaDunya-1.jpeg" alt="Arduino Nano ve u8glib ile Nokia 5110 ekranının kullanımı"><p>Nokia 5110 ekranı; Arduino, ESP vs. ile yapacağınız hemen her uygulamada kullanabileceğiniz, kullanımı kolay ve oldukça da ucuz bir donanım. Internet'te bolca örnek var ancak genelde başka bileşenler de kullanıldığı için örnekler biraz karmaşıklaşıyor. Bana en başta lazım olan en basit &quot;Merhaba Dünya&quot; uygulaması.</p>
<p>Bileşenler:</p>
<ol>
<li>Arduino Nano (Uno da kullanılabilir)</li>
<li>Nokia 5110 LCD</li>
<li>u8glib kütüphanesi: <a href="https://bintray.com/olikraus/u8glib/Arduino">https://bintray.com/olikraus/u8glib/Arduino</a></li>
</ol>
<p>u8glib kütüphanesini ilgili linkten indirdikten sonra Sketch&gt;Include Library&gt;Add .zip Library menüsünden ekleyebilirsiniz.</p>
<p>Ayrıca u8glib ile ile Page Loop kullanımını daha önce anlatmıştım:<br>
<a href="http://cuneyt.aliustaoglu.biz/tr/u8glib-kutuphanesi-ve-page-loop-ile-arduino-uno-i2c-oled-kullanimi/">http://cuneyt.aliustaoglu.biz/tr/u8glib-kutuphanesi-ve-page-loop-ile-arduino-uno-i2c-oled-kullanimi/</a></p>
<p>Ancak bu uygulamamızda sadece Nokia 5110 ekranının kullanımına yoğunlaşacağız.</p>
<figure>
<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/c858a4862a76088390111f411c508c88.png" alt="Arduino Nano ve u8glib ile Nokia 5110 ekranının kullanımı"><figcaption>Nokia 5110 ayak bağlantıları</figcaption>
</figure>
<br>
<table>
    <tr><th>Nokia 5110</th><th>Renk</th><th>Arduino Nano</th></tr>
    <tr><td>RST</td><td>Sarı</td><td>D7</td></tr>
    <tr><td>CE</td><td>Yeşil</td><td>D8</td></tr>
    <tr><td>DC</td><td>Mavi</td><td>D9</td></tr>
    <tr><td>Din</td><td>Beyaz</td><td>D10</td></tr>
    <tr><td>Clk</td><td>Mor</td><td>D11</td></tr>
    <tr><td>VCC</td><td>Kırmızı</td><td>3V3</td></tr>
    <tr><td>BL</td><td>Kahverengi</td><td>3V3</td></tr>
    <tr><td>Gnd</td><td>Siyah</td><td>GND</td></tr>
</table>
<figure>
    <img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/NanoNokiaSimpleExample_bb.png" \="" alt="Arduino Nano ve u8glib ile Nokia 5110 ekranının kullanımı">
    <figcaption>Arduino Nano - Nokia 5110 bağlantısı</figcaption>
</figure>
<br>
<p>Ve aşağıda olabilecek en sade ve basit haliyle Merhaba Dünya. Daha sonra biraz daha gelişmiş uygulamalar yapmak istiyorum ancak en basit devre şemasının ve kodunun elimizin altında bulunmasında fayda var.</p>
<pre><code class="language-clike">#include &quot;U8glib.h&quot;

U8GLIB_PCD8544 u8g(11, 10, 8, 9, 7); // Clk, Din, DC, CE, RST

void draw()
{
    u8g.setFont(u8g_font_unifont);
    u8g.drawStr(0, 20, &quot;Merhaba &quot;);
    u8g.drawStr(12, 36, &quot;Dunya&quot;);
}

void setup()
{
    u8g.setColorIndex(1);
    u8g.setRot180(); // Ekranı 180 derece çevir
}

void loop()
{
    u8g.firstPage();

    do
    {
        draw();
    }
    while(u8g.nextPage());

    delay(1000);
}
</code></pre>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/04/ArduinoNanoMerhabaDunya-2.jpeg" alt="Arduino Nano ve u8glib ile Nokia 5110 ekranının kullanımı"></p>
<p>Şimdi biraz daha karmaşık projelere hazırız. Sensörden okuttuğumuz değerleri ekrana yansıtacak havalı projeler...</p>
]]></content:encoded></item><item><title><![CDATA[React Native Kurulumu]]></title><description><![CDATA[React Native kurulumu aslında çok problemli değil ancak aşağıdaki basit notların elimizin altında bulunmasında fayda var.
]]></description><link>http://cuneyt.aliustaoglu.biz/tr/react-native-kurulumu/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb35</guid><category><![CDATA[React.Native]]></category><category><![CDATA[React]]></category><category><![CDATA[Genymotion]]></category><category><![CDATA[create-react-native-app]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Fri, 30 Mar 2018 10:44:20 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/ReactNative-2.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/ReactNative-2.png" alt="React Native Kurulumu"><p>React Native sayesinde React kullanan herkes aslında bir mobil yazılımcıya dönüşüyor. Aslında kurulumu çok problemli değil ancak aşağıdaki notların elimizin altında bulunmasında fayda var.</p>
<h3 id="macosiinkurulum">MacOS için kurulum</h3>
<p>Mac kullanıcılarında brew ve cask kurulumlarının yapıldığını varsayıyorum. Eğer yapmadıysanız:</p>
<pre><code>/usr/bin/ruby -e &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)&quot;
brew tap caskroom/cask
</code></pre>
<p>Daha sonra ise node, android-sdk, android-platform-tools, java8 ve watchman kurulumlarını brew ve cask yardımıyla gerçekleştiriyoruz.</p>
<pre><code>brew tap caskroom/cask
brew install node
brew cask install android-sdk
brew cask install android-platform-tools
brew cask install caskroom/versions/java8
brew install watchman
</code></pre>
<p>Elimizin altında Android olsa da emulatörden çalışmak daha hızlı ve pratik bu yüzden bir emülatöre ihtiyacımız olacak. Genymotion kişisel kullanımlar için ücretsiz. Ücretsiz bir hesap yaratıp aşağıdan Genymotion'u indirelim.</p>
<p><a href="https://www.genymotion.com/fun-zone/">https://www.genymotion.com/fun-zone/</a></p>
<p>Eğer Virtual Box ile birlikte gelmiyorsa Virtual Box'ı da kurmak lazım:<br>
<a href="https://www.virtualbox.org/wiki/Downloads">https://www.virtualbox.org/wiki/Downloads</a></p>
<p>Genymotion açılışında 'Personal Use' seçip kullanıcı adımızla giriş yaptıktan sonra bir sanal telefon oluşturmamız gerekecek. Android 4, 5, 6, 7 vs. ve favori telefonunuzu seçip emulatörü başlatın.</p>
<p>React uygulamasında create-react-app kullanmıştık. Benzer şekilde yine Facebook'un resmi installer'ı olan create-react-native-app uygulamasını da global olarak yükleyelim:</p>
<pre><code>npm install -g create-react-native-app
</code></pre>
<p>Daha sonra boş bir uygulama yaratalım ve bu uygulamayı çalıştıralım:</p>
<pre><code>create-react-native-app ilkUygulama
cd ilkUygulama
npm install
npm start
</code></pre>
<p>Genymotion'ın arka planda çalıştığından emin olduktan sonra, çıkan menüde android için <code>a</code>'ya basıyoruz ve ilk uygulamamız hazır.</p>
  <img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/Anroid-emulator-react-native-ilkUygulama.png" alt="React Native Kurulumu" height="800">
<p>Elbette emülatörü sallamak pek gerçekçi değil. Sallama olayını ise command+m tuş kombinasyonu ile gerçekleştirebilirsiniz.</p>
<h3 id="windowsiinkurulum">Windows için kurulum</h3>
<p>Windows üzerinde node ve java kurulumlarını sitesinden indirdiğiniz kurulum dosyaları ile gerçekleştirin. Windows üzerinde sdk ve platform-tools kurulumu bende oldukça sorunlu oldu. Eğer sorun yaşarsanız direk Android Studio'yu da kurabilirsiniz.</p>
<p>Bunun dışında yine Genymotion'a ihtiyaç duyacağız ve create-react-native-app ile ilgili kısımlar MacOS ile aynı şekilde olacaktır:</p>
<pre><code>npm install -g create-react-native-app

create-react-native-app ilkUygulama
cd ilkUygulama
npm install
npm start
</code></pre>
]]></content:encoded></item><item><title><![CDATA[zsh ve Prezto ile renkli terminal]]></title><description><![CDATA[bash terminal, varsayılan özellikleri ile kullanılırken pek de kullanışlı değildir. zsh kullanırsanız otomatik tamamlama, renklendirme gibi pek yok yararlı özellikten yararlanabilirsiniz. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/zsh-ve-prezto-ile-renkli-terminal/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb36</guid><category><![CDATA[Unix]]></category><category><![CDATA[zsh]]></category><category><![CDATA[prezto]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Thu, 29 Mar 2018 22:55:15 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/Prezto-Terminal.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/Prezto-Terminal.png" alt="zsh ve Prezto ile renkli terminal"><p>Mac ve Linux işletim sistemlerindeki bash terminal, varsayılan özellikleri ile kullanılırken pek de kullanışlı değildir. bash yerine <code>zsh</code> kullanırsanız otomatik tamamlama, renklendirme gibi pek yok yararlı özellikten yararlanabilirsiniz. Ayrıca <code>git</code> ile çalışırken içinde bulunduğunuz branch ile ilgili bilgileri alır ve otomatik tamamlamanın tüm nimetlerinden yararlanırsınız.</p>
<blockquote>
<p>git checkout cok-uzun-branch-adi</p>
</blockquote>
<p>yerine</p>
<blockquote>
<p>git che [tab] cok [tab]</p>
</blockquote>
<p>gibi bir kullanımla çalışırken verimliliğinizi artırırsınız. Prezto aslında bir ohmyzsh forku ancak bence daha sade ve kullanışlı. Şimdi nasıl kurulur ona bakalım.</p>
<p>Oncelikle ZSH kurulur</p>
<pre><code>brew install zsh zsh-completions
</code></pre>
<p>(ya da Linux için <code>apt-get install zsh</code>)</p>
<p>Daha sonra Prezto'yu kopyalayalım:</p>
<pre><code>git clone --recursive https://github.com/sorin-ionescu/prezto.git &quot;${ZDOTDIR:-$HOME}/.zprezto&quot;
</code></pre>
<p>şimdi bash konsoluna <code>which zsh</code> yazıp çıkan sonucu kopyalayalım: <code>/usr/local/bin/zsh</code> ve default login shell yerine zsh kullanalım:</p>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/Screen-Shot-2018-03-30-at-10.41.04.png" alt="zsh ve Prezto ile renkli terminal"></p>
<p>Terminali açıp kapattığınızda</p>
<pre><code>This is the Z Shell configuration function for new users,
zsh-newuser-install.
You are seeing this message because you have no zsh startup files
(the files .zshenv, .zprofile, .zshrc, .zlogin in the directory
~).  This function can help you with a few settings that should
make your use of the shell easier.

You can:

(q)  Quit and do nothing.  The function will be run again next time.

(0)  Exit, creating the file ~/.zshrc containing just a comment.
     That will prevent this function being run again.

(1)  Continue to the main menu.
</code></pre>
<p>şeklinde bir uyarı görebilirsiniz. Henüz .zshrc dosyasını oluşturmadığımız için bu uyarıyı aldık. (q) ile devam edebilirsiniz.</p>
<p>Daha sonra ise sırasıyla</p>
<pre><code>setopt EXTENDED_GLOB
</code></pre>
<p>ve</p>
<pre><code>for rcfile in &quot;${ZDOTDIR:-$HOME}&quot;/.zprezto/runcoms/^README.md(.N); do
ln -s &quot;$rcfile&quot; &quot;${ZDOTDIR:-$HOME}/.${rcfile:t}&quot;
done
</code></pre>
<p>komutlarını terminalde çalıştırarak .zshrc dosyasını oluşturalım.</p>
<p>Daha sonra da zpreztorc içeriğini görüntüleyelim:</p>
<pre><code>nano ~/.zpreztorc
</code></pre>
<p>ve içeriği tamamen silip aşağıdaki ile değiştirelim:</p>
<pre><code>zstyle ':prezto:load' pmodule \
  'environment' \
  'terminal' \
  'editor' \
  'history' \
  'directory' \
  'spectrum' \
  'utility' \
  'completion' \
  'git' \
  'syntax-highlighting' \
  'history-substring-search' \
  'prompt'

zstyle ':prezto:module:prompt' theme 'steeef'
</code></pre>
<p><img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/prezto-steef.png" alt="zsh ve Prezto ile renkli terminal"></p>
<p>Ben en çok steeef temasını seviyorum ancak seçim size kalmış. steeef yerine prezto kurulumu ile gelen 21 temadan herhangi birini kullanabilir ya da kendi temanızı yaratabilirsiniz.</p>
<p>Bu 21 temanın listesi aşağıdaki gibidir. Tema adı yerine herhani birini seçin:</p>
<p>zstyle ':prezto:module:prompt' theme 'THEME_NAME'</p>
<pre><code>minimal
nicoulaj
peepcode
sorin
step
adam1
adam2
bart
bigfade
clint
elite
elite2
fade
fire 
off
oliver
pws
redhat
suse
walters
zefram
</code></pre>
]]></content:encoded></item><item><title><![CDATA[AWS Cognito ve Lambda ile kullanıcı yönetimi]]></title><description><![CDATA[İster web, ister mobil, isterse de masaüstü yazılımı olsun; kullanıcının kimliğini doğrulama işlemi hemen her uygulamada gerekli bir altyapıdır. Milyonlarca kullanıcı, kendi uygulamaları için aynı şeyi farklı şekillerde defalarca yeni baştan yazdılar. Bu sebeple bazı standartlar oluştu. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/aws-cognito-ve-lambda-ile-kullanici-yonetimi/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb33</guid><category><![CDATA[Cognito]]></category><category><![CDATA[AWS]]></category><category><![CDATA[Lambda]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sun, 11 Mar 2018 07:10:01 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/cognito-3.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/cognito-3.png" alt="AWS Cognito ve Lambda ile kullanıcı yönetimi"><p>İster web, ister mobil, isterse de masaüstü yazılımı olsun; kullanıcının kimliğini doğrulama işlemi hemen her uygulamada gerekli bir altyapıdır. Milyonlarca kullanıcı, kendi uygulamaları için aynı şeyi farklı şekillerde defalarca yeni baştan yazdılar. Bu sebeple bazı standartlar oluştu. Auth0 veya Cognito gibi yapılar bu standartları yönetmek amacıyla oluşturulmuş servislerdir. Daha önce çalıştığım bir şirkette Auth0 kullanmıştım, fakat kendi kişisel projelerimde halihazırda AWS kullandığım için başka bir üçüncü parti modülünü kullanmak istemedim. Bu sebeple Amazon'un Cognito servisini tercih ettim.</p>
<p>Auth0 gerçekten çok güçlü bir şirket ve tamamen kullanıcı yönetimi üzerinde yoğunlaşıyorlar. JWT standardını yaratanlar da Auth0 mühendisleri. Bu sebeple AWS Cognito, fonksiyonellik açısından Auth0'nun yanına bile yaklaşamaz. Ancak, küçük ve orta boyutlu projelerde Auth0'nun pek çok özelliği size lüks gelecektir. Hatta bazı büyük uygulamalarda bile AWS Cognito yeterli olacaktır.</p>
<p>Auth0 için ilk 7000 aylık aktif kullanıcı için bedava iken, AWS Cognito'da bu sayı 50,000'dir. Neyse konumuz AWS Cognito. AWS Cognito ile NodeJS kullanarak kullanıcı oluşturma, email adresini doğrulama ve giriş yapan kullanıcının parolasının nasıl kontrol edileceğini açıklayalım.</p>
<p>Sunucu kullanmadığım için herşeyi AWS Lambda üzerinde gerçekleştiriyorum ancak aynı kodlar elbette(ufak bir modifikasyonla) sunucuda çalışan NodeJS ile de çalışacaktır.</p>
<h3 id="awscognito">AWS Cognito</h3>
<p>Öncelikle AWS Cognito yapılandırmamızı hazırlayalım. Cognito anasayfasında 2 adet seçenek göreceksiniz.</p>
<ul>
<li>Manage User Pools</li>
<li>Manage Federated Identities</li>
</ul>
<p>Federated Identities kullanıcıların Facebook veya Twitter hesaplarıyla giriş yapıp AWS kaynaklarına(S3, EC2 vs.) erişmelerini sağlayan bir modül. Biz web sayfamız için kullanıcı kontrolü yapmak istiyoruz. Bu yüzden kullanacağımız modül &quot;Manage User Pools&quot;.</p>
<p>&quot;Create a User Pool&quot; diyerek yeni bir kullanıcı havuzu oluşturalım. Havuz adını belirttikten sonra &quot;Step Through Settings&quot; ile sihirbazı kullanarak havumuzu adım adım oluşturabiliriz. Aşağıdaki alanlar OAuth standard alanları. Bu alanları zorunlu ya da seçimlik alan olarak belirtebilirsiniz. Bu alanlar dışında eklemek istediğimiz alanlar var ise &quot;Custom&quot; olarak eklenebilir.</p>
<h3 id="oauthstandardzellikleri">OAuth standard özellikleri</h3>
<ul>
<li>address</li>
<li>nickname</li>
<li>birthdate</li>
<li>phone number</li>
<li>email</li>
<li>picture</li>
<li>family name</li>
<li>preferred username</li>
<li>gender</li>
<li>profile</li>
<li>given name</li>
<li>zoneinfo</li>
<li>locale</li>
<li>updated at</li>
<li>middle name</li>
<li>website</li>
<li>name</li>
</ul>
<p>Sonraki adımda kullanıcıların email adresini doğrulamak isteyip istemediğinizi belirtiyorsunuz. Eğer istiyorsanız e-mail mesajının içeriğini de değiştirebiliyorsunuz. Daha sonra &quot;App Clients&quot; kısmında bir ID oluşturmamız gerekiyor. Bu ID önemli. Çünkü daha sonra programımıza hangi havuza bağlanmak istediğimizi bu ID'yi kullanarak belirteceğiz. &quot;App Client Secret&quot; kısmını ise boş bırakıyoruz. Cognito SDK bunu desteklemiyor. Eğer Client Secret yaratırsak Javascript SDK ile kullanamıyoruz. (<a href="https://github.com/aws/amazon-cognito-identity-js/issues/2">https://github.com/aws/amazon-cognito-identity-js/issues/2</a>). Bu sanırım güvenlik için özel olarak bu şekilde tasarlanmış. Çünkü Javascript SDK istemci üzerinde çalışabilir. Bu da demek oluyor ki şifreyi herkesin görebileceği şekilde açık etmemiz gerekiyor. Lambda ise sunucu üzerinde çalışıyor elbet, ancak JS SDK kullandığı için bu özelliği kullanamıyoruz. Bu sebeple Lambda'yı yaratırken AWS Cognito kaynaklarına erişebilecek şekilde yaratmamız gerekiyor.</p>
<p>Triggers ya da Analytics gerekli değil. Eğer kullanıcı login olmadan önce, ya da kullanıcı yaratıldıktan sonra vs. gibi durumlar için belli bir kod parçası çalıştırmak istiyorsanız ilgili yerleri kullanabilirsiniz ancak ben gerek duymadım.</p>
<p>Kullanıcı havuzumuzu yarattıktan sonra kodlama işlemine geçebiliriz:</p>
<p>AWS Cognito nedenini bilmediğim bir şekilde Lambda için &quot;aws-sdk&quot; içerisine dahil edilmemiş bu sebeple <a href="https://github.com/aws/amazon-cognito-identity-js/blob/master/dist/amazon-cognito-identity.min.js"><code>amazon-cognito-identity.min.js</code></a> dosyasını indirip lambda klasörüne eklememiz lazım.</p>
<h3 id="kullancoluturma">Kullanıcı oluşturma</h3>
<pre><code class="language-javascript">'use strict';

exports.handler = function(event, context, callback) {
  // Burası önemli. Aşağıdaki dosyayı yukarıdaki adresten indirdim
  // ve bu dosya ile aynı klasöre kopyaladım
  const AWSCognito = require('./amazon-cognito-identity.min');

  const payload = JSON.parse(event.body);

  const poolData = {
    UserPoolId: 'us-east-1_*******',
    ClientId: '70do*************ak'
  };
  const userPool = new AWSCognito.CognitoUserPool(poolData);

  let attributeList = [];
  const emailAttribute = {
    Name: 'email',
    Value: payload.email
  };
  const websiteAttribute = {
    Name: 'website',
    Value: payload.website
  };
  const memleketAttribute = {
    Name: 'custom:memleket',
    Value: payload.memleket
  };

  attributeList.push(new AWSCognito.CognitoUserAttribute(emailAttribute));
  attributeList.push(new AWSCognito.CognitoUserAttribute(websiteAttribute));
  attributeList.push(new AWSCognito.CognitoUserAttribute(memleketAttribute));

  userPool.signUp(payload.username, payload.password, attributeList, null, function(err, result) {
    if (err) {
      const errorResponse = httpResponse.getResponse(400, { err });
      callback(null, errorResponse);
    } else {
      const signUpDetails = {
        userConfirmed: result.userConfirmed,
        userSub: result.userSub,
        userName: result.user.username
      };
      const successResponse = getResponse(200, { signUpDetails });
      callback(null, successResponse);
    }
  });
};

const getResponse = (statusCode, body) =&gt; {
  const response = {
    statusCode: statusCode,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true
    },
    body: JSON.stringify(body)
  };
  return response;
};
</code></pre>
<p>Yukarıda API Gateway kullanarak Lambda'ya POST isteği gönderdik. Bu POST isteğinin içeriğini <code>const payload = JSON.parse(event.body)</code> ile okuduk. POST içeriğinde ise username, password ikilisinin dışında OAuth standard özellikleri (claims) de bulunabilir. Yukarıdaki örnekte &quot;email&quot; ve&quot;website&quot; özellikleri ile bir de custom &quot;memleket&quot; özelliğini gönderdiğimizi de varsaydık. Daha çok standard ve custom claim eklenebilir. Ancak kodu basit tutmak amacıyla bu iki özelliği ekledim. Bu örnek için payload'ım aşağıdaki gibi:</p>
<pre><code class="language-json">{
   &quot;email&quot;: &quot;email@example.com&quot;,
   &quot;website&quot;: &quot;www.example.com&quot;,
   &quot;memleket&quot;: &quot;Giresun&quot;
}
</code></pre>
<p>Herhangi bir problem olmadığı taktirde kullanıcı Cognito üzerine kaydediliyor ve eğer email onaylanması istendiyse onay emaili gönderiliyor.</p>
<h3 id="kullanconay">Kullanıcı Onayı</h3>
<p>Kullanıcı onayını iki şekilde gerçekleştirebilirsiniz. Eğer</p>
<p><code>Message Customizations &gt; Verification type</code></p>
<p>üzerinden &quot;Link&quot; seçeneğini seçerseniz, AWS bu işi kendisi hallediyor. Ancak kendi kullanıcı deneyiminiz sebebiyle &quot;Code&quot; seçeneğini seçerseniz bu işi kendiniz halletmelisiniz. Bu da demek oluyor ki yeni bir gateway endpoint (ya da mevcut endpoint'e yeni bir parametre) ve yeni bir fonksiyon.</p>
<p>Benzer şekilde 'aws-cognito-identitiy' kütüphanesini kullanıyorum</p>
<pre><code class="language-javascript">/**
 * Enable user status
 * Conginot user status is UNCONFIRMED initially
 */

'use strict';

exports.handler = function(event, context, callback) {
  const AWSCognito = require('./amazon-cognito-identity.min');

  const payload = JSON.parse(event.body);
  const confirmationCode = payload.code;

  const poolData = {
    UserPoolId: 'us-east-1_*********',
    ClientId: '70*******************ak'
  };
  const userPool = new AWSCognito.CognitoUserPool(poolData);
  const userData = {
    Username: payload.username,
    Pool: userPool
  };
  const cognitoUser = new AWSCognito.CognitoUser(userData);
  cognitoUser.confirmRegistration(confirmationCode, true, (err, result) =&gt; {
    if (err) {
      const errorResponse = getResponse(400, err);
      callback(null, errorResponse);
      return;
    }
    const successResponse = getResponse(200, result);
    callback(null, successResponse);
  });
};

const getResponse = (statusCode, body) =&gt; {
  const response = {
    statusCode: statusCode,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true
    },
    body: JSON.stringify(body)
  };
  return response;
};
</code></pre>
<p>Payload'ım ise aşağıdaki gibi</p>
<pre><code class="language-json">{
  &quot;username&quot;: &quot;cuneyt&quot;,
  &quot;code&quot;: &quot;ABCDEFGH&quot;
}
</code></pre>
<h3 id="kullancgirii">Kullanıcı girişi</h3>
<p>Kullanıcı girişi kontrolünü ise aşağıdaki gibi yapıyoruz. Elbette normalde kullanıcı girişi yaptıktan sonra kullanıcının onay yaptığını sunucuda Session(oturum) üzerinde tutmamız gerekiyor. Ancak AWS üzerinde tüm istekler tek oturumluk olduğu için bir sonraki istekte kullanıcının giriş yapıp yapmadığını bilemeyeceğiz. Bu nedenle JWT token oluşturmamız gerekiyor fakat bu yazıda sadece Cognito'nun nasıl çalıştığını anlatmak istedim. O yüzden kodumu basit tutuyorum ve sadece kullanıcının onayını yapıyoruz.</p>
<pre><code class="language-javascript">'use strict';

exports.handler = function(event, context, callback) {
  const AWSCognito = require('./amazon-cognito-identity.min');

  const body = JSON.parse(event.body);
  const payload = body.payload;
  const authenticationData = {
    Username: payload.username,
    Password: payload.password
  };
  const authenticationDetails = new AWSCognito.AuthenticationDetails(authenticationData);
  const poolData = {
    UserPoolId: 'us-east-1_*********',
    ClientId: '70*******************ak'
  };
  const userPool = new AWSCognito.CognitoUserPool(poolData);
  const userData = {
    Username: payload.username,
    Pool: userPool
  };
  const cognitoUser = new AWSCognito.CognitoUser(userData);
  cognitoUser.authenticateUser(authenticationDetails, {
    onSuccess: function(result) {
      const token = { login: true }
      const successData = getResponse(200, mySurfToken);
      callback(null, successData);
    },
    onFailure: function(err) {
      const failData = getResponse(400, err);
      callback(null, failData);
    }
  });
};

const getResponse = (statusCode, body) =&gt; {
  const response = {
    statusCode: statusCode,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Credentials': true
    },
    body: JSON.stringify(body)
  };
  return response;
};
</code></pre>
<p>Burada payload'ımız ise:</p>
<pre><code>{
  &quot;username&quot;: &quot;cuneyt&quot;,
  &quot;password&quot;: &quot;123456&quot;
}
</code></pre>
<p>Yukarıdaki 3 özelliğin hemen her online uygulamada bulunması gerekiyor. AWS Cognito bize gerekli minimum fonksiyonelliği sağlıyor. Auth0 gibi uygulamalar çok daha kapsamlı ancak eğer halihazırda AWS kullandığınız bir uygulama var ise Cognito ile çok ucuza hatta büyük ihtimalle (50,000'i aşmayan aktif kullanıcı sayısına sahipseniz) bedavaya bu özelliklere kavuşabiliyorsunuz.</p>
]]></content:encoded></item><item><title><![CDATA[Redux-Thunk ile asenkron işlemler ve middleware kullanımı]]></title><description><![CDATA[Eğer Redux'a giriş yaptıysanız redux-thunk'ı duymuşsunuzdur. Thunk; saf olmayan fonksiyonlarımızı, saf Redux actionlarımızla kaynaştıran bir middleware'dir.Redux reducer'larımızın her daim saf olması, uygulamamızın sağlıklı işlemesi açısından çok önemlidir. Peki nedir bu "saf" fonksiyonlar ve bu saflık neden önemlidir?]]></description><link>http://cuneyt.aliustaoglu.biz/tr/redux-thunk-ile-asenkron-islemler/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb30</guid><category><![CDATA[Redux]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Fri, 02 Mar 2018 21:34:34 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/redux-5.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2018/03/redux-5.png" alt="Redux-Thunk ile asenkron işlemler ve middleware kullanımı"><p>Eğer Redux'a giriş yaptıysanız redux-thunk'ı duymuşsunuzdur. Thunk; saf olmayan fonksiyonlarımızı, saf Redux actionlarımızla kaynaştıran bir middleware'dir. Redux reducer'larımızın her daim saf olması, uygulamamızın sağlıklı işlemesi açısından çok önemlidir. Peki nedir bu &quot;saf&quot; fonksiyonlar ve bu saflık neden önemlidir?</p>
<p>Kısaca saf fonksiyon, aynı girdilere her zaman aynı çıktıyı üreten fonksiyonlara denir.</p>
<pre><code class="language-javascript">function topla(a, b) {
    return a+b;
}
</code></pre>
<p>Örneğin topla fonksiyonu bir saf fonksiyondur 2+3 zamandan, mekandan ve veritabanındaki herhangi bir veriden bağımsız olarak 5'tir.</p>
<pre><code class="language-javascript">function rastgeleTopla(a){
    return Math.random() + a;
}
</code></pre>
<p>Fakat yukarıdaki bu fonksiyon, her çağırdığımızda farklı sonuçlar üretebileceği için saf değildir. Benzer şekilde tarihe bağlı fonksiyonlar, veritabanından aldığı veriye göre sonuç üreten fonksiyonlar da saf değildir. Ancak hesap makinası dışında bir uygulama geliştiriyor isek elbette saf olmayan fonksiyonlarımız olacak.</p>
<p>Aslında asenkron fonksiyonlarımızı yazmak için herhangi bir middleware yapısına ihtiyacımız yok. Ancak Redux yapısını 'saf' tutabilmek için asenkron fonksiyonları veya genel olarak yan etkiye sahip fonksiyonları redux-thunk (veya saga) gibi middleware içerisinde işlememiz gerekir.</p>
<p>Yapınızı saf tuttuğunuzda öncelikle kodunuzun okunması çok daha kolay olacaktır. Asenkron cevapların olduğu fonksiyonlar için unit test yazmak oldukça zordur. Saf olmayan reducer kullandığınızda buna bağlı olan değişkenler değiştiğinde DOM üzerinde beklediğiniz güncellemeyi göremeyebilirsiniz. Ayrıca hot-reloading, time-travel gibi yazılım geliştirirken oldukça yararlı olan fonksiyonları devre dışı kalacaktır.</p>
<p>Eğer NodeJS ile Express.JS üzerinde uygulamalar geliştirdiyseniz middleware kavramı sizin için yeni değildir. Middleware Redux'ta da benzer şekilde işliyor. Action yerine function dispatch ettiğinizde middleware devreye giriyor. Redux-thunk'ın kaynak koduna bakarsak bunun nereden geldiğini görebiliriz.</p>
<pre><code class="language-javascript">
function createThunkMiddleware(extraArgument) {
  return ({ dispatch, getState }) => next => action => {
    if (typeof action === 'function') {
      return action(dispatch, getState, extraArgument);
    }

    return next(action);
  };
}

const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;

export default thunk;
</code></pre>
<p>Evet redux-thunk'ın tüm olayı bu 15 satırlık koddan ibaret. Redux'ta dispatch edilen tüm işlemler öncelikle middleware yapısına uğrar. Thunk da bir middleware olduğundan öncelikle gelen action'a bakıyor. Function tipinde bir işlem dispatch edildiğinde devreye giriyor. Thunk'ın ana sayfasında hiç anlayamadığım şu cümleyi ancak kaynak koduna baktıktan sonra anlayabildim:</p>
<blockquote>
<p>Redux Thunk middleware allows you to write action creators that return a function instead of an action.</p>
</blockquote>
<blockquote>
<p>Redux thunk middleware yapısı action yerine fonksiyon dönebilmenizi sağlar.</p>
</blockquote>
<p>İyi de neden fonksiyon dönmemi sağlıyor? Amacım neden fonksiyon döndürmek olsun? Bunun hakkında pek bir şey söylemediğinden kafa karıştırıcı. Aslında fonksiyon dönmek zorunda olmayabilirdik. Middleware o şekilde dizayn edildiği için fonksiyon dönmek zorundayız. Yani tanımı aslında çok kafa karıştırıcı. Ben başka bir middleware yazıp örneğin adı hasan ile başlayan tüm fonksiyonların middleware'i tetiklemesini sağlayabilirdim.</p>
<pre><code class="language-javascript">
if (action.name.startsWith("hasan")) {
      return action(dispatch, getState, extraArgument);
    }
</code></pre>
<p>Bu durumda redux-thunk adı hasan ile başlayan fonksiyonlar dönmenizi sağlayan bir yapıdır mı diyecektim. Neyse absürd bir örnek oldu ancak demek istediğim thunk'ta action yerine fonksiyon dönmemizin tek amacı middleware'e bir nevi sinyal göndermek.</p>
<p>Middleware devreye girdiğinde, Redux kontrolü bir süreliğine middleware'e verecek; middleware asenkron işlemini tamamladığında Redux da tüm veri ağacını güncelleyip React'e gönderecek. Bu şekilde Redux fonksiyonlarımız saf kalacak ve React uygulamamız stabil çalışacak.</p>
<p>Şimdi de ufak bir örnekle thunk'ı nasıl kullanacağımıza bakalım:</p>
<pre><code class="language-javascript">
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers';

const store = createStore(
  rootReducer,
  applyMiddleware(thunk)
);
</code></pre>
<p>Thunk middleware'i reducerlarımızla birlikte Redux'a ilettik.</p>
<pre><code class="language-javascript">
export const asenkronIslem = params => {
  return (dispatch, getState) => {
    fetch('http://example.com').then(
        response => {
            dispatch(senkronIslem(response));
        }
    );
  };
};
</code></pre>
<p>Burada senkron işlem, asenkron isteğin tamamlanmasına bağlı olduğundan öncelikle asenkronIslem'i dispatch etmemiz gerekiyor. Asenkron işlem tamamlandığında gelen cevaba göre istediğimiz senkron işlemi devreye sokabiliriz.</p>
]]></content:encoded></item><item><title><![CDATA[CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün]]></title><description><![CDATA[Ev kullanıcıları için yazıcılara çalıştığınız masada yer ayırmak gerçekten zor iştir. 7 dolarlık bir bilgisayarla eski yazıcınızı kablosuz yazıcıya dönüştürün.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/cups-orange-pi-ile-eski-yazicinizi-kablosuz-ag-yazicisina-donusturun/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb32</guid><category><![CDATA[Orange Pi]]></category><category><![CDATA[Raspberry Pi 3]]></category><category><![CDATA[CUPS]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Fri, 29 Dec 2017 23:04:29 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/12/printserver.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/12/printserver.jpg" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"><p>Ev kullanıcıları için yazıcılara çalıştığınız masada yer ayırmak gerçekten zor iştir. Her zaman ihtiyaç duymadığınız ve en küçüğünün bile yeterince büyük olduğu bir yazıcı için çalıştığınız masada yer ayırmak istemezsiniz. Eğer yeterince şanslıysanız USB kablosunun uzanabildiği yerde uygun bir yer olabilir. Ancak böyle bir alan yoksa Linux yüklü bir OrangePi ile standard yazıcınızı ağ yazıcısına dönüştürüp istediğiniz yerden erişebilirsiniz.</p>
<p>OrangePi modelleri Aliexpress'te 7 dolardan başlayan fiyatlarla bulunuyor. Ben 9 dolar olan 512MB versiyonunu kullandım.</p>
<p>OrangePi'ın kurulumunu ve kablosuz ağa nasıl bağlandığını aşağıdaki yazımda anlatmıştım.</p>
<p><a href="http://cuneyt.aliustaoglu.biz/tr/orange-pi-zero-kurulumu-ve-dinamik-dns-ile-dunyaya-acilmak/">http://cuneyt.aliustaoglu.biz/tr/orange-pi-zero-kurulumu-ve-dinamik-dns-ile-dunyaya-acilmak/</a></p>
<p>Elimizde SSH ile bağlanabileceğimiz Ubuntu yüklü OrangePi var. Şimdi sıra yazıcımızı buna bağlamak ve ağ üzerinde paylaştırmakta. Bunun için CUPS kullacağız.</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/de3492d935300e2904081d3b07a5141be63dd8da/OrangeSSH.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"> OrangePi ile SSH</p>
<p>CUPS (Common UNIX Printing System), Apple'ın geliştirdiği açık kaynak kodlu bir yazıcı yönetim sistemidir diyebiliriz. Sistemimizi hazırlamaya başlayalım:</p>
<p>Öncelikle sistemimizi güncelleyelim ve genel yazıcı sürücülerini yükleyelim. Daha sonra CUPS yazılımını ekleyelim. Burada 2. satırda eklediğimiz yazıcı sürücüleri çoğu yazıcı için çalışacaktır.</p>
<pre><code>sudo apt-get update
sudo apt-get install -y printer-driver-escpr
sudo apt-get install -y cups cups-client cups-common cups-pdf
</code></pre>
<p>SSH ile Orange Pi'a bağlandığımız ekran çıktısına bakarsanız 'login as cuneyt' ile bağlandım. Bu kullanıcı Ubuntu kurarken oluşturduğum admin kullanıcısı. Hangi kullanıcıyla bağlanıyorsak bu kullanıcıya CUPS kullanma yetkisini verelim. Daha sonra yönetici paneline uzaktan erişim yetkisi verelim.</p>
<pre><code>usermod -a -G lpadmin cuneyt 
sudo cupsctl --remote-any
</code></pre>
<p>ve CUPS servisini yeniden başlatalım.</p>
<pre><code>sudo service cups restart
</code></pre>
<p>Yukarıdaki usermod adımları aslında cupsd.conf dosyasınının içeriğini değiştiriyor. Eğer elle ayarlıyorsanız aşağıdaki gibi bir yapıda olması gerekiyor. Eğer yukarıdaki komutları kullanıyorsanız aşağıdaki dosya üzerinde herhangi bir değişiklik yapmanıza gerek yok. Sadece referans olması açısından bırakıyorum:</p>
<pre><code class="language-conf">LogLevel warn
PageLogFormat
MaxLogSize 0
# Allow remote access
Port 631
Listen /var/run/cups/cups.sock
Browsing Off
BrowseLocalProtocols dnssd
DefaultAuthType Basic
WebInterface Yes
&lt;Location /&gt;
  # Allow remote access...
  Order allow,deny
  Allow all
&lt;/Location&gt;
&lt;Location /admin&gt;
&lt;/Location&gt;
&lt;Location /admin/conf&gt;
  AuthType Default
  Require user @SYSTEM
&lt;/Location&gt;
&lt;Location /admin/log&gt;
  AuthType Default
  Require user @SYSTEM
  Order allow,deny
&lt;/Location&gt;
&lt;Policy default&gt;
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default
  &lt;Limit Create-Job Print-Job Print-URI Validate-Job&gt;
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document&gt;
    Require user @OWNER @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default CUPS-Get-Devices&gt;
    AuthType Default
    Require user @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs&gt;
    AuthType Default
    Require user @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Cancel-Job CUPS-Authenticate-Job&gt;
    Require user @OWNER @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit All&gt;
    Order deny,allow
  &lt;/Limit&gt;
&lt;/Policy&gt;
&lt;Policy authenticated&gt;
  JobPrivateAccess default
  JobPrivateValues default
  SubscriptionPrivateAccess default
  SubscriptionPrivateValues default
  &lt;Limit Create-Job Print-Job Print-URI Validate-Job&gt;
    AuthType Default
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document&gt;
    AuthType Default
    Require user @OWNER @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit CUPS-Add-Modify-Printer CUPS-Delete-Printer CUPS-Add-Modify-Class CUPS-Delete-Class CUPS-Set-Default&gt;
    AuthType Default
    Require user @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Pause-Printer Resume-Printer Enable-Printer Disable-Printer Pause-Printer-After-Current-Job Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer Activate-Printer Restart-Printer Shutdown-Printer Startup-Printer Promote-Job Schedule-Job-After Cancel-Jobs CUPS-Accept-Jobs CUPS-Reject-Jobs&gt;
    AuthType Default
    Require user @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit Cancel-Job CUPS-Authenticate-Job&gt;
    AuthType Default
    Require user @OWNER @SYSTEM
    Order deny,allow
  &lt;/Limit&gt;
  &lt;Limit All&gt;
    Order deny,allow
  &lt;/Limit&gt;
&lt;/Policy&gt;
</code></pre>
<p>Orange Pi'a SSH ile bağlanırken kullandığımız adrese (benim için 192.168.1.70) 631 portu üzerinden bağlanıyoruz ve karşımıza CUPS konsolu çıkıyor.</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/823eea4b5aa7f5f9447f368d718486d860930dcc/CUPS.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"> CUPS konsolu</p>
<p>Daha sonra Administration kısmında OrangePi'a bağladığımız yazıcıyı görüyoruz.</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/ca4d32712d07e359f6a2c722245cc8874bd720a1/AddPrinter.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"> CUPS Yönetici Konsolu</p>
<p>Daha sonra devam ettiğimizde 'Share' seçeneğini dahil etmeyi unutmayalım ve ilerleyelim. Model kısmında ben Generic PCL Laser Printer seçeneğini işaretledim ve hiçbir sıkıntı çıkarmadı.</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/a9365a01a1fa9318861ac4906731dedba3a6acad/SharePrinter.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"> CUPS Generic PCL Laser Printer</p>
<p>Yazıcımızı verdiğimiz isme bağlı olarak aşağıdaki aşağıdaki gibi bir adresten görüntüleyebiliriz:</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/11775afe20bbf7749b54ac0ec92747e263f987a7/PrinterInstalled.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"> Yazıcı kurulumu başarılı</p>
<p>Şimdi sıra geldi son adıma. Başka bir odadaki ya da yazıcıya fiziksel olarak bağlı olmayan herhangi bir bilgisayar üzerinden bu yazıcıya nasıl erişeceğiz? Yukarıdaki şekliyle görüntüleyebildiğiniz sayfanın adresini kopyalayın ve &quot;Yazıcı Ekle&quot; kısmına aynen yapıştırın. (https yerine http kullanmanız gerekebilir)</p>
<p><img src="https://gist.githubusercontent.com/aliustaoglu/c222ea1db91658c3996438779bf6eaed/raw/11775afe20bbf7749b54ac0ec92747e263f987a7/YaziciEkle.png" alt="CUPS ve OrangePi ile eski yazıcınızı kablosuz ağ yazıcısına dönüştürün"></p>
<p>OrangePi yerine elbette Raspberry Pi da kullanılabilir ancak Raspberry Pi yalnızca yazıcı sunucusu olarak kullanmak için oldukça pahalı bence. Ancak halihazırda web sunucusu ya da başka bir amaçlı kullanıyorsanız ekstra bir görev daha ekleyebilirsiniz.</p>
]]></content:encoded></item><item><title><![CDATA[NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek]]></title><description><![CDATA[Bu yazıda Arduino IDE dışında bir şeye ihtiyaç duymadan NodeMCU ile internet üzerinden OLED kontrolünün nasıl yapılacağını inceliyoruz.]]></description><link>http://cuneyt.aliustaoglu.biz/tr/nodemcu-ile-oled-ekranini-internet-uzerinden-kontrol-etmek/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb31</guid><category><![CDATA[Yazılım]]></category><category><![CDATA[ESP8266]]></category><category><![CDATA[OLED]]></category><category><![CDATA[NodeMCU]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Mon, 18 Dec 2017 10:15:02 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/12/nodemcu-deneme-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/12/nodemcu-deneme-1.jpg" alt="NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek"><p>NodeMCU, ESP8266-12 versiyonunu kullanan ve nesnelerin programlanmasını sanırım olabilecek en kolay hale getiren bir mikroişlemci. Hakkında pek çok kaynak var o yüzden fazla açıklama yapmayacağım ve direk uygulamaya geçeceğim. Zaten 8266-01'de olduğu gibi programlayıcı yapmamıza gerek yok çünkü NodeMCU'nun kendi üzerinde USB girişi zaten bulunuyor tek yapmak gereken programı yazıp mikroişlemciye yüklemek.</p>
<figure>
<img src="https://gist.githubusercontent.com/aliustaoglu/aa7bdfc8e102095e273a52323ebd711d/raw/ebce8f94ce39544822d75ce1ebf150b204f85078/NodeMCU.jpg" alt="NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek">
<figcaption>NodeMCU ve 128x64 OLED</figcaption>
</figure>
<p>Bu yazıda Arduino IDE'nin, NodeMCU'yu programlayabilecek ayarlarının yapılmış olduğunu varsayıyorum. Eğer değilse <a href="http://cuneyt.aliustaoglu.biz/tr/esp8266webserver-kullanarak-kolay-yolla-web-sunucusu-kurmak/">http://cuneyt.aliustaoglu.biz/tr/esp8266webserver-kullanarak-kolay-yolla-web-sunucusu-kurmak/</a> adresinden &quot;Arduino IDE&quot; kısmına giderek ayarların nasıl yapılacağına bakabilirsiniz.</p>
<h3 id="gereklidonanmlar">Gerekli donanımlar:</h3>
<ul>
<li>NodeMCU ESP8266-12E</li>
<li>128x64 0.96 Inch OLED</li>
</ul>
<figure>
<img src="http://cuneyt-aliustaoglu.s3.amazonaws.com/blog.tr/2017-12-17-NodeMCU-ile-OLED/NodeMCU.jpg" alt="NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek">
<figcaption>NodeMCU ESP8266-12E</figcaption>
</figure>
<figure>
<img src="http://cuneyt-aliustaoglu.s3.amazonaws.com/blog.tr/2017-12-17-NodeMCU-ile-OLED/OLED96.jpg" alt="NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek">
<figcaption>128x64 .96 OLED</figcaption>
</figure>
<br>
Gerekli kütüphaneler yüklendikten sonra NodeMCU ile web sunucusu kurulumu da OLED ekranına yazdırmak da oldukça kolay.
<h3 id="balantemas">Bağlantı Şeması:</h3>
<script src="https://gist.github.com/aliustaoglu/aa7bdfc8e102095e273a52323ebd711d.js?file=Baglanti_bb.png"></script>
<table border="1">
<tbody>
<tr>
<th style="width: 61px;">ESP8266</th>
<th style="width: 44px;">OLED&nbsp;</th>
</tr>
<tr>
<td style="width: 61px;">G</td>
<td style="width: 44px;">&nbsp;GND</td>
</tr>
<tr>
<td style="width: 61px;">3V&nbsp;</td>
<td style="width: 44px;">VCC&nbsp;</td>
</tr>
<tr>
<td style="width: 61px;">D1&nbsp;</td>
<td style="width: 44px;">SDA&nbsp;</td>
</tr>
<tr>
<td style="width: 61px;">D2</td>
<td style="width: 44px;">SCL</td>
</tr>
</tbody>
</table>
<!-- DivTable.com -->
<h3 id="kullanacamzktphaneler">Kullanacağımız kütüphaneler:</h3>
<ul>
<li>ESP8266WebServer.h</li>
<li>SD1306.h</li>
</ul>
<script src="https://gist.github.com/aliustaoglu/aa7bdfc8e102095e273a52323ebd711d.js?file=NodeMCU-OLED-Wifi.ino"></script>
<p>Kodu olabildiğince sade tutmaya çalıştım. İki tane ana işlem var. İlki modülü internete bağlamak, ikincisi ise NodeMCU ile OLED ekranına yazı yazdırmak. Bunları yaptıktan sonra; bu işlemleri birleştirecek, birbiriyle etkileşime sokacak mantığı kurmak gerekiyor.</p>
<p>Kodu biraz açıklayalım. Kod ve bağlantı şemasına ilk baktığımızda bir şeyler yanlış gibi duruyor:</p>
<blockquote>
<p>SSD1306  display(0x3c, 5, 4);</p>
</blockquote>
<p>Bağlantı şemasında OLED'in girişlerini NodeMCU'nun D1, D2 bacaklarına bağladık ama neden <code>display(0x3x,1,2)</code> değil de <code>display(0x3x,5,4)</code> şeklinde kullanma ihtiyacı duyduk. NodeMCU, ESP-8266 tabanlı bir geliştirme kiti. Ayak bağlantıları ESP ile birebir eşleşmiyor. IO1-D1, IO2-D2 şeklinde bir eşleşme bekliyoruz ancak durum bu şekilde değil. Kullandığımız kütüphane NodeMCU'nun ayaklarına göre değil de ESP8266'nın ayaklarına göre düzenlenmiş. Bu düzem şu şekilde:</p>
<pre><code class="language-cpp">static const uint8_t D0   = 16;
static const uint8_t D1   = 5;
static const uint8_t D2   = 4;
static const uint8_t D3   = 0;
static const uint8_t D4   = 2;
static const uint8_t D5   = 14;
static const uint8_t D6   = 12;
static const uint8_t D7   = 13;
static const uint8_t D8   = 15;
static const uint8_t D9   = 3;
static const uint8_t D10  = 1;
</code></pre>
<p>Yani OLED'i D1, D2'ye değil de D4, D5'e bağlamak isteseydik <code>display(0x3x,2,14)</code> şeklinde bir atama yapmamız gerekecekti.</p>
<blockquote>
<p>display.flipScreenVertically();</p>
</blockquote>
<p>Bir tek bana mı öyle geliyor ama OLED ekranına varsayılan ayarlarla yazdırdığınızda yazılar ters basılıyor. Bana göre ekranın üst kısmı pinlerin bulunduğu kısım. O yüzden flip komutuyla ekranın üst kısmını istediğim şekilde ayarladım burada.</p>
<blockquote>
<p>void mesajYaz(String message)</p>
</blockquote>
<p>Burası gönderilen mesajı ekrana basan fonksiyon.</p>
<blockquote>
<p>WiFi.begin(ssid, password);</p>
</blockquote>
<blockquote>
<p>server.on(&quot;/&quot;, ana_sayfa);</p>
</blockquote>
<blockquote>
<p>server.begin()</p>
</blockquote>
<p>kısımlarıyla ise kablosuz ağa bağlanıyor ve ufak bir web sunucusu oluşturuyoruz. Bu sunucumuzun tek bir route'ı var ve kullanıcı bu route'a eriştiğinde ilgili fonksiyonu devreye sokuyoruz. İlgili fonksiyon &quot;mesaj&quot; querystring'ini okuyor ve OLED ekranına bastırıyor.</p>
<p>Denememizi yapalım. İlk önce ağa bağlanan mikroişlemcinin IP adresini bir şekilde edinmemiz gerekiyor. Bunun için Arduino'nun &quot;Serial Monitor&quot; aracını kullanabilir ya da &quot;Advanced Port Scanner&quot; gibi uygulamalarla arama yapabiliriz. Bende 192.168.1.65 adresine bağlandı. Sizde daha farklı bir adres olabilir. Bundan sonra ekran üzerindeki mesajı değiştirmek için tek yapmamız gereken aşağıdaki GET isteğini göndermek ya da tarayıcının adres çubuğuna yazmak.</p>
<p><a href="http://192.168.1.65/?mesaj=iyi%20g%C3%BCnler">http://192.168.1.65/?mesaj=iyi günler</a></p>
<figure>
<img src="https://gist.githubusercontent.com/aliustaoglu/aa7bdfc8e102095e273a52323ebd711d/raw/9bf25f0ae7cd5eab006905773194ff5026e07a6b/nodemcu-deneme2.jpg" alt="NodeMCU ile OLED ekranını Internet üzerinden kontrol etmek">
</figure>
<p>Burada NodeMCU'ya yerel ağ üzerinden eriştik. Ancak router'ınıza gerekli ayarları yaparak evinizdeki OLED'e iş yerinde iken mesaj gönderebilirsiniz. Hatta chat uygulaması bile yapabilirsiniz. Bu ayarların nasıl yapılacağını Orange PI için anlatmıştım. Ancak Orange PI ya da ESP fark etmez ayarlar aynı. Aşağıdaki linkten bu ayarların nasıl yapıldığına bakabilirsiniz.</p>
<p><a href="http://cuneyt.aliustaoglu.biz/tr/orange-pi-zero-kurulumu-ve-dinamik-dns-ile-dunyaya-acilmak/">http://cuneyt.aliustaoglu.biz/tr/orange-pi-zero-kurulumu-ve-dinamik-dns-ile-dunyaya-acilmak/</a></p>
]]></content:encoded></item><item><title><![CDATA[NPM Publish - NPM'e kendi React kütüphanenizi ekleyin]]></title><description><![CDATA[NPM her yazılımcının en çok da full stack yazılımcının sıkılıkla başvurduğu bir kaynak. Artık bu kaynağa ufak da olsa bir katkı yapmamızın zamanı geldi. ]]></description><link>http://cuneyt.aliustaoglu.biz/tr/npm-publish-npme-kendi-react-kutuphanenizi-ekleyin/</link><guid isPermaLink="false">5b4ac401c6a91011ef30eb2e</guid><category><![CDATA[React]]></category><category><![CDATA[Node JS]]></category><category><![CDATA[NPM]]></category><category><![CDATA[Boilerplate]]></category><dc:creator><![CDATA[Cüneyt Aliustaoğlu]]></dc:creator><pubDate>Sun, 12 Nov 2017 08:59:57 GMT</pubDate><media:content url="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/11/react-npm1.png" medium="image"/><content:encoded><![CDATA[<img src="http://cuneyt.aliustaoglu.biz/tr/content/images/2017/11/react-npm1.png" alt="NPM Publish - NPM'e kendi React kütüphanenizi ekleyin"><p>NPM her yazılımcının, en çok da full stack yazılımcının sıkılıkla başvurduğu bir kaynak. Yeterince kullandığımız bu kaynağa artık ufak da olsa bir katkı yapmamızın zamanı geldi. &quot;Neden&quot; üzerinde değil de &quot;Nasıl&quot; üzerinde durmak istiyorum.</p>
<p>Öncelikle <a href="https://www.npmjs.com/">https://www.npmjs.com/</a> üzerinden bir kullanıcı yaratalım. Kullanıcı adımızı da aktifleştirdikten sonra:</p>
<blockquote>
<p>npm adduser</p>
</blockquote>
<p>komutu ile kullanıcı adı ve parolamızı sisteme tanıtalım. Daha sonra boş bir klasör yaratıp bu klasör içinden init komutunu çalıştıralım:</p>
<blockquote>
<p>npm init</p>
</blockquote>
<p>Bu komut, klasör içerisinde ilgili package.json dosyasını yaratacaktır. Aslında yalnızca &quot;package.json&quot; içeren bir klasör başlı başına bir NPM paketidir, ya da daha doğru bir ifade ile Node JS uygulamasıdır. Hemen şimdi:</p>
<blockquote>
<p>npm publish</p>
</blockquote>
<p>komutunu çalıştırarak boş bir NPM modülü yaratabilirsiniz. Tavsiyem bunu 0.0.1 versiyon adıyla yapmanızdır. Unutmayın ki bir kere eklediğiniz NPM paketini artık kaldıramazsınız. NPM 24 saat içinde eklenen paketleri silmeye izin veriyor ancak bu sürenin sonunda NPM'in isteği dışında kendi paketinizi dahi silemezsiniz. Ancak boş NPM modülü yaratıp modül adını rezerve etmek NPM'in şartlarına uymamaktadır. Kısa süre içinde kodunuzu göndermeniz gerekiyor. Ya da kodunuz bitene dek bekleyin eğer o süre içerisinde modül adı alınmış olursa başka bir ad seçebilirsiniz.</p>
<p>Herhangi bir NodeJS uygulamasını eklemek aslında oldukça kolay. Çünkü NPM'in açılımı da zaten Node Paket Yöneticisi. Her Node uygulaması aslında bir NPM paketidir. Ancak ben React kütüphanemi eklemek ve daha sonra başka bir React uygulamasından <code>import</code>komutuyla kullanmak istiyorum. Üstelik ES5 değil ES6 kullanmak istiyorum. O halde Babel ve Webpack ayarları yapmam gerekiyor.</p>
<p>package.json dosyasının bulunduğu klasör üzerinde <code>.babelrc</code> dosyası yaratıp içeriğini aşağıdaki gibi oluşturalım:</p>
<script src="https://gist.github.com/aliustaoglu/9a6ed6005796dc9b602308e22e1de4e8.js?file=.babelrc"></script>
<p>Daha sonra <code>webpack.config.js</code> dosyasını ekleyelim:</p>
<script src="https://gist.github.com/aliustaoglu/9a6ed6005796dc9b602308e22e1de4e8.js?file=webpack.config.js"></script>
<p>Olabilecek en basit React bileşenini de <code>src/index.js</code> konumuna ekleyelim. Çünkü bir önceki webpack ayarında modülün başlangıç noktası olarak burayı seçmiştik.</p>
<script src="https://gist.github.com/aliustaoglu/9a6ed6005796dc9b602308e22e1de4e8.js?file=index.js"></script>
<p>İlk adımda yarattığımız package.json dosyası React ile kullanmak için yeterli bir dosya değil. Bu dosyanın içeriğini aşağıdaki şekilde değiştirelim:</p>
<p><strong>DİKKAT</strong> Aşağıdaki dosya yalnızca örnek olması açısından konulmuştur. name, description, author, repository ve homepage gibi yerleri değiştirmeniz gerekecektir.</p>
<script src="https://gist.github.com/aliustaoglu/9a6ed6005796dc9b602308e22e1de4e8.js?file=package.json"></script>
<p>Şimdi paketimizi npm'e göndermeden önce derlememiz gerekiyor. Çünkü daha önceden de belirttiğim gibi React bileşeni bir Node paketi değil. Webpack'in bunu derlemesi gerekiyor.</p>
<blockquote>
<p>npm run build</p>
</blockquote>
<p>Bu komutu çalıştırdıktan sonra build klasörü ve bu klasörün içinde index.js dosyasının yaratıldığını göreceksiniz. Bunun ayarını webpack.config.js dosyasının 5. ve 6. satırlarında yapmıştık. Ayrıca öbür tarafta package.json dosyasının 5. satırında da bu dosyayı kullanacağımızı belirtmiştik. Dosya içerisine bakarsanız bunun Node paketlerine benzediğini (module.exports = .. şeklinde) göreceksiniz. Artık ilk npm modülümüzü yaratmaya hazırız.</p>
<blockquote>
<p>npm publish</p>
</blockquote>
<p>Bir kere publish ettikten sonra değişiklikler yapmak isterseniz, yeni bir versiyon yaratmanız gerekecektir. package.json dosyasının ilgili yerini güncellemeniz gerekiyor. Örneğin 0.0.2. Versiyon adı ve nasıl çoğaltılacağı sizin takdirinize kalmış.</p>
<p>Bu işleme yazılım dünyasında <code>boilerplate</code> deniyor. Bir uygulamayı çalıştırmak için yapmak gereken minimum ayar. Bu sebeple boilerplate'ler otomasyon için uygundur. Daha da ötesi otomasyon gereklidir. Ben bu boilerplate'i otomatik yapan başka bir npm paketi hazırladım. Yalnız, bu paketi global olarak kullanıyorum (create-react-app gibi).</p>
<p><a href="https://www.npmjs.com/package/create-npm-module">https://www.npmjs.com/package/create-npm-module</a></p>
<p>create-npm-module olarak eklediğim bu modülü aşağıdaki gibi kullanabilirsiniz:</p>
<blockquote>
<ol>
<li>npm install -g create-npm-module</li>
<li>create-npm-module my-awesome-module</li>
<li>cd my-awesome-module</li>
<li>npm install</li>
<li>npm run build</li>
<li>npm publish</li>
</ol>
</blockquote>
<p>Ancak genel olarak tavsiyem bütün boilerplate'leri öncelikle kendiniz elle yapın daha sonra otomasyon kullanın.</p>
<p><strong>Not</strong>: Unutmayın. Eğer publish etmeden önce modülünüzü test etmek isterseniz bir React uygulamasına</p>
<blockquote>
<p>npm install --save C:\benim-npm-modülüm</p>
</blockquote>
<p>şeklinde ekleyip sonuçlarını görebilirsiniz.</p>
]]></content:encoded></item></channel></rss>