Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
KtorでおうちAPIをリプレースした話
Search
yagi2
December 18, 2017
Programming
1
1.1k
KtorでおうちAPIをリプレースした話
2017/12/18 CA.kt #5 @大阪 LT
yagi2
December 18, 2017
Tweet
Share
More Decks by yagi2
See All by yagi2
モバイルアプリエンジニアの生存戦略
yagi2
0
200
Kotlin DSLを理解してみる / Understanding Kotlin DSL
yagi2
4
2.6k
おうちにAPIを生やすお話.pdf
yagi2
0
510
略解 The Navigation Architecture Component
yagi2
1
260
10分で完全に(雰囲気を)理解するマテリアルデザイン
yagi2
1
470
Other Decks in Programming
See All in Programming
LM Linkで(非力な!)ノートPCでローカルLLM
seosoft
0
240
AWS×クラウドネイティブソフトウェア設計 / AWS x Cloud-Native Software Design
nrslib
16
3.4k
おれのAgentic Coding 2026/03
tsukasagr
1
100
Mastering Event Sourcing: Your Parents Holidayed in Yugoslavia
super_marek
0
120
Ruby and LLM Ecosystem 2nd
koic
1
1.3k
GC言語のWasm化とComponent Modelサポートの実践と課題 - Scalaの場合
tanishiking
0
130
Rで始めるML・LLM活用入門
wakamatsu_takumu
0
210
Understanding Apache Lucene - More than just full-text search
spinscale
0
140
RailsのValidatesをSwift Macrosで再現してみた
hokuron
0
130
Agentic AI: Evolution oder Revolution
mobilelarson
PRO
0
190
ファインチューニングせずメインコンペを解く方法
pokutuna
0
190
Nostalgia Meets Technology: Super Mario with TypeScript
manfredsteyer
PRO
0
110
Featured
See All Featured
Mobile First: as difficult as doing things right
swwweet
225
10k
HDC tutorial
michielstock
1
590
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
64
52k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Statistics for Hackers
jakevdp
799
230k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
980
Chasing Engaging Ingredients in Design
codingconduct
0
150
How to build an LLM SEO readiness audit: a practical framework
nmsamuel
1
690
Designing for humans not robots
tammielis
254
26k
How to Ace a Technical Interview
jacobian
281
24k
Designing Powerful Visuals for Engaging Learning
tmiket
0
300
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Transcript
torͰ͓͏ͪAPI ɹΛϦϓϨʔεͨ͠ 2017/12/18 CA.kt #5 @େࡕ Itsuki AOYAGI
͍͋ͭ͝͞ - ࣗݾհ - • ໊લ : ੨༄ थ Itsuki
AOYAGIʢ23ʣ a.k.a ͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
͍͋ͭ͝͞ - ࣗݾհ - • ໊લ : ੨༄ थ Itsuki
AOYAGIʢ23ʣ a.k.a ͗ʹ͍ • AndroidΞϓϦΤϯδχΞ • Kotlinྺ : • Twitter : @yaginier • GitHub etc… : @yagi2 / @yagi21 • ͓͏͍͖ͪͩ͢
͓͏ͪϋοΫͯ͠·͔͢ʁ
͓͏ͪϋοΫ ͓͏ͪΛΑΓշదͳͷʹ͢ΔͨΊʹ ΨδΣοταʔϏεΛΈ߹Θͤͯ ϋοϐʔʹ͢ΔͨΊͷ͋Ε͜Ε ɻ ࠷ۙͩͱεϚʔτεϐʔΧʔ͕͍ͬͺ͍͋ΔͷͰ ͦΕΒܦ༝ͰՈిͱ͔Λૢ࡞Ͱ͖Δɻ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ
͓͏ͪϋοΫ - զ͕Ո - ɾRaspberry Piʢॳʣ ɹˠ ͓͏ͪAPI͕͍͑ͯΔʢPHPʣ ɹɹˠ ϒϥβ͔ΒHTTPSܦ༝ͯ͠ϖʔδ͔Βୟ͘
ɹɹˠ ࣗ࡞ͷAndroidΞϓϦ͔ΒϦΫΤετ Ұྫ ɾࣗͷσεΫτοϓPCͷిݯΛ֎͔ΒೖΕΔ ɾΤΞίϯɺςϨϏͷ֎ઢͰૢ࡞͢ΔՈిͷૢ࡞ ɾϥδΦʢRasPiΛrtmpετϦʔϛϯάͬͯϥδΦʹ͍ͯͨ͠ʣ ͍ͭ͜ΛKotlinʹॻ͖͑Δ
αʔόʔαΠυ Kotlin
αʔόʔαΠυKotlin ɾSpring Boot ɹҎલKotlin + Spring BootͰJSONΛు͘APIΛ࡞ͬͨ͜ͱ͕͋Δ ɹ ͦͷ࣌ͷϒϩά →
KotlinͱSpring BootΛͬͯαΫοͱୟ͚ΔAPIΛ࡞Δ ɾKotr ɹΊͬͪΌബ͍ ɹ ɹKtor is a framework for quickly creating web applications in Kotlin with minimal effort.
Ktor fun main(args: Array<String>) { embeddedServer(Netty, 8080) { routing {
get("/") { call.respondText("Hello, world!", ContentType.Text.Html) } } }.start(wait = true) } ɾബ͗ͯ͢README͕͍ ɹɹɹɹউखͳΠϝʔδ ɹɹɹɹɹɹɹSpringBoot → Ruby on Rails ɹɹɹɹɹɹɹKtor → Sinatra
Ktor - WoL API - KtorΛͬͯɺࣗPCͷిݯΛ֎͔ΒೖΕΔAPIΛॻ͖͢ ݱࡏͷ༷ ɾΫϥΠΞϯτPOSTͰରͷMacΞυϨεΛ͛Δ ɾαʔόʔड͚औͬͨΒͦͷMacΞυϨεʹରͯ͠WoL͢Δ ɹʢexecͰwakeonlanίϚϯυΛୟ͍͍ͯΔʣ
Ktor - WoL API - KtorΛͬͯɺࣗPCͷిݯΛ֎͔ΒೖΕΔAPIΛॻ͖͢ ৽͍༷͠ ɾΫϥΠΞϯτPOSTͰରͷϗετ໊Λ͛Δ ɹˠ ϗετ໊ͦΕʹ४ͣΔͷʢཧ༝ޙड़ʣΛ͛Δ
ɹˠ DBαʔόʔଆͰϗετ໊ͱMacΞυϨεΛ͓͍࣋ͬͯͯࢀর ɾαʔόʔड͚औͬͨΒରʹରͯ͠WoL͢Δ ɹ͔ͤͬ͘ͳͷͰϚδοΫύέοτૹ৴Λ࣮͢Δ
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻ object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } }
Ktor - WoL API - install(Routing) { post("/wol") { val
name = call.receiveParameters()[“name”] val host = ϗετΛDB͔Βݕࡧ(name) if (host == null) { call.respond("ݟ͔ͭΒͳ͔ͬͨ") } else { try { WakeOnLan(host.macAddr).sendMagicPacket() call.respond("ૹͬͨ") } catch (e: IOException) { call.respond("ૹΔͷʹࣦഊͨ͠") } } } ɾPOSTͰड͚औͬͯϚδοΫύέοτΛૹΔ ɹˠ Ͳͷϗετʹରͯ͠ϚδοΫύέοτΛૹΔͷ͔ύϥϝʔλͰ ɹˠ DBʹExposed + MySQLΛ༻
Ktor - WoL API - class WakeOnLan(private val macAddress: String)
{ @Throws(IOException::class) fun sendMagicPacket() { val iNetAddress = InetAddress.getByName("255.255.255.255") val magicPacket = getMagicPacket(macAddress) DatagramSocket().send(DatagramPacket(magicPacket, magicPacket.size, iNetAddress, 8080)) } private fun getMagicPacket(macAddress: String): ByteArray { val packet = ByteArray(102) var index = 0 repeat(6) { packet[index++] = 0xFF.toByte() } val macAddressByte = getMacAddressByte(macAddress) repeat(16) { repeat(6) { packet[index++] = macAddressByte[it] } } return packet } private fun getMacAddressByte(macAddress: String): ByteArray = macAddress.split(":").map { Integer.parseInt(it, 16).toByte() }.toByteArray() }
ʂ ͨ͠ͷͰɺGoogleHome͔Β͑ΔΑ͏ʹ͢Δ
Google Home + IFTTT Google HomeͷԻίϚϯυͰIFTTTͷτϦΨʔΛୟ͍ͯ IFTTTWebHookͰ͓ՈAPIʹPOST͢Δ
Google Home + IFTTT ී௨ʹϓϩάϥϜ͔ΒPOST͢Δͱ͖ $ curl --data-urlencode "name=hoge"
http://api.example.com/wol Google Homeͩͱ”name=hoge”͕ͭΒ͍ ɹˠ ຊޠͰͷΤΠϦΞεΛ͚ͯDBͷΧϥϜʹೖΕ͓ͯ͘ ྫʣʮͶ͐ɺGoogle ͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ɹɹˠ name=͜ͱΓ ɹɹˠ DB͔Βʮ͜ͱΓʯͰҰக͢ΔͷΛݕࡧͯ͠Δ
Google Home + IFTTT object Computers : IntIdTable() { val
hostName = varchar("hostname", 50).index() val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } object Computers : IntIdTable() { val hostName = varchar("hostname", 50).index() val name = varchar("name", 50) val macAddr = varchar("mac_addr", 50) } class Computer(id: EntityID<Int>) : IntEntity(id) { companion object : IntEntityClass<Computer>(Computers) var hostname by Computers.hostName var name by Computers.name var macAddr by Computers.macAddr } fun findByHostName(hostName: String?): Computer? { return transaction { Computer.find { Computers.hostName eq hostName }.firstOrNull() } } fun findByName(name: String?): Computer? { return transaction { Computer.find { Computers.name eq name }.firstOrNull() } }
Google Home + IFTTT transaction { Computer.new { hostname =
"kotori" name = "͜ͱΓ" macAddr = “FF:FF:FF:FF:FF:FF” } } ͓Ոʹ͋ΔϚγϯΛDBʹೖΕͯ͋͛Δɻ $ curl --data-urlencode "name=kotori" http://api.example.com:/wol ʮͶ͐ɺGoogle ͓͏ͪͷ͜ͱΓΛىͯ͜͠ʯ ✨྆ํڞOK✨
Google Home + IFTTT ҙ ʮͶ͐ɺGoogle ͏ͪͷ͜ͻͳͨΛىͯ͜͠ʯ → ͬͯ͘Δ໊લ͕ʮ͜ ͻͳ
ͨʯ ʮͶ͐ɺGoogle ͏ͪͷͪΌͪΌΛىͯ͜͠ʯ → ͬͯ͘Δ໊લ͕ʮʑʯ ղܾࡦ → 1ճࢼͯ͠Կ͕ͬͯ͘Δͷ͔ΛݟΔ
ຊͷ͓͠ͳ͕͖ ɾAPI ɹˠ https://github.com/yagi2/Kaya ɾKtor ɹˠ https://github.com/ktorio/ktor ɾExposed ɹˠ https://github.com/JetBrains/Exposed
Have a Nice Kotlin!