1. Başlamadan önce
Nesnelerin İnterneti (IoT) geliştiricisi olarak, kullanıcılarınıza Google Home uygulamasındaki dokunma kontrolleri ve Asistan'la sesli komutlar aracılığıyla cihazlarını kontrol etme olanağı sunan akıllı ev işlemleri oluşturabilirsiniz.
Akıllı Ev İşlemleri, ev ve cihazları hakkında bağlamsal veriler sağlamak için Ev Grafiği'ni kullanır ve evin mantıksal bir haritasını oluşturur. Bu bağlam, Asistan'ın kullanıcının evdeki konumuna göre isteklerini daha doğal bir şekilde anlamasını sağlar. Örneğin, Home Graph farklı üreticilere ait termostat, lamba, fan ve elektrik süpürgesi gibi çeşitli cihazların bulunduğu bir oturma odası kavramını saklayabilir.
Ön koşullar
- Akıllı ev oluşturma İşlem Geliştirici Kılavuzu
Neler oluşturacaksınız?
Bu codelab'de sanal akıllı çamaşır makinesini yöneten bir bulut hizmeti yayınlayacak, ardından akıllı ev işlemi geliştirip bunu Asistan'a bağlayacaksınız.
Neler öğreneceksiniz?
- Akıllı ev bulut hizmeti dağıtma
- Hizmetinizi Asistan'a bağlama
- Cihaz durumu değişikliklerini Google'da yayınlama
Gerekenler
- Google Chrome gibi bir web tarayıcısı
- Google Home uygulamasının yüklü olduğu bir iOS veya Android cihaz
- Node.js 10.16 veya sonraki sürümler
- Google Cloud faturalandırma hesabı
2. Başlarken
Etkinlik kontrollerini etkinleştirme
Google Asistan'ı kullanabilmek için belirli etkinlik verilerini Google ile paylaşmanız gerekir. Google Asistan'ın düzgün çalışması için bu veriler gerekir; Ancak veri paylaşma zorunluluğu SDK'ya özel değildir. Bu verileri paylaşmak için hesabınız yoksa bir Google Hesabı oluşturun. Geliştirici hesabınız olması gerekmeden istediğiniz Google Hesabını kullanabilirsiniz.
Asistan'la kullanmak istediğiniz Google Hesabı'nın Etkinlik kontrolleri sayfasını açın.
Aşağıdaki açma/kapatma anahtarlarının etkinleştirildiğinden emin olun:
- Web ve Uygulama Etkinliği - Ayrıca, Chrome geçmişini ve Google hizmetlerini kullanan site, uygulama ve cihazlardaki etkinlikleri ekle onay kutusunu işaretlediğinizden emin olun.
- Cihaz Bilgileri
- Ses ve Ses Etkinliği
Actions projesi oluşturma
- Actions on Google Developer Console'a gidin.
- New Project'i (Yeni Proje) tıklayın, proje için bir ad girin ve CREATE PROJECT'yi (PROJE OLUŞTUR) tıklayın.
Akıllı Ev uygulamasını seçin
Actions konsolundaki Genel Bakış ekranında, Akıllı ev'i seçin.
Akıllı ev deneyimi kartını seçip Derlemeyi Başlat'ı tıkladığınızda proje konsolunuza yönlendirilirsiniz.
Firebase CLI'ı yükleme
Firebase Komut Satırı Arayüzü (KSA), web uygulamalarınızı yerel olarak sunmanızı ve web uygulamanızı Firebase barındırmaya dağıtmanızı sağlar.
CLI'yı yüklemek için terminalden aşağıdaki npm komutunu çalıştırın:
npm install -g firebase-tools
CLI'ın düzgün şekilde yüklendiğini doğrulamak için aşağıdaki komutu çalıştırın:
firebase --version
Firebase CLI'ı Google Hesabınızla yetkilendirin. Bunun için şu komutu çalıştırın:
firebase login
3. Başlangıç uygulamasını çalıştırma
Geliştirme ortamınızı ayarladığınıza göre artık her şeyin düzgün bir şekilde yapılandırıldığını doğrulamak için başlangıç projesini dağıtabilirsiniz.
Kaynak kodunu alma
Bu codelab'in örneğini geliştirme makinenize indirmek için şu bağlantıyı tıklayın:
veya GitHub deposunu komut satırından klonlayabilirsiniz:
git clone https://github.com/google-home/smarthome-washer.git
Proje hakkında
Başlangıç projesi aşağıdaki alt dizinleri içerir:
public:
Akıllı çamaşır makinesinin durumunu kolayca kontrol edip izlemeyi sağlayan bir ön uç kullanıcı arayüzü.functions:
Akıllı çamaşır makinesini Firebase için Cloud Functions ve Firebase Realtime Database ile yöneten, eksiksiz bir bulut hizmeti.
Firebase'e bağlanma
washer-start
dizinine gidin ve ardından Actions projenizle Firebase CLI'ı ayarlayın:
cd washer-start firebase use <project-id>
Firebase projesini yapılandırın
Bir Firebase projesini başlatın.
firebase init
CLI özelliklerini seçin, Realtime Database, Functions ve Firebase Hosting'i içeren Hosting (Barındırma) özelliğini seçin.
? Which Firebase CLI features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices. ❯◉ Realtime Database: Configure a security rules file for Realtime Database and (optionally) provision default instance ◯ Firestore: Configure security rules and indexes files for Firestore ◉ Functions: Configure a Cloud Functions directory and its files ◉ Hosting: Configure files for Firebase Hosting and (optionally) set up GitHub Action deploys ◯ Hosting: Set up GitHub Action deploys ◯ Storage: Configure a security rules file for Cloud Storage ◯ Emulators: Set up local emulators for Firebase products ◯ Remote Config: Configure a template file for Remote Config ◯ Extensions: Set up an empty Extensions manifest
Bu, projeniz için gerekli API'leri ve özellikleri kullanıma hazırlayacaktır.
İstendiğinde Realtime Database'i başlatın. Veritabanı örneği için varsayılan konumu kullanabilirsiniz.
? It seems like you haven't initialized Realtime Database in your project yet. Do you want to set it up? Yes ? Please choose the location for your default Realtime Database instance: us-central1
Başlangıç proje kodunu kullandığınızdan, Güvenlik kuralları için varsayılan dosyayı seçin ve mevcut veritabanı kuralları dosyasının üzerine yazmadığınızdan emin olun.
? File database.rules.json already exists. Do you want to overwrite it with the Realtime Database Security Rules for <project-ID>-default-rtdb from the Firebase Console? No
Projenizi yeniden başlatıyorsanız bir kod tabanını başlatmak mı yoksa üzerine yazmak mı istediğiniz sorulduğunda Üzerine yaz'ı seçin.
? Would you like to initialize a new codebase, or overwrite an existing one? Overwrite
Functions'ınızı yapılandırırken varsayılan dosyaları kullanmanız ve proje örneğindeki mevcut index.js ve package.json dosyalarının üzerine yazmadığınızdan emin olmanız gerekir.
? What language would you like to use to write Cloud Functions? JavaScript ? Do you want to use ESLint to catch probable bugs and enforce style? No ? File functions/package.json already exists. Overwrite? No ? File functions/index.js already exists. Overwrite? No
Projenizi yeniden başlatıyorsanız işlevleri/.gitignore işlevini başlatmak mı yoksa üzerine yazmak mı istediğiniz sorulduğunda Hayır'ı seçin.
? File functions/.gitignore already exists. Overwrite? No
? Do you want to install dependencies with npm now? Yes
Son olarak, proje kodunda public
dizinini kullanmak için Hosting kurulumunuzu yapılandırın ve mevcut index.html dosyasını kullanın. ESLint kullanmanız istendiğinde Hayır'ı seçin.
? What do you want to use as your public directory? public ? Configure as a single-page app (rewrite all urls to /index.html)? Yes ? Set up automatic builds and deploys with GitHub? No ? File public/index.html already exists. Overwrite? No
ESLint yanlışlıkla etkinleştirildiyse bunu devre dışı bırakmak için iki yöntem vardır:
- GUI'yi kullanarak projenin altındaki
../functions
klasörüne gidin, gizli.eslintrc.js
dosyasını seçin ve silin. Bunu, benzer isimli.eslintrc.json
ile karıştırmayın. - Komut satırını kullanarak:
cd functions rm .eslintrc.js
Doğru ve eksiksiz bir Firebase yapılandırmasına sahip olduğunuzdan emin olmak için firebase.json
dosyasını washer-done
dizininden washer-start
dizinine kopyalayıp washer-start
dizinindeki dosyanın üzerine yazın.
washer-start
dizininde:
cp -vp ../washer-done/firebase.json .
Firebase'e dağıtma
Bağımlılıkları yüklediğinize ve projenizi yapılandırdığınıza göre uygulamayı ilk kez çalıştırmaya hazırsınız.
firebase deploy
Görmeniz gereken konsol çıkışı şudur:
... ✔ Deploy complete! Project Console: https://console.firebase.google.com/project/<project-id>/overview Hosting URL: https://<project-id>.web.app
Bu komut, çeşitli Firebase için Cloud Functions işleviyle birlikte bir web uygulaması dağıtır.
Web uygulamasını görüntülemek için tarayıcınızda (https://<project-id>.web.app
) Barındırma URL'sini açın. Şu arayüzü göreceksiniz:
Bu web kullanıcı arayüzü, cihaz durumlarını görüntülemek veya değiştirmek için kullanılan bir üçüncü taraf platformu temsil eder. Veritabanınızı cihaz bilgileriyle doldurmaya başlamak için GÜNCELLE'yi tıklayın. Sayfada herhangi bir değişiklik görmezsiniz ancak çamaşır makinenizin mevcut durumu veritabanında saklanır.
Şimdi, dağıttığınız bulut hizmetini Actions Console'u kullanarak Google Asistan'a bağlama zamanı.
Actions konsolu projenizi yapılandırma
Genel Bakış > İşleminizi oluşturun, İşlem Ekle'yi seçin. Akıllı ev amaçları için karşılama sağlayan bulut işlevinizin URL'sini girin ve Kaydet'i tıklayın.
https://us-central1-<project-id>.cloudfunctions.net/smarthome
Geliştirme > Çağrı sekmesinde, işleminiz için bir Görünen Ad ekleyin ve Kaydet'i tıklayın. Bu ad Google Home uygulamasında görünecek.
Hesap bağlama özelliğini etkinleştirmek için Geliştir > Hesap bağlama seçeneğini tıklayın. Şu hesap bağlama ayarlarını kullanın:
İstemci Kimliği |
|
İstemci gizli anahtarı |
|
Yetkilendirme URL'si |
|
Jeton URL'si |
|
Hesap bağlama yapılandırmanızı kaydetmek için Kaydet'i ve projenizde testi etkinleştirmek için Test'i tıklayın.
Simulator'a yönlendirilirsiniz. "Test şimdi etkin" seçeneğini görmüyorsanız testin etkinleştirildiğini doğrulamak için Testi Sıfırla'yı tıklayın.
Artık cihaz durumunu Asistan'a bağlamak için gereken webhook'ları uygulamaya başlayabilirsiniz.
4. Çamaşır makinesi oluşturma
İşleminizi yapılandırdığınıza göre artık cihaz ekleyebilir ve veri gönderebilirsiniz. Bulut hizmetinizin aşağıdaki amaçları işlemesi gerekir:
- Asistan, kullanıcının hangi cihazları bağladığını öğrenmek istediğinde
SYNC
niyeti ortaya çıkar. Bu mesaj, kullanıcı bir hesap bağladığında hizmetinize gönderilir. Tüm kullanıcının cihazlarının ve yeteneklerinin JSON yüküyle yanıt vermelisiniz. - Asistan bir cihazın mevcut durumunu veya durumunu öğrenmek istediğinde
QUERY
niyeti ortaya çıkar. İstenen her cihazın durumunu içeren bir JSON yüküyle yanıt vermeniz gerekir. - Asistan, bir cihazı kullanıcı adına kontrol etmek istediğinde
EXECUTE
niyeti ortaya çıkar. İstenen her cihazın yürütme durumunu içeren bir JSON yüküyle yanıt vermeniz gerekir. - Kullanıcı, hesabının Asistan'la bağlantısını kaldırdığında
DISCONNECT
intent'i gerçekleşir. Bu kullanıcının cihazlarıyla ilgili etkinliklerin Asistan'a gönderilmesini durdurmalısınız.
Bu amaçları işlemek için daha önce dağıttığınız işlevleri aşağıdaki bölümlerde güncelleyeceksiniz.
SENKRONİZASYON yanıtını güncelle
Asistan'dan gelen isteklere yanıt vermek için kullanılacak kodu içeren functions/index.js
uygulamasını açın.
Cihaz meta verilerini ve özelliklerini döndürerek bir SYNC
niyetini işlemeniz gerekir. onSync
dizisindeki JSON dosyasını, giysi yıkama makinesi için cihaz bilgilerini ve önerilen özellikleri içerecek şekilde güncelleyin.
index.js
app.onSync((body) => {
return {
requestId: body.requestId,
payload: {
agentUserId: USER_ID,
devices: [{
id: 'washer',
type: 'action.devices.types.WASHER',
traits: [
'action.devices.traits.OnOff',
'action.devices.traits.StartStop',
'action.devices.traits.RunCycle',
],
name: {
defaultNames: ['My Washer'],
name: 'Washer',
nicknames: ['Washer'],
},
deviceInfo: {
manufacturer: 'Acme Co',
model: 'acme-washer',
hwVersion: '1.0',
swVersion: '1.0.1',
},
willReportState: true,
attributes: {
pausable: true,
},
}],
},
};
});
Firebase'e dağıtma
Güncellenen bulut karşılama hizmetini Firebase CLI kullanarak dağıtın:
firebase deploy --only functions
Google Asistan'a bağlama
Akıllı ev işleminizi test etmek için projenizi bir Google Hesabı'na bağlamanız gerekir. Bu şekilde, aynı hesapta oturum açmış olan Google Asistan yüzeyleri ve Google Home uygulaması üzerinden test yapabilirsiniz.
- Telefonunuzda Google Asistan ayarlarını açın. Konsoldaki hesapla aynı hesapla giriş yapmanız gerektiğini unutmayın.
- Google Asistan > Ayarlar > Ev Kontrolü'ne (Asistan'ın altında) gidin.
- Sağ üstteki arama simgesini tıklayın.
- İlgili test uygulamanızı bulmak için [test] önekini kullanarak test uygulamanızı arayın.
- İlgili öğeyi seçin. Google Asistan, hizmetinizle kimlik doğrular ve
SYNC
isteği göndererek hizmetinizden kullanıcı için cihazların listesini sağlamasını ister.
Google Home uygulamasını açın ve çamaşır makinesi cihazınızı görebildiğinizi doğrulayın.
5. Komutları ve sorguları işleme
Bulut hizmetiniz, çamaşır makinesi cihazını Google'a doğru şekilde bildirdiğine göre artık cihaz durumunu isteme ve komut gönderme özelliğini eklemeniz gerekir.
QUERY amacını işleme
QUERY
amacı, bir cihaz grubu içerir. Her cihaz için o anki durumuyla yanıt vermeniz gerekir.
functions/index.js
içinde, QUERY
işleyicisini, intent isteğinde yer alan hedef cihazların listesini işleyecek şekilde düzenleyin.
index.js
app.onQuery(async (body) => {
const {requestId} = body;
const payload = {
devices: {},
};
const queryPromises = [];
const intent = body.inputs[0];
for (const device of intent.payload.devices) {
const deviceId = device.id;
queryPromises.push(queryDevice(deviceId)
.then((data) => {
// Add response to device payload
payload.devices[deviceId] = data;
}
));
}
// Wait for all promises to resolve
await Promise.all(queryPromises);
return {
requestId: requestId,
payload: payload,
};
});
İstekte yer alan her cihaz için Realtime Database'de depolanan mevcut durumu döndürün. Çamaşır makinesinin durum verilerini döndürmek için queryFirebase
ve queryDevice
işlevlerini güncelleyin.
index.js
const queryFirebase = async (deviceId) => {
const snapshot = await firebaseRef.child(deviceId).once('value');
const snapshotVal = snapshot.val();
return {
on: snapshotVal.OnOff.on,
isPaused: snapshotVal.StartStop.isPaused,
isRunning: snapshotVal.StartStop.isRunning,
};
};
const queryDevice = async (deviceId) => {
const data = await queryFirebase(deviceId);
return {
on: data.on,
isPaused: data.isPaused,
isRunning: data.isRunning,
currentRunCycle: [{
currentCycle: 'rinse',
nextCycle: 'spin',
lang: 'en',
}],
currentTotalRemainingTime: 1212,
currentCycleRemainingTime: 301,
};
};
YÜRÜTME amacını işleme
EXECUTE
intent, cihaz durumunu güncelleme komutlarını işler. Yanıt, her komutun durumunu (örneğin, SUCCESS
, ERROR
veya PENDING
) ve yeni cihaz durumunu döndürür.
functions/index.js
ürününde, güncelleme gerektiren özelliklerin listesini ve her komut için hedef cihaz grubunu işlemek üzere EXECUTE
işleyicisini düzenleyin:
index.js
app.onExecute(async (body) => {
const {requestId} = body;
// Execution results are grouped by status
const result = {
ids: [],
status: 'SUCCESS',
states: {
online: true,
},
};
const executePromises = [];
const intent = body.inputs[0];
for (const command of intent.payload.commands) {
for (const device of command.devices) {
for (const execution of command.execution) {
executePromises.push(
updateDevice(execution, device.id)
.then((data) => {
result.ids.push(device.id);
Object.assign(result.states, data);
})
.catch(() => functions.logger.error('EXECUTE', device.id)));
}
}
}
await Promise.all(executePromises);
return {
requestId: requestId,
payload: {
commands: [result],
},
};
});
Her bir komut ve hedef cihaz için Realtime Database'de istenen özelliğe karşılık gelen değerleri güncelleyin. updateDevice
işlevini değiştirerek uygun Firebase referansını güncelleyin ve güncellenmiş cihaz durumunu döndürün.
index.js
const updateDevice = async (execution, deviceId) => {
const {params, command} = execution;
let state; let ref;
switch (command) {
case 'action.devices.commands.OnOff':
state = {on: params.on};
ref = firebaseRef.child(deviceId).child('OnOff');
break;
case 'action.devices.commands.StartStop':
state = params.start
? {isRunning: true, isPaused: false}
: {isRunning: false, isPaused: false};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
case 'action.devices.commands.PauseUnpause':
const data = await queryDevice(deviceId);
state = (data.isPaused === false && data.isRunning === false)
? {isRunning: false, isPaused: false}
: {isRunning: !params.pause, isPaused: params.pause};
ref = firebaseRef.child(deviceId).child('StartStop');
break;
}
return ref.update(state)
.then(() => state);
};
6. İşleminizi test etme
Üç amacı da uyguladıktan sonra İşleminizin çamaşır makinesini kontrol edip etmediğini test edebilirsiniz.
Firebase'e dağıtma
Güncellenen bulut karşılama hizmetini Firebase CLI kullanarak dağıtın:
firebase deploy --only functions
Çamaşır makinesini test etme
Artık telefonunuzda aşağıdaki sesli komutlardan herhangi birini denediğinizde değerin değiştiğini görebilirsiniz:
"Ok Google, çamaşır makinemi aç."
"Ok Google, çamaşır makinemi duraklat."
"Ok Google, çamaşır makinemi durdur."
Ayrıca, sorular sorarak çamaşır makinenizin mevcut durumunu da öğrenebilirsiniz.
"Ok Google, çamaşır makinem açık mı?"
"Ok Google, çamaşır makinem çalışıyor mu?"
"Ok Google, çamaşır makinem hangi döngüde?"
Bu sorguları ve komutları, Firebase Konsolu'nun İşlevler bölümünde, işlevinizin altında görünen günlüklerde görüntüleyebilirsiniz. Firebase günlükleri hakkında daha fazla bilgi edinmek için Günlükleri yazma ve görüntüleme başlıklı makaleyi inceleyin.
Bu sorguları ve komutları Google Cloud Console'da Günlük > Günlük Gezgini. Google Cloud günlük kaydı hakkında daha fazla bilgi için Cloud Logging ile etkinlik günlüklerine erişme başlıklı makaleyi inceleyin.
7. Güncellemeleri Google'a bildirin
Bulut hizmetinizi akıllı ev amaçlarıyla tamamen entegre ettiniz. Böylece kullanıcılar, cihazlarının mevcut durumunu kontrol edip sorgulayabilecek. Ancak uygulamada, hizmetinizin, cihazın varlığı veya durumunda yapılan değişiklikler gibi etkinlik bilgilerini proaktif olarak Asistan'a göndermesi mümkün değildir.
Senkronizasyon İsteğinde, kullanıcılar cihaz eklediğinde veya kaldırdığında ya da cihaz özellikleri değiştiğinde yeni bir senkronizasyon isteğini tetikleyebilirsiniz. Rapor Durumu sayesinde bulut hizmetiniz, kullanıcılar fiziksel olarak bir cihaz durumunu değiştirdiğinde (ör. bir ışık anahtarını açtığında) veya başka bir hizmeti kullanarak durumu değiştirdiğinde cihazın durumunu proaktif olarak Home Graph'e gönderebilir.
Bu bölümde, ön uç web uygulamasından bu yöntemleri çağırmak için kod ekleyeceksiniz.
HomeGraph API'yi etkinleştirme
HomeGraph API, cihazların ve cihaz durumlarının kullanıcının Home Graph'inde depolanmasını ve sorgulanmasını sağlar. Bu API'yi kullanmak için önce Google Cloud konsolunu açıp HomeGraph API'yi etkinleştirmeniz gerekir.
Google Cloud konsolunda İşlemlerinizle eşleşen projeyi seçtiğinizden emin olun <project-id>.
Ardından HomeGraph API'nin API Kitaplığı ekranında Etkinleştir'i tıklayın.
Rapor Durumunu Etkinleştir
Realtime Database'e yazma işlemleri, başlangıç projesindeki reportstate
işlevini tetikler. Veritabanına yazılan verileri yakalamak ve bunları Rapor Durumu aracılığıyla Home Graph'te yayınlamak için functions/index.js
ürününde reportstate
işlevini güncelleyin.
index.js
exports.reportstate = functions.database.ref('{deviceId}').onWrite(
async (change, context) => {
functions.logger.info('Firebase write event triggered Report State');
const snapshot = change.after.val();
const requestBody = {
requestId: 'ff36a3cc', /* Any unique ID */
agentUserId: USER_ID,
payload: {
devices: {
states: {
/* Report the current state of our washer */
[context.params.deviceId]: {
on: snapshot.OnOff.on,
isPaused: snapshot.StartStop.isPaused,
isRunning: snapshot.StartStop.isRunning,
},
},
},
},
};
const res = await homegraph.devices.reportStateAndNotification({
requestBody,
});
functions.logger.info('Report state response:', res.status, res.data);
});
Senkronizasyon İsteğini Etkinleştir
Ön uç web kullanıcı arayüzündeki simgenin yenilenmesi, başlangıç projesinde requestsync
işlevini tetikler. HomeGraph API'yi çağırmak için functions/index.js
ürününde requestsync
işlevini uygulayın.
index.js
exports.requestsync = functions.https.onRequest(async (request, response) => {
response.set('Access-Control-Allow-Origin', '*');
functions.logger.info(`Request SYNC for user ${USER_ID}`);
try {
const res = await homegraph.devices.requestSync({
requestBody: {
agentUserId: USER_ID,
},
});
functions.logger.info('Request sync response:', res.status, res.data);
response.json(res.data);
} catch (err) {
functions.logger.error(err);
response.status(500).send(`Error requesting sync: ${err}`);
}
});
Firebase'e dağıtma
Güncellenen kodu Firebase CLI'yı kullanarak dağıtın:
firebase deploy --only functions
Uygulamanızı test etme
Web kullanıcı arayüzünde Yenile düğmesini tıklayın ve Firebase konsol günlüğünde bir senkronizasyon isteği gördüğünüzden emin olun.
Ardından, ön uç web kullanıcı arayüzünde çamaşır makinesi cihazının özelliklerini düzenleyip Güncelle'yi tıklayın. Firebase konsolu günlüklerinizde Google'a bildirilen durum değişikliğini görebildiğinizi doğrulayın.
8. Tebrikler
Tebrikler! Akıllı ev İşlemleri'ni kullanarak Asistan'ı cihaz bulut hizmetiyle başarıyla entegre ettiniz.
Daha fazla bilgi
Daha ayrıntılı bilgi edinmek için uygulayabileceğiniz bazı fikirler:
- Cihazınıza mod ve geçiş düğmesi ekleyin.
- Cihazınıza desteklenen daha fazla özellik ekleyin.
- Akıllı ev için yerel yürütmeyi keşfedin.
- Daha fazla bilgi edinmek için GitHub örneğimize göz atın.
İşleminizi kullanıcılara yayınlamak için sertifika süreci de dahil olmak üzere bir İşlemi test etme ve incelemeye gönderme hakkında daha fazla bilgi edinebilirsiniz.